legionus / kbd

Mirror of https://git.kernel.org/pub/scm/linux/kernel/git/legion/kbd.git
https://kbd-project.org
Other
84 stars 41 forks source link

question about command execution privileges #108

Closed JJ-Meng closed 8 months ago

JJ-Meng commented 8 months ago

When using dumpkeys, fgconsole, kbdinfo, kbd_mode, showkey, setkeycodes, getkeycodes commands, I always get a error message

“Couldn't get a file descriptor referring to the console.”

Then I use strace to trace what happened when these commands are called. I find that they all try to open tty related files, which as a normal user I am not authorized to access. So I think it might be a permissions issue.

I'm not sure if these keyboard and console related information are that sensitive, but if I switch to root, there is no error and it works fine.

So I would like to ask how other people use these commands, do I need to switch to root or use sudo every time?

legionus commented 8 months ago

Most utilities require root privileges for modifications. The message you provide means that the utility was unable to find an available tty device file at least for reading. Typically the user has access to some tty.

Here is an example of strace from my machine from a regular user using a terminal emulator:

$ strace -e trace=%file src/kbdinfo getmode
execve("src/kbdinfo", ["src/kbdinfo", "getmode"], 0x7fff0a8e4038 /* 77 vars */) = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=74670, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "/usr/lib64/libxkbcommon.so.0", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=289320, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "/usr/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=1892440, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=224335824, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2998, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "/usr/local/share/locale/C.UTF8/LC_MESSAGES/kbd.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/share/locale/C.utf8/LC_MESSAGES/kbd.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/share/locale/C/LC_MESSAGES/kbd.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/proc/self/fd/0", O_RDWR) = 3
openat(AT_FDCWD, "/dev/tty", O_RDWR)    = 3
openat(AT_FDCWD, "/dev/tty0", O_RDWR)   = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/tty0", O_WRONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/tty0", O_RDONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/vc/0", O_RDWR)   = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/vc/0", O_WRONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/vc/0", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/systty", O_RDWR) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/systty", O_WRONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/systty", O_RDONLY) = 3
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x10), ...}, AT_EMPTY_PATH) = 0
graphics
+++ exited with 0 +++

As you can see, the device was eventually found.

JJ-Meng commented 8 months ago

Most utilities require root privileges for modifications.

Okay, I got it. Thanks.

Interestingly, when I run kbdinfo getmode with normal user permissions, I can't find an available tty.

openat(AT_FDCWD, "/proc/self/fd/0", O_RDWR) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/proc/self/fd/0", O_WRONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/proc/self/fd/0", O_RDONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/tty", O_RDWR)    = 3
ioctl(3, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(3, KDGKBTYPE, 0x7ffcace2dbd7)     = -1 ENOTTY (Inappropriate ioctl for device)
close(3)                                = 0
openat(AT_FDCWD, "/dev/tty0", O_RDWR)   = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/tty0", O_WRONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/tty0", O_RDONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/vc/0", O_RDWR)   = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/vc/0", O_WRONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/vc/0", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/systty", O_RDWR) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/systty", O_WRONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/systty", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/dev/console", O_RDWR) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/console", O_WRONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/console", O_RDONLY) = -1 EACCES (Permission denied)
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, KDGKBTYPE, 0x7ffcace2dbd7)     = -1 ENOTTY (Inappropriate ioctl for device)
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, KDGKBTYPE, 0x7ffcace2dbd7)     = -1 ENOTTY (Inappropriate ioctl for device)
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, KDGKBTYPE, 0x7ffcace2dbd7)     = -1 ENOTTY (Inappropriate ioctl for device)
write(2, "Couldn't get a file descriptor r"..., 56) = 56
write(2, "\n", 1)                       = 1
exit_group(1)                           = ?
+++ exited with 1 +++

I guess I'll use root to execute these commands.

And I also have a backup plan. Considering that these "Permission denied" are actually caused by accessing to special files, I've granted CAP_DAC_OVERRIDE (a capability to bypass the filesystem checks) to kbdinfo in advance, then it works fine every time.

$ sudo setcap cap_dac_override+ep /usr/bin/kbdinfo

$ kbdinfo getmode
text
legionus commented 8 months ago

Interestingly, when I run kbdinfo getmode with normal user permissions, I can't find an available tty.

openat(AT_FDCWD, "/proc/self/fd/0", O_RDWR) = -1 EACCES (Permission denied) openat(AT_FDCWD, "/proc/self/fd/0", O_WRONLY) = -1 EACCES (Permission denied) openat(AT_FDCWD, "/proc/self/fd/0", O_RDONLY) = -1 EACCES (Permission denied) ... ioctl(0, KDGKBTYPE, 0x7ffcace2dbd7) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(1, KDGKBTYPE, 0x7ffcace2dbd7) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, KDGKBTYPE, 0x7ffcace2dbd7) = -1 ENOTTY (Inappropriate ioctl for device)

It means that where you run strace the stdin is not readable or writable and is not a terminal.

I guess I'll use root to execute these commands.

In this case, the utility will be able to open /dev/tty0 for example. Yes, it will work.