我使用 hidepid=2 来挂载 /proc,因此用户只能看到自己的进程。我想要使用的特定二进制文件已被限制为 rwx--x--x 权限,因此只有其所有者(root)可以读取它,但其他用户可以执行它。普通用户可以毫无问题地运行它,但无法用“ps”看到进程。如果二进制文件的权限已更改,以便用户可以读取它,则该进程将再次出现在“ps”中。
一个可重现的例子:
sudo mount -o remount,hidepid=2 /proc
sudo cp $(which yes) /tmp
sudo chmod 0711 /tmp/yes
/tmp/yes >/dev/null &
ps aux | grep yes # The process is hidden
sudo ps aux | grep yes # The process can be seen by root
kill %1
sudo chmod og+r /tmp/yes
/tmp/yes >/dev/null &
ps aux | grep yes # The process appears in the list
为什么会发生这种情况?它显然与文件权限有一些关系,但它不应该有:如果进程属于用户,即使二进制文件受到限制,用户也应该能够看到它。
我的猜测是,由于 /proc/PID 中的链接“exe”指向正在执行的二进制文件,因此除了二进制文件本身之外,内核还禁止对该目录的所有访问。但我想知道这是真的还是只是其他事情发生的结果。
提前致谢!
答案1
答案是(或者至少开始) 在fs/proc/base.c
(至少从内核 3.12 到 4.2 没有变化)
742 static int proc_pid_permission(struct inode *inode, int mask)
743 {
744 struct pid_namespace *pid = inode->i_sb->s_fs_info;
745 struct task_struct *task;
746 bool has_perms;
747
748 task = get_proc_task(inode);
749 if (!task)
750 return -ESRCH;
751 has_perms = has_pid_permissions(pid, task, 1);
752 put_task_struct(task);
753
754 if (!has_perms) {
755 if (pid->hide_pid == 2) {
756 /*
757 * Let's make getdents(), stat(), and open()
758 * consistent with each other. If a process
759 * may not stat() a file, it shouldn't be seen
760 * in procfs at all.
761 */
762 return -ENOENT;
763 }
764
765 return -EPERM;
766 }
767 return generic_permission(inode, mask);
768 }
/proc/PID
上面的代码是确定特定条目是否存在的起点。当hide_pid
设置为 2时-ENOENT
,如果您没有所需的权限,则会返回。权限通过以下方式检查:
has_pid_permissions()
→
ptrace_may_access()
→
__ptrace_may_access()
__ptrace_may_access()
拒绝访问,因为该进程不可“转储”,因为它是从不可读的可执行映像创建的,如进程创建期间确定的:
setup_new_exec()
→
would_dump()
1118 void would_dump(struct linux_binprm *bprm, struct file *file)
1119 {
1120 if (inode_permission(file_inode(file), MAY_READ) < 0)
1121 bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
1122 }