diff options
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r-- | kernel/ptrace.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 321127d965c2..4559e84f4b8a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -21,9 +21,7 @@ | |||
21 | #include <linux/audit.h> | 21 | #include <linux/audit.h> |
22 | #include <linux/pid_namespace.h> | 22 | #include <linux/pid_namespace.h> |
23 | #include <linux/syscalls.h> | 23 | #include <linux/syscalls.h> |
24 | 24 | #include <linux/uaccess.h> | |
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | 25 | ||
28 | 26 | ||
29 | /* | 27 | /* |
@@ -38,7 +36,7 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent) | |||
38 | list_add(&child->ptrace_entry, &new_parent->ptraced); | 36 | list_add(&child->ptrace_entry, &new_parent->ptraced); |
39 | child->parent = new_parent; | 37 | child->parent = new_parent; |
40 | } | 38 | } |
41 | 39 | ||
42 | /* | 40 | /* |
43 | * Turn a tracing stop into a normal stop now, since with no tracer there | 41 | * Turn a tracing stop into a normal stop now, since with no tracer there |
44 | * would be no way to wake it up with SIGCONT or SIGKILL. If there was a | 42 | * would be no way to wake it up with SIGCONT or SIGKILL. If there was a |
@@ -163,7 +161,7 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode) | |||
163 | task_lock(task); | 161 | task_lock(task); |
164 | err = __ptrace_may_access(task, mode); | 162 | err = __ptrace_may_access(task, mode); |
165 | task_unlock(task); | 163 | task_unlock(task); |
166 | return (!err ? true : false); | 164 | return !err; |
167 | } | 165 | } |
168 | 166 | ||
169 | int ptrace_attach(struct task_struct *task) | 167 | int ptrace_attach(struct task_struct *task) |
@@ -348,7 +346,7 @@ int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst | |||
348 | copied += retval; | 346 | copied += retval; |
349 | src += retval; | 347 | src += retval; |
350 | dst += retval; | 348 | dst += retval; |
351 | len -= retval; | 349 | len -= retval; |
352 | } | 350 | } |
353 | return copied; | 351 | return copied; |
354 | } | 352 | } |
@@ -373,7 +371,7 @@ int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long ds | |||
373 | copied += retval; | 371 | copied += retval; |
374 | src += retval; | 372 | src += retval; |
375 | dst += retval; | 373 | dst += retval; |
376 | len -= retval; | 374 | len -= retval; |
377 | } | 375 | } |
378 | return copied; | 376 | return copied; |
379 | } | 377 | } |
@@ -486,9 +484,9 @@ static int ptrace_resume(struct task_struct *child, long request, long data) | |||
486 | if (unlikely(!arch_has_single_step())) | 484 | if (unlikely(!arch_has_single_step())) |
487 | return -EIO; | 485 | return -EIO; |
488 | user_enable_single_step(child); | 486 | user_enable_single_step(child); |
489 | } | 487 | } else { |
490 | else | ||
491 | user_disable_single_step(child); | 488 | user_disable_single_step(child); |
489 | } | ||
492 | 490 | ||
493 | child->exit_code = data; | 491 | child->exit_code = data; |
494 | wake_up_process(child); | 492 | wake_up_process(child); |
@@ -596,10 +594,11 @@ repeat: | |||
596 | ret = security_ptrace_traceme(current->parent); | 594 | ret = security_ptrace_traceme(current->parent); |
597 | 595 | ||
598 | /* | 596 | /* |
599 | * Set the ptrace bit in the process ptrace flags. | 597 | * Check PF_EXITING to ensure ->real_parent has not passed |
600 | * Then link us on our parent's ptraced list. | 598 | * exit_ptrace(). Otherwise we don't report the error but |
599 | * pretend ->real_parent untraces us right after return. | ||
601 | */ | 600 | */ |
602 | if (!ret) { | 601 | if (!ret && !(current->real_parent->flags & PF_EXITING)) { |
603 | current->ptrace |= PT_PTRACED; | 602 | current->ptrace |= PT_PTRACED; |
604 | __ptrace_link(current, current->real_parent); | 603 | __ptrace_link(current, current->real_parent); |
605 | } | 604 | } |