aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r--kernel/ptrace.c23
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
169int ptrace_attach(struct task_struct *task) 167int 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 }