diff options
| -rw-r--r-- | fs/proc/array.c | 2 | ||||
| -rw-r--r-- | include/linux/ptrace.h | 5 | ||||
| -rw-r--r-- | kernel/ptrace.c | 12 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 2 |
4 files changed, 15 insertions, 6 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index 3a1dafd228d1..ddffd7a88b97 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
| @@ -380,7 +380,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, | |||
| 380 | 380 | ||
| 381 | state = *get_task_state(task); | 381 | state = *get_task_state(task); |
| 382 | vsize = eip = esp = 0; | 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 | mm = get_task_mm(task); | 384 | mm = get_task_mm(task); |
| 385 | if (mm) { | 385 | if (mm) { |
| 386 | vsize = task_vsize(mm); | 386 | vsize = task_vsize(mm); |
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 800f113bea66..a27e56ca41a4 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
| @@ -127,8 +127,9 @@ extern void __ptrace_link(struct task_struct *child, | |||
| 127 | struct task_struct *new_parent); | 127 | struct task_struct *new_parent); |
| 128 | extern void __ptrace_unlink(struct task_struct *child); | 128 | extern void __ptrace_unlink(struct task_struct *child); |
| 129 | extern void exit_ptrace(struct task_struct *tracer); | 129 | extern void exit_ptrace(struct task_struct *tracer); |
| 130 | #define PTRACE_MODE_READ 1 | 130 | #define PTRACE_MODE_READ 0x01 |
| 131 | #define PTRACE_MODE_ATTACH 2 | 131 | #define PTRACE_MODE_ATTACH 0x02 |
| 132 | #define PTRACE_MODE_NOAUDIT 0x04 | ||
| 132 | /* Returns 0 on success, -errno on denial. */ | 133 | /* Returns 0 on success, -errno on denial. */ |
| 133 | extern int __ptrace_may_access(struct task_struct *task, unsigned int mode); | 134 | extern int __ptrace_may_access(struct task_struct *task, unsigned int mode); |
| 134 | /* Returns true on success, false on denial. */ | 135 | /* Returns true on success, false on denial. */ |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 210bbf045ee9..c890ac9a7962 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -161,6 +161,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state) | |||
| 161 | return ret; | 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 | int __ptrace_may_access(struct task_struct *task, unsigned int mode) | 172 | int __ptrace_may_access(struct task_struct *task, unsigned int mode) |
| 165 | { | 173 | { |
| 166 | const struct cred *cred = current_cred(), *tcred; | 174 | const struct cred *cred = current_cred(), *tcred; |
| @@ -187,7 +195,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |||
| 187 | cred->gid == tcred->sgid && | 195 | cred->gid == tcred->sgid && |
| 188 | cred->gid == tcred->gid)) | 196 | cred->gid == tcred->gid)) |
| 189 | goto ok; | 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 | goto ok; | 199 | goto ok; |
| 192 | rcu_read_unlock(); | 200 | rcu_read_unlock(); |
| 193 | return -EPERM; | 201 | return -EPERM; |
| @@ -196,7 +204,7 @@ ok: | |||
| 196 | smp_rmb(); | 204 | smp_rmb(); |
| 197 | if (task->mm) | 205 | if (task->mm) |
| 198 | dumpable = get_dumpable(task->mm); | 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 | return -EPERM; | 208 | return -EPERM; |
| 201 | 209 | ||
| 202 | return security_ptrace_access_check(task, mode); | 210 | return security_ptrace_access_check(task, mode); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c9605c4a2e08..14f94cd29c80 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -1809,7 +1809,7 @@ static int selinux_ptrace_access_check(struct task_struct *child, | |||
| 1809 | if (rc) | 1809 | if (rc) |
| 1810 | return rc; | 1810 | return rc; |
| 1811 | 1811 | ||
| 1812 | if (mode == PTRACE_MODE_READ) { | 1812 | if (mode & PTRACE_MODE_READ) { |
| 1813 | u32 sid = current_sid(); | 1813 | u32 sid = current_sid(); |
| 1814 | u32 csid = task_sid(child); | 1814 | u32 csid = task_sid(child); |
| 1815 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); | 1815 | return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); |
