Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Shell commands in cmd-button are run by root/privileged user #426

Open
MuhammedZakir opened this issue Nov 17, 2021 · 27 comments
Open
Labels
bug Something isn't working

Comments

@MuhammedZakir
Copy link
Contributor

Currently, if kmonad is run using sudo, shell commands in cmd-button are run by root/privileged/admin user. IMHO, this is a serious issue. I always thought shell commands were run as current user.

Simple example:

  1. Mape a button to
(cmd-button "echo $USER")
  1. Run KMonad using sudo kmonad -ctrue <config>
  2. root will be printed.

FWIW, in Linux, if you configure KMonad to run without sudo, then this won't happen.

@slotThe
Copy link
Member

slotThe commented Nov 17, 2021

cmd-button essentially just opens a shell and runs the given command there—I thought we were pretty explicit that it's i) dangerous and ii) a bad idea to run kmonad as root anyways. However, I do think that running commands as the current user is prety much a net-win for everyone. I believe we would just need to change child_user in the definition of spawnCommand for that; would you like to give this a try?

@molleweide
Copy link

fyi this does not work T34 (cmd-button "sudo zsh -c \'yabai -m space --layout stack\'")

@MuhammedZakir
Copy link
Contributor Author

MuhammedZakir commented Nov 17, 2021

cmd-button essentially just opens a shell and runs the given command there—I thought we were pretty explicit that it's i) dangerous

I understood it as running shell commands per se is not dangerous, but rather it depends on the commands being run.

and ii) a bad idea to run kmonad as root anyways.

The problem is that there is no other option in Mac (afaik).

However, I do think that running commands as the current user is prety much a net-win for everyone. I believe we would just need to change child_user in the definition of spawnCommand for that; would you like to give this a try?

From doc:

Use posix setuid to set child process's user id; does nothing on other platforms.

Will this work for Mac and Windows?

@slotThe
Copy link
Member

slotThe commented Nov 17, 2021

I understood it as running shell commands per se is not dangerous, but rather it depends on the commands being run.

Well, running shell commands as root is not dangerious per se either, but I do take your point.

and ii) a bad idea to run kmonad as root anyways.

The problem is that there is no other option in Mac (afaik).

Oh. Well that's not good :)

From doc:

Use posix setuid to set child process's user id; does nothing on other platforms.

Will this work for Mac and Windows?

I believe "other" here refers to "non posix" platforms, so I would assume it works on Mac but not on Windows

@MuhammedZakir
Copy link
Contributor Author

MuhammedZakir commented Nov 17, 2021

I believe "other" here refers to "non posix" platforms, so I would assume it works on Mac but not on Windows

Okay, then I will post here after testing. Btw, if KMonad is run as root, how can we get the userID of "current user"? :-D

@slotThe
Copy link
Member

slotThe commented Nov 17, 2021 via email

@molleweide
Copy link

Lol

@molleweide
Copy link

molleweide commented Nov 17, 2021

Hey would it be possible to pass the userid to kmonad with a flag when initiating kmonad?

@molleweide
Copy link

molleweide commented Nov 17, 2021

could one of these be the answer
https://www.unix.com/shell-programming-and-scripting/152400-unix-user-logname-environment-variables.html
https://www.unix.com/shell-programming-and-scripting/147411-how-can-i-get-user-id-root.html

according to second link this might work:

id -u $USER

and according to the first link there is a variable $LOGNAME that might work also if there are multiple users on a system.

@MuhammedZakir
Copy link
Contributor Author

MuhammedZakir commented Nov 18, 2021

Hey would it be possible to pass the userid to kmonad with a flag when initiating kmonad?

It's possible, but I don't want to add that unless it's the only way or if there is a particular reason for it.


@molleweide: What is the output of echo logname=$(logname) -- if you execute it from KMonad?

@molleweide
Copy link

are you sure it should be small letters?

@molleweide
Copy link

it returns root

@molleweide
Copy link

this returns 0:

  T34 (cmd-button "echo xxx=$(id -u $USER)")

@MuhammedZakir
Copy link
Contributor Author

MuhammedZakir commented Nov 18, 2021

In Linux, logname returns the current user's name even when run as sudo. What about echo $SUDO_USER?

this returns 0:

0 is UID of root.

@molleweide
Copy link

I'll report back when i come home!

@molleweide
Copy link

sudo_user also returns 0.

@MuhammedZakir
Copy link
Contributor Author

MuhammedZakir commented Nov 21, 2021

In Mac, who and in Linux, logname return correct username.


@slotThe: I hardcoded my userID in shellCmd function in src/KMonad/App/Types.hs (master branch). It's working in Linux, but not in Mac. Setting it did do something as I am getting this error if I don't run KMonad using sudo.

kmonad: /bin/sh: spawnCommand: initgroups: permission denied (Operation not permitted)

Edit: You'll also have to run KMonad with sudo in Linux. Otherwise I am getting this error when executing command

kmonad: /bin/sh: spawnCommand: initgroups: does not exist (No child processes)

This means we can't run KMonad without sudo if you want to use shell commands. :-(

@MuhammedZakir
Copy link
Contributor Author

It looks like the simplest (and reliable) solution is to wrap the shell command in sudo -u <user> sh -c '<command>'. As you can guess, we will have to do some escapings to make it work. If we don't want to do that, tell users that commands are run as root and to wrap the commands themself?

There is probably a better way, but I don't know.

@molleweide
Copy link

I hardcoded my userID in shellCmd function in src/KMonad/App/Types.hs

lol do you think this would be possible to do also in a bash function.

@MuhammedZakir
Copy link
Contributor Author

I hardcoded the userID there for testing only.

@molleweide: I told you to wait in the thread about Yabai. But this is more complicated than I thought and may take some time before fixing. In the meantime, you can use sudo -u <current_username> bash -lc '<shell commands>'.

@molleweide
Copy link

molleweide commented Nov 22, 2021

Allright cool! Just tell me if there is anything you want me to test for you and I'll try to help.

EDIT

I confirm that sudo -u <current_username> bash -lc '<shell commands>' works for me fyi.

@slotThe
Copy link
Member

slotThe commented Nov 22, 2021

This means we can't run KMonad without sudo if you want to use shell commands. :-(

Well that's not good :/

I don't think forcing sudo for everyone is the right solution; it works fine as-is right now on GNU/Linux systems and it would be a shame if we had to give that up

@MuhammedZakir
Copy link
Contributor Author

MuhammedZakir commented Nov 22, 2021

For wrapping code with minimal work (from KMonad's side), rather the one I posted above, I think heredoc is better.

E.g. For the shell command -- "yabai -m space --layout stack", KMonad will internally transnform that to

sudo -u <username> /bin/sh -l <<'_KMonad_Shell_Command_EOF_'
<shell commands>
_KMonad_Shell_Command_EOF_

Note: We will need to quote the eof-marker(?) to avoid shell interpretation of the content in heredoc.

If we are going to do this way, we could also let user decide the shell (and shell's cli args) to which we pass the user's original commands - the one after sudo -u <username>, not the internally translated command - which will always be executed by sh.


This means we can't run KMonad without sudo if you want to use shell commands. :-(

Well that's not good :/

I don't think forcing sudo for everyone is the right solution; it works fine as-is right now on GNU/Linux systems and it would be a shame if we had to give that up

Exactly. That's why I don't like that solution. What do you think about wrapping them in heredoc (quoted variant) and executing* that using sh (or user-provided shell)?

* by passing shell commands to be executed via STDIN using heredoc.

@molleweide
Copy link

Hey guys, do you know if it is possible to use variables in .kbd files.

My thinking is that until this has been solved, which might take a while, maybe one could add, eg. sudo -u <current_username> bash -lc \' to a variable and then concatenate it into each command string just so I don't have to write the full sudo prefix for each command.

@molleweide
Copy link

molleweide commented Dec 14, 2021

I have an additional question / proposal:

From what I understand a new shell process is started for each command? Is this correct?

Would it be possible to have a single running background shell process that kmonad owns to which one can submit all of
ones commands so that each command is run without a delay?

This would make sense with layouts that grow in size and that use lots of cmd buttons and also when it comes to functionality like mouse pointer.

I don't know if this is a good idea but I add it here in case you have not thought about this. Personally I am kind of moving away from regular OS key bindings to mapping most things to cmd buttons because then I can move stuff away into layers that I won't accidentally trigger but also because of real estate reasons. In the end I would describe the way I use kmonad as a complex vim-style leader tree and I am trying to map all keys to OS cross-compatible cmd-buttons.

@molleweide
Copy link

Hi guys,

I just wanted to check on this issue and see if there has been any progress made lately?

@ulcuber
Copy link

ulcuber commented Aug 18, 2023

For OpenRC

/etc/init.d/kmonad

command_user=username

See:
https://wiki.gentoo.org/wiki/OpenRC/User_services

slotThe added a commit that referenced this issue Oct 7, 2023
Notable changes:

- Added `around-next-single`, a variant of `around-next` that will
  release its context on any change, as opposed to only on the release
  of the 'arounded' button.
- Added default compose sequence for Ü
- Added a `sticky-key`
- Added `--version` (`-V`) flag
- Added `+,` for  "add a cedilla"
- Added `:timeout-button` keyword to `tap-hold-next` and
  `tap-hold-next-release`, so that they can switch to a button
  other than the hold button when the timeout expires.
- The `multi-tap` key now immediately taps the current key when another
  key is pressed during tapping.
- Fixed compilation error under Mac, having to do with typo in Keycodes.
- Fixed issue with empty-names for uinput-sinks.
- Ignore SIGCHLD to deal with non-termination bug.

---

This should probably be 0.5, but notable issues like [1..6] still
preventing me from being comfortable with that. None of these seem
completely insurmountable, though, so stay tuned :)

[1]: #475
[2]: #704
[3]: #681
[4]: #716
[5]: #516
[6]: #426
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants