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); |