sudo 之后 /dev/stderr 上的权限被拒绝

sudo 之后 /dev/stderr 上的权限被拒绝

我经常使用此命令在我的开发虚拟机中切换用户:

✸ sudo su - otheruser

但是,如果我尝试访问/dev/stderr或类似操作,我会遇到麻烦:

otheruser$ echo hi > /dev/stderr
-bash: /dev/stderr: Permission denied

我知道我可以>&2在这个特定实例中使用它,但在某些情况下(例如tee /dev/stderr)您需要一个可打开的文件,而不仅仅是一个文件描述符。

我发现我可以在 sudo 之前在 tty 上打开写权限来解决这个问题:

✸ ls -ld /dev/stderr
lrwxrwxrwx 1 root root 15 Jan 13 08:06 /dev/stderr -> /proc/self/fd/2
✸ ls -ld /proc/self/fd/2
lrwx------ 1 aron aron 64 Jan 14 15:08 /proc/self/fd/2 -> /dev/pts/13
✸ ls -ld /dev/pts/13
crw--w---- 1 aron tty 136, 13 Jan 14 15:08 /dev/pts/13
✸ chmod a+w /dev/pts/13

或者更简单地说:

✸ chmod a+w /dev/stderr

但我想知道我是否应该使用其他调用,以便正确分配和/或授予权限。有什么建议吗?

答案1

这是 Linux 实现 /proc 的一个已知怪癖;从未修复多年来。在 Linux 中,打开下面的链接/proc/*/fd/*不会像 dup() 那样直接复制文件描述符(尽管神奇的 /proc 链接可以理论上实现这一点)——相反,它会重新打开文件,并执行新的权限检查。

您发现的最基本的解决方法是在使用su或之前授予目标用户对您的 tty 的权限sudo。例如:

userA$  setfacl -m u:userB:rw /dev/stderr
userA$  sudo -i -u userB

(也许可以编写一个具有同样功能的 PAM 模块。)

一个可能更好的解决方法是使用用户切换方法,为你提供一个全新的 tty——su --pty如果你有 su 的 util-linux 版本,那么就有这样的工具。Systemd 有一个systemd-run工具可以运行临时服务交互地;同样,它带有一个machinectl shell主要用于容器的工具,但最近的版本还有“环回”模式:

userA$  sudo su -l -P userB

userA$  sudo systemd-run --uid=userB --shell --quiet --collect

userA$  sudo machinectl shell userB@

你也可以得到与使用相同的结果终端多路复用器例如 Screen 或 tmux,它们必须为其窗口/窗格分配新的 tty:

userA$  sudo -u userB tmux

所有这些工具都会为嵌套会话分配一个新的 pty,在双方之间中继所有输入/输出。

相关内容