From: Greg Kroah-Hartman Date: Mon, 21 Apr 2014 02:10:20 +0000 (-0700) Subject: 3.10-stable patches X-Git-Tag: v3.13.11~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1e545b0ca51093cbd324f61160d9e05f0ae6cdc7;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: exit-call-disassociate_ctty-before-exit_task_namespaces.patch wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race.patch --- diff --git a/queue-3.10/exit-call-disassociate_ctty-before-exit_task_namespaces.patch b/queue-3.10/exit-call-disassociate_ctty-before-exit_task_namespaces.patch new file mode 100644 index 00000000000..a90b1a9761f --- /dev/null +++ b/queue-3.10/exit-call-disassociate_ctty-before-exit_task_namespaces.patch @@ -0,0 +1,74 @@ +From c39df5fa37b0623589508c95515b4aa1531c524e Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Mon, 7 Apr 2014 15:38:29 -0700 +Subject: exit: call disassociate_ctty() before exit_task_namespaces() + +From: Oleg Nesterov + +commit c39df5fa37b0623589508c95515b4aa1531c524e upstream. + +Commit 8aac62706ada ("move exit_task_namespaces() outside of +exit_notify()") breaks pppd and the exiting service crashes the kernel: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 + IP: ppp_register_channel+0x13/0x20 [ppp_generic] + Call Trace: + ppp_asynctty_open+0x12b/0x170 [ppp_async] + tty_ldisc_open.isra.2+0x27/0x60 + tty_ldisc_hangup+0x1e3/0x220 + __tty_hangup+0x2c4/0x440 + disassociate_ctty+0x61/0x270 + do_exit+0x7f2/0xa50 + +ppp_register_channel() needs ->net_ns and current->nsproxy == NULL. + +Move disassociate_ctty() before exit_task_namespaces(), it doesn't make +sense to delay it after perf_event_exit_task() or cgroup_exit(). + +This also allows to use task_work_add() inside the (nontrivial) code +paths in disassociate_ctty(). + +Investigated by Peter Hurley. + +Signed-off-by: Oleg Nesterov +Reported-by: Sree Harsha Totakura +Cc: Peter Hurley +Cc: Sree Harsha Totakura +Cc: "Eric W. Biederman" +Cc: Jeff Dike +Cc: Ingo Molnar +Cc: Andrey Vagin +Cc: Al Viro +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/exit.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -801,6 +801,8 @@ void do_exit(long code) + exit_shm(tsk); + exit_files(tsk); + exit_fs(tsk); ++ if (group_dead) ++ disassociate_ctty(1); + exit_task_namespaces(tsk); + exit_task_work(tsk); + check_stack_usage(); +@@ -816,13 +818,9 @@ void do_exit(long code) + + cgroup_exit(tsk, 1); + +- if (group_dead) +- disassociate_ctty(1); +- + module_put(task_thread_info(tsk)->exec_domain->module); + + proc_exit_connector(tsk); +- + /* + * FIXME: do that only when needed, using sched_exit tracepoint + */ diff --git a/queue-3.10/series b/queue-3.10/series index 2acea454ab2..0dda3311b5f 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -20,3 +20,5 @@ revert-sparc64-fix-__copy_-to-from-_user_inatomic-defines.patch sparc32-fix-build-failure-for-arch_jump_label_transform.patch sparc64-don-t-treat-64-bit-syscall-return-codes-as-32-bit.patch sparc64-make-sure-pil-interrupts-are-enabled-during-hypervisor-yield.patch +wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race.patch +exit-call-disassociate_ctty-before-exit_task_namespaces.patch diff --git a/queue-3.10/wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race.patch b/queue-3.10/wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race.patch new file mode 100644 index 00000000000..79c3755bd4f --- /dev/null +++ b/queue-3.10/wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race.patch @@ -0,0 +1,78 @@ +From dfccbb5e49a621c1b21a62527d61fc4305617aca Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Mon, 7 Apr 2014 15:38:41 -0700 +Subject: wait: fix reparent_leader() vs EXIT_DEAD->EXIT_ZOMBIE race + +From: Oleg Nesterov + +commit dfccbb5e49a621c1b21a62527d61fc4305617aca upstream. + +wait_task_zombie() first does EXIT_ZOMBIE->EXIT_DEAD transition and +drops tasklist_lock. If this task is not the natural child and it is +traced, we change its state back to EXIT_ZOMBIE for ->real_parent. + +The last transition is racy, this is even documented in 50b8d257486a +"ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE +race". wait_consider_task() tries to detect this transition and clear +->notask_error but we can't rely on ptrace_reparented(), debugger can +exit and do ptrace_unlink() before its sub-thread sets EXIT_ZOMBIE. + +And there is another problem which were missed before: this transition +can also race with reparent_leader() which doesn't reset >exit_signal if +EXIT_DEAD, assuming that this task must be reaped by someone else. So +the tracee can be re-parented with ->exit_signal != SIGCHLD, and if +/sbin/init doesn't use __WALL it becomes unreapable. + +Change reparent_leader() to update ->exit_signal even if EXIT_DEAD. +Note: this is the simple temporary hack for -stable, it doesn't try to +solve all problems, it will be reverted by the next changes. + +Signed-off-by: Oleg Nesterov +Reported-by: Jan Kratochvil +Reported-by: Michal Schmidt +Tested-by: Michal Schmidt +Cc: Al Viro +Cc: Lennart Poettering +Cc: Roland McGrath +Cc: Tejun Heo +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/exit.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -570,9 +570,6 @@ static void reparent_leader(struct task_ + struct list_head *dead) + { + list_move_tail(&p->sibling, &p->real_parent->children); +- +- if (p->exit_state == EXIT_DEAD) +- return; + /* + * If this is a threaded reparent there is no need to + * notify anyone anything has happened. +@@ -580,9 +577,19 @@ static void reparent_leader(struct task_ + if (same_thread_group(p->real_parent, father)) + return; + +- /* We don't want people slaying init. */ ++ /* ++ * We don't want people slaying init. ++ * ++ * Note: we do this even if it is EXIT_DEAD, wait_task_zombie() ++ * can change ->exit_state to EXIT_ZOMBIE. If this is the final ++ * state, do_notify_parent() was already called and ->exit_signal ++ * doesn't matter. ++ */ + p->exit_signal = SIGCHLD; + ++ if (p->exit_state == EXIT_DEAD) ++ return; ++ + /* If it has exited notify the new parent about this child's death. */ + if (!p->ptrace && + p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) {