JSubelj / g910-gkey-macro-support

GKey support for Logitech G910 Keyboard on Linux
GNU General Public License v3.0
99 stars 30 forks source link

[Bug] No such file or directory ("hotkey_type": "run") #13

Closed Rihoj closed 1 year ago

Rihoj commented 5 years ago

I am trying to run a bash script with custom parameters as a Gkey. The command config is:

"g1": {
        "hotkey_type": "run",
        "do": "/home/james/bin/fivestar -k'"
    },

I can not give you this script, however you can see the same error running this:

"g1": {
        "hotkey_type": "run",
        "do": "/bin/bash echo 'hello world'"
    },

When trying to press the key I get

2019-05-02 17:53:41,968 [INFO] {lib.functionalities.gkey_functionality} - g1 pressed, running: /bin/bash echo 'hello world'
2019-05-02 17:53:41,972 [ERROR] {lib.g910_gkey_mapper} - ERROR:[Errno 2] No such file or directory: "/bin/bash echo 'hello world'": "/bin/bash echo 'hello world'"

Any help would be greatly appreciated. Thank you.

JSubelj commented 5 years ago

Hey,

first I have to say, thank you for using my driver. I didn't really put a lot of effort into run hotkey_type, because of many reasons I summarized here: Why can't I run graphic programs by default.

That being said I think there is currently a problem with line 20 in gkey_functionality.py. The problem is that it expects a one off command like "firefox" and does not work correctly for commands with spaces inside. To correct this I think replacing:

subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

with:

import shlex
subprocess.Popen(shlex.split(command), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

would do the trick. Please try this out (I currently can't because I don't have the keyboard with me) and report on the result.

If the changed code does not work please report the error it throws out. In the mean time you can assign the G1 key to press a shortcut and then assign the shortcut to the script you want to run in your desktop environment.

You should also be wary that when running the driver with a service manager like systemd, all scripts executed with a run command will be run as a super user with elevated privileges. This can expose a potential security threat, because the driver is running even before you log in and someone can exploit this behavior (like changing the script to rm -rf /) and potential bugs inside your script can break your system because they are run with sudo privileges.

If you need any help please ask and I will gladly try to help you.

denialofsandwich commented 5 years ago

I got it working. In line 20, you pass the command arguments as a string, but it requires an array (An element for each parameter).

This fixed it for me:

process = subprocess.Popen(['bash', '-c', command], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

Nice work btw. :+1:

PS: Is it currently possible to map the M1-R Keys as well? Because I want to implement a recording function for the gkeys.

Edit: Now I can even start graphical Programs with it (This example starts firefox):

su username -c 'DISPLAY=:0 nohup firefox' & 2>&1 > /dev/null
JSubelj commented 5 years ago

Nice. Have you maybe tried this:

import shlex
subprocess.Popen(shlex.split(command), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

About the MKeys there is already an issue opened here: https://github.com/JSubelj/g910-gkey-macro-support/issues/14

If you just want to build a recording function you can just add a function here: gkey_functionality.py and then call it from emitKeys function here: g910_gkey_mapper.

If you do implement this please, when you'r done, open a pull request. I will be ethereally grateful.

If you need any help I'm available here or by email (jan(dot)subelj010(at)gmail(dot)com).

denialofsandwich commented 5 years ago

Yes. I tried using shlex. But it treats pipes and redirection-operators as regular parameters.

I'm currently using the "run" hotkey_type to send a signal so my python-script, which does further handling, because I want it to interact with the key colors. But I will notify you, as soon as I made it work.

hbregalad commented 4 years ago

I didn't notice this was already an open issue until I'd already submitted a pull request with my choice: subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True) Which works great for my desired string: "mate-terminal --window --maximize -e top --tab -e 'tail -n 24 -f /var/log/g910-gkeys.log' --tab -e 'nano /etc/g910-gkeys/config.json'"

Which is I think should be vaguely the same functionality under the hood as: subprocess.Popen(['bash', '-c', command], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

Are either of these solution considered more secure or more stable than the other?

suabo commented 2 years ago

This information needs to go to the readme:

Edit: Now I can even start graphical Programs with it (This example starts firefox):

su username -c 'DISPLAY=:0 nohup firefox' & 2>&1 > /dev/null

Thx to @denialofsandwich

This is my new setup to launch my fav apps:

    "g6": {
        "hotkey_type": "run",
        "do": "su marcel -c 'DISPLAY=:0 nohup terminator' & 2>&1 > /dev/null"
    },
    "g7": {
        "hotkey_type": "run",
        "do": "su marcel -c 'DISPLAY=:0 nohup firefox' & 2>&1 > /dev/null"
    },
    "g8": {
        "hotkey_type": "run",
        "do": "su marcel -c 'DISPLAY=:0 nohup thunderbird' & 2>&1 > /dev/null"
    },
    "g9": {
        "hotkey_type": "run",
        "do": "su marcel -c 'DISPLAY=:0 nohup phpstorm' & 2>&1 > /dev/null"
    }

After adding the info how to start graphical programms to the readme this bug could be closed i think. I'm glad i came here.

suabo commented 1 year ago

Are either of these solution considered more secure or more stable than the other?

You can read the security considerations here. Basically if you turn shell=True better use shelx.quote() to be sure.

braoult commented 1 year ago
"g6": {
    "hotkey_type": "run",
    "do": "su marcel -c 'DISPLAY=:0 nohup terminator' & 2>&1 > /dev/null"
},

To do this, without playing with "su" and potential security issues regarding root, I would rather map the key to a F-key, and have the F-key configured at the user level (for example in window manager) to run the command. When I see more and more functionalities added to a root program (such as running python code, or run commands), I feel very uncomfortable. The G-keys become dangerous bombs, when they should be simply just new keys in same user context as other keys like F1.

suabo commented 1 year ago

The G-keys become dangerous bombs, when they should be simply just new keys in same user context as other keys like F1.

I disagree on this. The Gkeys should be programmable macro keys like in the windows driver. Everybody can decide which commands to run with run or python hotkey_type or can just simply map their keys to some not used F keys with the shortcut type. You don't need to make use of the other hotkey_types if you don't feel good about it.

In fact using su to execute a command as user instead of root makes no potential security issues. I'd say it's more save then running commands without it.

I kind of agree with you that running the service as root is maybe not the best solution. Maybe we should look into a way to run the service as a dedicated user or the installing user. But since you need advanced rights to access usb and udev I couldn't figure something out. Maybe you can come up with something?

braoult commented 1 year ago

I disagree on this. The Gkeys should be programmable macro keys like in the windows driver.

I don't know how it works on Windows (is it user specific configuration ? Because our run type surely is not).

Everybody can decide which commands to run with run or python hotkey_type or can just simply map their keys to some not used F keys with the shortcut type. You don't need to make use of the other hotkey_types if you don't feel good about it.

Not everybody: root only can do that. There is a huge difference between a "run" command, with or without su and the mapping to another key : The keys are always active with the "run" type, even if nobody is logged in, logged in as another user, if the screen is locked, or even when the user is switched to another one (the first session still being active): In the first 2 cases the program will be launched but will fail (the DISPLAY does not exist), but will be successful in the 2 other cases (screen locked or user switched).

For example, if my G1 is configured to run xterm with your method, and if I lock the screen, if I press G1 and unlock the screen, a new xterm will be there. Even worse: If my session is locked, and my wife switches to her account (as my session is still active, she will get a new display, like :1.0), then presses G1, an xterm will be opened on my session !

This is not the case when the G-key is mapped to a F-key, which itself is managed by the user settings (for example to run your firefox command): Nothing would happen when not logged-in, screen-locked, or switched to another user (I mean really nothing, no launch of firefox which could be successful or fail), which is (for me) the basic we can expect on a machine.

In fact using su to execute a command as user instead of root makes no potential security issues. I'd say it's more save then running commands without it.

But less safe than avoiding the run command itself and let the user use his own "run command" within his session. Much less flexible too. We simply add something dangerous with less functionality than the system offers natively (the possibility for any user to manage his own keys within his session, globally or per application).

I kind of agree with you that running the service as root is maybe not the best solution. Maybe we should look into a way to run the service as a dedicated user or the installing user. But since you need advanced rights to access usb and udev I couldn't figure something out. Maybe you can come up with something?

No idea. My feeling is that, if we need the service running as root, we should simply limit as much as possible the code run as root, and give the keys the same functionalities as any other key, no "super power". For me, running "su" is super-power.

If we absolutely want to keep the run capability, maybe we could split the service in two : One root service which accesses the hardware (gets the key), and one user service which would do everything that can be done without being root (this would include the "run" action). The communication between them could be anything (D-Bus, socket, etc...). I am unsure how/if this could work, and how we should handle 2 users on 2 different X servers (the switch example above).

Note: My config for G1 is :

"g1": {
        "hotkey_type": "shortcut",
        "do": "F13"
}

And I activate the Emacs window within my keyboard setting : F13 runs wmctrl -F -a "GNU Emacs". My wife's account F13 launches LibreOffice. She has exactly the same feature as your own configuration (launching a program), with no root involved, no side effect, and working even if DISPLAY is not :0.0. The difference with your configuration is that the key is inactive when it should. IMHO, if you decide to keep the run capability, these side effects should be clearly explained, and alternative solutions (when they exist, as for your configuration example) should be proposed and stated as preferable.

suabo commented 1 year ago

There is a huge difference between a "run" command, with or without su and the mapping to another key : The keys are always active with the "run" type, even if nobody is logged in, logged in as another user, if the screen is locked, or even when the user is switched to another one (the first session still being active): In the first 2 cases the program will be launched but will fail (the DISPLAY does not exist), but will be successful in the 2 other cases (screen locked or user switched).

I didn't even thought about that. But don't you agree that a multi user setup is probably not the most common out there and therefore and because the driver don't really supports it right now you are bound to your setup. You got the same limitations if you use the run type with another command someone would use not being on a multi user setup in described situations. I can't think of any example right now, but i hope you get the point.

If we absolutely want to keep the run capability, maybe we could split the service in two : One root service which accesses the hardware (gets the key), and one user service which would do everything that can be done without being root (this would include the "run" action). The communication between them could be anything (D-Bus, socket, etc...). I am unsure how/if this could work, and how we should handle 2 users on 2 different X servers (the switch example above).

I did a lot of researching on pyusb today and there is a part in the faq explaining how to deal with access rights with usb on linux: How to practically deal with permission issues on Linux? I would be happy if we could run the service on a user base and have real multi user config. You got a nice Workaround for using a multi user setup without the need of a individual config.

My wife's account F13 launches LibreOffice. She has exactly the same feature as your own configuration (launching a program), with no root involved, no side effect, and working even if DISPLAY is not :0.0.

I just thought that a lot of people are interested in launching a program with the gkey. This is just an easy way without all the catches described in the wiki and without the need to setup some other configs and shortcuts to keep track of.

IMHO, if you decide to keep the run capability, these side effects should be clearly explained, and alternative solutions (when they exist, as for your configuration example) should be proposed and stated as preferable.

I want to keep the run hotkey_type, but want to direct my time into getting some other things done. I would be happy if you could make an How to multi user setup for the wiki pages and describe how your setup works and how to set it up and maybe you can suggest some changes to the readme so everybody is happy.

Please open a new issue if you do so. This issue originated from another problem and is only low key related. Maybe you can mention this issue in the new one.

braoult commented 1 year ago

I would be happy if you could make an How to multi user setup for the wiki pages and describe how your setup works and how to set it up and maybe you can suggest some changes to the readme so everybody is happy.

This is not only for multi-user setup... Using F-key mapping, we do not need any system-wide change (g910-gkeys configuration file + daemon restart) to setup a program to run, or change it. This is a pure user setup, accessible via menus in Applications Menu/Settings/Keyboard/Application Shortcuts (this is for Xubuntu, the menu could be somewhere else for different variants).

Please open a new issue if you do so. This issue originated from another problem and is only low key related. Maybe you can mention this issue in the new one.

Sure, I will try. I cannot do anything the next two days, I will have a look from this week-end...