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 }
According to what proc(5)
has to say on /proc/[pid]/io
, _"Permission to access this file is governed by a ptrace access mode TRACE_MODE_READ_FSCREDS check; see ptrace(2)."_ The Ptrace access mode checking section of the ptrace(2)
man page contains a list of things that are checked to grant or deny permission, including whether the process is marked dumpable, whether you have the same fsuid as the target process etc, might be worth it having a look at it.
The documentation was added very recently, check upstream.
I suspect you need to change the GID your process is running under, in addition to the UID.
Best Answer
I came across this issue yesterday and found two methods:
1. Sudoers
Add a rule allowing the command access without a password.
Replacing username:
Some downsides include auth log pollution, especially if checking signal every few seconds, as well as the need to add
sudo
to these scripts.2. Capabilities
Give the binary
CAP_NET_ADMIN
+
to add and-
to removeMore info at
man cap_from_text
Disclaimer:
CAP_NET_ADMIN
is a form of elevated privilege. Allowing harm to things like network configuration and firewalls. In my case I only need it forgrep
used in an i3 blocklet. I am not sure myself what the risk is in this case and would appreciate commentary.