如果用户不是 root,为什么使用 hidepid=2 时,仅具有执行权限的二进制进程仍隐藏在“ps”中?

如果用户不是 root,为什么使用 hidepid=2 时,仅具有执行权限的二进制进程仍隐藏在“ps”中?

我使用 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 }

相关内容