4

I'm using hidepid=2 to mount /proc, so users can't see any but their own processes. A particular binary I want to use has been restricted to rwx--x--x permissions, so only its owner (root) can read it but other users can execute it. A normal user can run it without problems, but can't see the process with "ps". If the binary has its permissions changed so the user can read it, then the process appears in "ps" again.

A reproducible example:

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

Why is this happening? It obviously has some relationship to the file permissions, but it shouldn't have: if the process belongs to a user, the user should be able to see it even if the binary is restricted.

My guess is that, as the link "exe" inside /proc/PID points to the binary being executed, the kernel is forbidding all access the the directory in addition to the binary itself. But I'd like to know if this is true or just a consequence of some other thing going on.

Thanks in advance!

6
  • Nope. Can't reproduce. Both pgrep and ps aux show the process just fine. Arch Linux, kernel: 4.1.6-1-ARCH. I compared with pgrep -u lightdm to test if the mount option was applied.
    – muru
    Sep 24, 2015 at 12:50
  • The kernel version may be the reason. I'm using Ubuntu 14.04, with 3.13.0. I'll try with another kernel version to see what happens. Thanks!
    – rsuarez
    Sep 24, 2015 at 15:27
  • Funny: I've downloaded an ArchLinux vagrant box, with a 4.1.2 kernel, and the same happens. The user can't see his process when the binary has no read permissions. Sorry to be suspicious, @muru, but are you sure you can't reproduce this issue?
    – rsuarez
    Sep 24, 2015 at 15:42
  • Dammit, I'd forgotten the sudo while copying. Yep, I can confirm now. Interestingly, this also happens if the program is owned by me and I don't have read permission. :D
    – muru
    Sep 24, 2015 at 18:04
  • @rsuarez, Could you explain why would you want to restrict read permissions on a binary executable for your users? Sep 28, 2015 at 10:03

1 Answer 1

4
+50

The answer is (or at least starts) in fs/proc/base.c (unchanged from kernel 3.12 to 4.2 at least)

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 }

The code above is the starting point for determining if a specific /proc/PID entry can been seen to exist or not. When hide_pid is set to 2 it returns -ENOENT if you don't have the required permission. Permissions are checked via:

has_pid_permissions()ptrace_may_access()__ptrace_may_access()

__ptrace_may_access() denies access because the process is not "dumpable" as it was created from an unreadable executable image, as determined during process creation:

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 }
1
  • 1
    Great explanation. Thanks, I'm marking this as the right answer.
    – rsuarez
    Oct 1, 2015 at 14:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .