From: Chris Wright Date: Thu, 16 Feb 2006 08:30:43 +0000 (-0800) Subject: Add Oleg's zap_thread fix X-Git-Tag: v2.6.15.5~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=06b5159ba605504b39181dc11787389932ce79ed;p=thirdparty%2Fkernel%2Fstable-queue.git Add Oleg's zap_thread fix --- diff --git a/queue/fix-zap_thread-s-ptrace-related-problems.patch b/queue/fix-zap_thread-s-ptrace-related-problems.patch new file mode 100644 index 00000000000..fab7d900ecf --- /dev/null +++ b/queue/fix-zap_thread-s-ptrace-related-problems.patch @@ -0,0 +1,95 @@ +From nobody Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Wed Feb 15 22:50:10 2006 +0300 +Subject: [PATCH] fix zap_thread's ptrace related problems + +1. The tracee can go from ptrace_stop() to do_signal_stop() + after __ptrace_unlink(p). + +2. It is unsafe to __ptrace_unlink(p) while p->parent may wait + for tasklist_lock in ptrace_detach(). + +Signed-off-by: Oleg Nesterov +Cc: Roland McGrath +Cc: Ingo Molnar +Cc: Christoph Hellwig +Cc: Eric W. Biederman +Signed-off-by: Linus Torvalds +Signed-off-by: Chris Wright +--- + + fs/exec.c | 2 +- + include/linux/ptrace.h | 1 + + kernel/ptrace.c | 25 +++++++++++++++---------- + 3 files changed, 17 insertions(+), 11 deletions(-) + +--- linux-2.6.15.4.orig/fs/exec.c ++++ linux-2.6.15.4/fs/exec.c +@@ -1403,7 +1403,7 @@ static void zap_threads (struct mm_struc + do_each_thread(g,p) { + if (mm == p->mm && p != tsk && + p->ptrace && p->parent->mm == mm) { +- __ptrace_unlink(p); ++ __ptrace_detach(p, 0); + } + } while_each_thread(g,p); + write_unlock_irq(&tasklist_lock); +--- linux-2.6.15.4.orig/include/linux/ptrace.h ++++ linux-2.6.15.4/include/linux/ptrace.h +@@ -84,6 +84,7 @@ extern int ptrace_readdata(struct task_s + extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); + extern int ptrace_attach(struct task_struct *tsk); + extern int ptrace_detach(struct task_struct *, unsigned int); ++extern void __ptrace_detach(struct task_struct *, unsigned int); + extern void ptrace_disable(struct task_struct *); + extern int ptrace_check_attach(struct task_struct *task, int kill); + extern int ptrace_request(struct task_struct *child, long request, long addr, long data); +--- linux-2.6.15.4.orig/kernel/ptrace.c ++++ linux-2.6.15.4/kernel/ptrace.c +@@ -71,8 +71,8 @@ void ptrace_untrace(task_t *child) + */ + void __ptrace_unlink(task_t *child) + { +- if (!child->ptrace) +- BUG(); ++ BUG_ON(!child->ptrace); ++ + child->ptrace = 0; + if (!list_empty(&child->ptrace_list)) { + list_del_init(&child->ptrace_list); +@@ -183,22 +183,27 @@ bad: + return retval; + } + ++void __ptrace_detach(struct task_struct *child, unsigned int data) ++{ ++ child->exit_code = data; ++ /* .. re-parent .. */ ++ __ptrace_unlink(child); ++ /* .. and wake it up. */ ++ if (child->exit_state != EXIT_ZOMBIE) ++ wake_up_process(child); ++} ++ + int ptrace_detach(struct task_struct *child, unsigned int data) + { + if (!valid_signal(data)) +- return -EIO; ++ return -EIO; + + /* Architecture-specific hardware disable .. */ + ptrace_disable(child); + +- /* .. re-parent .. */ +- child->exit_code = data; +- + write_lock_irq(&tasklist_lock); +- __ptrace_unlink(child); +- /* .. and wake it up. */ +- if (child->exit_state != EXIT_ZOMBIE) +- wake_up_process(child); ++ if (child->ptrace) ++ __ptrace_detach(child, data); + write_unlock_irq(&tasklist_lock); + + return 0; diff --git a/queue/series b/queue/series index fd83a49c417..dc5f2885969 100644 --- a/queue/series +++ b/queue/series @@ -13,3 +13,4 @@ do_sigaction-cleanup-sa_mask-manipulation.patch sys32_signal-forgets-to-initialize-sa_mask.patch fix-s390-build-failure.patch fix-deadlock-in-br_stp_disable_bridge.patch +fix-zap_thread-s-ptrace-related-problems.patch