Commit 69f594a38967f4540ce7a29b3fd214e68a8330bd

Authored by Eric Paris
1 parent f1c84dae0e

ptrace: do not audit capability check when outputing /proc/pid/stat

Reading /proc/pid/stat of another process checks if one has ptrace permissions
on that process.  If one does have permissions it outputs some data about the
process which might have security and attack implications.  If the current
task does not have ptrace permissions the read still works, but those fields
are filled with inocuous (0) values.  Since this check and a subsequent denial
is not a violation of the security policy we should not audit such denials.

This can be quite useful to removing ptrace broadly across a system without
flooding the logs when ps is run or something which harmlessly walks proc.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Serge E. Hallyn <serge.hallyn@canonical.com>

Showing 4 changed files with 15 additions and 6 deletions Side-by-side Diff

... ... @@ -380,7 +380,7 @@
380 380  
381 381 state = *get_task_state(task);
382 382 vsize = eip = esp = 0;
383   - permitted = ptrace_may_access(task, PTRACE_MODE_READ);
  383 + permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
384 384 mm = get_task_mm(task);
385 385 if (mm) {
386 386 vsize = task_vsize(mm);
include/linux/ptrace.h
... ... @@ -127,8 +127,9 @@
127 127 struct task_struct *new_parent);
128 128 extern void __ptrace_unlink(struct task_struct *child);
129 129 extern void exit_ptrace(struct task_struct *tracer);
130   -#define PTRACE_MODE_READ 1
131   -#define PTRACE_MODE_ATTACH 2
  130 +#define PTRACE_MODE_READ 0x01
  131 +#define PTRACE_MODE_ATTACH 0x02
  132 +#define PTRACE_MODE_NOAUDIT 0x04
132 133 /* Returns 0 on success, -errno on denial. */
133 134 extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
134 135 /* Returns true on success, false on denial. */
... ... @@ -161,6 +161,14 @@
161 161 return ret;
162 162 }
163 163  
  164 +static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
  165 +{
  166 + if (mode & PTRACE_MODE_NOAUDIT)
  167 + return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
  168 + else
  169 + return has_ns_capability(current, ns, CAP_SYS_PTRACE);
  170 +}
  171 +
164 172 int __ptrace_may_access(struct task_struct *task, unsigned int mode)
165 173 {
166 174 const struct cred *cred = current_cred(), *tcred;
... ... @@ -187,7 +195,7 @@
187 195 cred->gid == tcred->sgid &&
188 196 cred->gid == tcred->gid))
189 197 goto ok;
190   - if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE))
  198 + if (ptrace_has_cap(tcred->user->user_ns, mode))
191 199 goto ok;
192 200 rcu_read_unlock();
193 201 return -EPERM;
... ... @@ -196,7 +204,7 @@
196 204 smp_rmb();
197 205 if (task->mm)
198 206 dumpable = get_dumpable(task->mm);
199   - if (!dumpable && !ns_capable(task_user_ns(task), CAP_SYS_PTRACE))
  207 + if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode))
200 208 return -EPERM;
201 209  
202 210 return security_ptrace_access_check(task, mode);
security/selinux/hooks.c
... ... @@ -1809,7 +1809,7 @@
1809 1809 if (rc)
1810 1810 return rc;
1811 1811  
1812   - if (mode == PTRACE_MODE_READ) {
  1812 + if (mode & PTRACE_MODE_READ) {
1813 1813 u32 sid = current_sid();
1814 1814 u32 csid = task_sid(child);
1815 1815 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);