Commit 69f594a3 authored by Eric Paris's avatar Eric Paris

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: default avatarEric Paris <eparis@redhat.com>
Acked-by: default avatarSerge E. Hallyn <serge.hallyn@canonical.com>
parent f1c84dae
...@@ -380,7 +380,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, ...@@ -380,7 +380,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
state = *get_task_state(task); state = *get_task_state(task);
vsize = eip = esp = 0; vsize = eip = esp = 0;
permitted = ptrace_may_access(task, PTRACE_MODE_READ); permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
mm = get_task_mm(task); mm = get_task_mm(task);
if (mm) { if (mm) {
vsize = task_vsize(mm); vsize = task_vsize(mm);
......
...@@ -127,8 +127,9 @@ extern void __ptrace_link(struct task_struct *child, ...@@ -127,8 +127,9 @@ extern void __ptrace_link(struct task_struct *child,
struct task_struct *new_parent); struct task_struct *new_parent);
extern void __ptrace_unlink(struct task_struct *child); extern void __ptrace_unlink(struct task_struct *child);
extern void exit_ptrace(struct task_struct *tracer); extern void exit_ptrace(struct task_struct *tracer);
#define PTRACE_MODE_READ 1 #define PTRACE_MODE_READ 0x01
#define PTRACE_MODE_ATTACH 2 #define PTRACE_MODE_ATTACH 0x02
#define PTRACE_MODE_NOAUDIT 0x04
/* Returns 0 on success, -errno on denial. */ /* Returns 0 on success, -errno on denial. */
extern int __ptrace_may_access(struct task_struct *task, unsigned int mode); extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
/* Returns true on success, false on denial. */ /* Returns true on success, false on denial. */
......
...@@ -161,6 +161,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state) ...@@ -161,6 +161,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state)
return ret; return ret;
} }
static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
{
if (mode & PTRACE_MODE_NOAUDIT)
return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
else
return has_ns_capability(current, ns, CAP_SYS_PTRACE);
}
int __ptrace_may_access(struct task_struct *task, unsigned int mode) int __ptrace_may_access(struct task_struct *task, unsigned int mode)
{ {
const struct cred *cred = current_cred(), *tcred; const struct cred *cred = current_cred(), *tcred;
...@@ -187,7 +195,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) ...@@ -187,7 +195,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
cred->gid == tcred->sgid && cred->gid == tcred->sgid &&
cred->gid == tcred->gid)) cred->gid == tcred->gid))
goto ok; goto ok;
if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE)) if (ptrace_has_cap(tcred->user->user_ns, mode))
goto ok; goto ok;
rcu_read_unlock(); rcu_read_unlock();
return -EPERM; return -EPERM;
...@@ -196,7 +204,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) ...@@ -196,7 +204,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
smp_rmb(); smp_rmb();
if (task->mm) if (task->mm)
dumpable = get_dumpable(task->mm); dumpable = get_dumpable(task->mm);
if (!dumpable && !ns_capable(task_user_ns(task), CAP_SYS_PTRACE)) if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode))
return -EPERM; return -EPERM;
return security_ptrace_access_check(task, mode); return security_ptrace_access_check(task, mode);
......
...@@ -1809,7 +1809,7 @@ static int selinux_ptrace_access_check(struct task_struct *child, ...@@ -1809,7 +1809,7 @@ static int selinux_ptrace_access_check(struct task_struct *child,
if (rc) if (rc)
return rc; return rc;
if (mode == PTRACE_MODE_READ) { if (mode & PTRACE_MODE_READ) {
u32 sid = current_sid(); u32 sid = current_sid();
u32 csid = task_sid(child); u32 csid = task_sid(child);
return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment