diff options
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r-- | kernel/ptrace.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 78ab24a7b0e4..00ab2ca5ed11 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -172,6 +172,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state) | |||
172 | return ret; | 172 | return ret; |
173 | } | 173 | } |
174 | 174 | ||
175 | static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) | ||
176 | { | ||
177 | if (mode & PTRACE_MODE_NOAUDIT) | ||
178 | return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE); | ||
179 | else | ||
180 | return has_ns_capability(current, ns, CAP_SYS_PTRACE); | ||
181 | } | ||
182 | |||
175 | int __ptrace_may_access(struct task_struct *task, unsigned int mode) | 183 | int __ptrace_may_access(struct task_struct *task, unsigned int mode) |
176 | { | 184 | { |
177 | const struct cred *cred = current_cred(), *tcred; | 185 | const struct cred *cred = current_cred(), *tcred; |
@@ -198,7 +206,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |||
198 | cred->gid == tcred->sgid && | 206 | cred->gid == tcred->sgid && |
199 | cred->gid == tcred->gid)) | 207 | cred->gid == tcred->gid)) |
200 | goto ok; | 208 | goto ok; |
201 | if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE)) | 209 | if (ptrace_has_cap(tcred->user->user_ns, mode)) |
202 | goto ok; | 210 | goto ok; |
203 | rcu_read_unlock(); | 211 | rcu_read_unlock(); |
204 | return -EPERM; | 212 | return -EPERM; |
@@ -207,7 +215,7 @@ ok: | |||
207 | smp_rmb(); | 215 | smp_rmb(); |
208 | if (task->mm) | 216 | if (task->mm) |
209 | dumpable = get_dumpable(task->mm); | 217 | dumpable = get_dumpable(task->mm); |
210 | if (!dumpable && !task_ns_capable(task, CAP_SYS_PTRACE)) | 218 | if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode)) |
211 | return -EPERM; | 219 | return -EPERM; |
212 | 220 | ||
213 | return security_ptrace_access_check(task, mode); | 221 | return security_ptrace_access_check(task, mode); |
@@ -277,7 +285,7 @@ static int ptrace_attach(struct task_struct *task, long request, | |||
277 | task->ptrace = PT_PTRACED; | 285 | task->ptrace = PT_PTRACED; |
278 | if (seize) | 286 | if (seize) |
279 | task->ptrace |= PT_SEIZED; | 287 | task->ptrace |= PT_SEIZED; |
280 | if (task_ns_capable(task, CAP_SYS_PTRACE)) | 288 | if (ns_capable(task_user_ns(task), CAP_SYS_PTRACE)) |
281 | task->ptrace |= PT_PTRACE_CAP; | 289 | task->ptrace |= PT_PTRACE_CAP; |
282 | 290 | ||
283 | __ptrace_link(task, current); | 291 | __ptrace_link(task, current); |