Messages in this thread Patch in this message | | | Date | Wed, 17 May 2006 00:00:21 -0700 | From | Chris Wright <> | Subject | [PATCH 21/22] [PATCH] Fix ptrace_attach()/ptrace_traceme()/de_thread() race |
| |
-stable review patch. If anyone has any objections, please let us know. ------------------
This holds the task lock (and, for ptrace_attach, the tasklist_lock) over the actual attach event, which closes a race between attacking to a thread that is either doing a PTRACE_TRACEME or getting de-threaded.
Thanks to Oleg Nesterov for reminding me about this, and Chris Wright for noticing a lost return value in my first version.
Signed-off-by: Linus Torvalds <torvalds@osdl.org> Signed-off-by: Chris Wright <chrisw@sous-sol.org> ---
kernel/ptrace.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-)
--- linux-2.6.16.16.orig/kernel/ptrace.c +++ linux-2.6.16.16/kernel/ptrace.c @@ -149,12 +149,16 @@ int ptrace_may_attach(struct task_struct int ptrace_attach(struct task_struct *task) { int retval; - task_lock(task); + retval = -EPERM; if (task->pid <= 1) - goto bad; + goto out; if (task->tgid == current->tgid) - goto bad; + goto out; + + write_lock_irq(&tasklist_lock); + task_lock(task); + /* the same process cannot be attached many times */ if (task->ptrace & PT_PTRACED) goto bad; @@ -167,17 +171,15 @@ int ptrace_attach(struct task_struct *ta ? PT_ATTACHED : 0); if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; - task_unlock(task); - write_lock_irq(&tasklist_lock); __ptrace_link(task, current); - write_unlock_irq(&tasklist_lock); force_sig_specific(SIGSTOP, task); - return 0; bad: + write_unlock_irq(&tasklist_lock); task_unlock(task); +out: return retval; } @@ -418,21 +420,22 @@ int ptrace_request(struct task_struct *c */ int ptrace_traceme(void) { - int ret; + int ret = -EPERM; /* * Are we already being traced? */ - if (current->ptrace & PT_PTRACED) - return -EPERM; - ret = security_ptrace(current->parent, current); - if (ret) - return -EPERM; - /* - * Set the ptrace bit in the process ptrace flags. - */ - current->ptrace |= PT_PTRACED; - return 0; + task_lock(current); + if (!(current->ptrace & PT_PTRACED)) { + ret = security_ptrace(current->parent, current); + /* + * Set the ptrace bit in the process ptrace flags. + */ + if (!ret) + current->ptrace |= PT_PTRACED; + } + task_unlock(current); + return ret; } /** -- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |