diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 4e3f919edc48..122fadb972fc 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/completion.h> | 13 | #include <linux/completion.h> |
14 | #include <linux/personality.h> | 14 | #include <linux/personality.h> |
15 | #include <linux/tty.h> | 15 | #include <linux/tty.h> |
16 | #include <linux/namespace.h> | 16 | #include <linux/mnt_namespace.h> |
17 | #include <linux/key.h> | 17 | #include <linux/key.h> |
18 | #include <linux/security.h> | 18 | #include <linux/security.h> |
19 | #include <linux/cpu.h> | 19 | #include <linux/cpu.h> |
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/file.h> | 22 | #include <linux/file.h> |
23 | #include <linux/binfmts.h> | 23 | #include <linux/binfmts.h> |
24 | #include <linux/nsproxy.h> | 24 | #include <linux/nsproxy.h> |
25 | #include <linux/pid_namespace.h> | ||
25 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
26 | #include <linux/profile.h> | 27 | #include <linux/profile.h> |
27 | #include <linux/mount.h> | 28 | #include <linux/mount.h> |
@@ -48,7 +49,6 @@ | |||
48 | #include <asm/mmu_context.h> | 49 | #include <asm/mmu_context.h> |
49 | 50 | ||
50 | extern void sem_exit (void); | 51 | extern void sem_exit (void); |
51 | extern struct task_struct *child_reaper; | ||
52 | 52 | ||
53 | static void exit_mm(struct task_struct * tsk); | 53 | static void exit_mm(struct task_struct * tsk); |
54 | 54 | ||
@@ -189,21 +189,18 @@ repeat: | |||
189 | int session_of_pgrp(int pgrp) | 189 | int session_of_pgrp(int pgrp) |
190 | { | 190 | { |
191 | struct task_struct *p; | 191 | struct task_struct *p; |
192 | int sid = -1; | 192 | int sid = 0; |
193 | 193 | ||
194 | read_lock(&tasklist_lock); | 194 | read_lock(&tasklist_lock); |
195 | do_each_task_pid(pgrp, PIDTYPE_PGID, p) { | 195 | |
196 | if (p->signal->session > 0) { | 196 | p = find_task_by_pid_type(PIDTYPE_PGID, pgrp); |
197 | sid = p->signal->session; | 197 | if (p == NULL) |
198 | goto out; | 198 | p = find_task_by_pid(pgrp); |
199 | } | 199 | if (p != NULL) |
200 | } while_each_task_pid(pgrp, PIDTYPE_PGID, p); | 200 | sid = process_session(p); |
201 | p = find_task_by_pid(pgrp); | 201 | |
202 | if (p) | ||
203 | sid = p->signal->session; | ||
204 | out: | ||
205 | read_unlock(&tasklist_lock); | 202 | read_unlock(&tasklist_lock); |
206 | 203 | ||
207 | return sid; | 204 | return sid; |
208 | } | 205 | } |
209 | 206 | ||
@@ -225,8 +222,8 @@ static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task) | |||
225 | || p->exit_state | 222 | || p->exit_state |
226 | || is_init(p->real_parent)) | 223 | || is_init(p->real_parent)) |
227 | continue; | 224 | continue; |
228 | if (process_group(p->real_parent) != pgrp | 225 | if (process_group(p->real_parent) != pgrp && |
229 | && p->real_parent->signal->session == p->signal->session) { | 226 | process_session(p->real_parent) == process_session(p)) { |
230 | ret = 0; | 227 | ret = 0; |
231 | break; | 228 | break; |
232 | } | 229 | } |
@@ -260,7 +257,8 @@ static int has_stopped_jobs(int pgrp) | |||
260 | } | 257 | } |
261 | 258 | ||
262 | /** | 259 | /** |
263 | * reparent_to_init - Reparent the calling kernel thread to the init task. | 260 | * reparent_to_init - Reparent the calling kernel thread to the init task |
261 | * of the pid space that the thread belongs to. | ||
264 | * | 262 | * |
265 | * If a kernel thread is launched as a result of a system call, or if | 263 | * If a kernel thread is launched as a result of a system call, or if |
266 | * it ever exits, it should generally reparent itself to init so that | 264 | * it ever exits, it should generally reparent itself to init so that |
@@ -278,8 +276,8 @@ static void reparent_to_init(void) | |||
278 | ptrace_unlink(current); | 276 | ptrace_unlink(current); |
279 | /* Reparent to init */ | 277 | /* Reparent to init */ |
280 | remove_parent(current); | 278 | remove_parent(current); |
281 | current->parent = child_reaper; | 279 | current->parent = child_reaper(current); |
282 | current->real_parent = child_reaper; | 280 | current->real_parent = child_reaper(current); |
283 | add_parent(current); | 281 | add_parent(current); |
284 | 282 | ||
285 | /* Set the exit signal to SIGCHLD so we signal init on exit */ | 283 | /* Set the exit signal to SIGCHLD so we signal init on exit */ |
@@ -302,9 +300,9 @@ void __set_special_pids(pid_t session, pid_t pgrp) | |||
302 | { | 300 | { |
303 | struct task_struct *curr = current->group_leader; | 301 | struct task_struct *curr = current->group_leader; |
304 | 302 | ||
305 | if (curr->signal->session != session) { | 303 | if (process_session(curr) != session) { |
306 | detach_pid(curr, PIDTYPE_SID); | 304 | detach_pid(curr, PIDTYPE_SID); |
307 | curr->signal->session = session; | 305 | set_signal_session(curr->signal, session); |
308 | attach_pid(curr, PIDTYPE_SID, session); | 306 | attach_pid(curr, PIDTYPE_SID, session); |
309 | } | 307 | } |
310 | if (process_group(curr) != pgrp) { | 308 | if (process_group(curr) != pgrp) { |
@@ -314,7 +312,7 @@ void __set_special_pids(pid_t session, pid_t pgrp) | |||
314 | } | 312 | } |
315 | } | 313 | } |
316 | 314 | ||
317 | void set_special_pids(pid_t session, pid_t pgrp) | 315 | static void set_special_pids(pid_t session, pid_t pgrp) |
318 | { | 316 | { |
319 | write_lock_irq(&tasklist_lock); | 317 | write_lock_irq(&tasklist_lock); |
320 | __set_special_pids(session, pgrp); | 318 | __set_special_pids(session, pgrp); |
@@ -384,9 +382,7 @@ void daemonize(const char *name, ...) | |||
384 | exit_mm(current); | 382 | exit_mm(current); |
385 | 383 | ||
386 | set_special_pids(1, 1); | 384 | set_special_pids(1, 1); |
387 | mutex_lock(&tty_mutex); | 385 | proc_clear_tty(current); |
388 | current->signal->tty = NULL; | ||
389 | mutex_unlock(&tty_mutex); | ||
390 | 386 | ||
391 | /* Block and flush all signals */ | 387 | /* Block and flush all signals */ |
392 | sigfillset(&blocked); | 388 | sigfillset(&blocked); |
@@ -429,7 +425,7 @@ static void close_files(struct files_struct * files) | |||
429 | for (;;) { | 425 | for (;;) { |
430 | unsigned long set; | 426 | unsigned long set; |
431 | i = j * __NFDBITS; | 427 | i = j * __NFDBITS; |
432 | if (i >= fdt->max_fdset || i >= fdt->max_fds) | 428 | if (i >= fdt->max_fds) |
433 | break; | 429 | break; |
434 | set = fdt->open_fds->fds_bits[j++]; | 430 | set = fdt->open_fds->fds_bits[j++]; |
435 | while (set) { | 431 | while (set) { |
@@ -470,11 +466,9 @@ void fastcall put_files_struct(struct files_struct *files) | |||
470 | * you can free files immediately. | 466 | * you can free files immediately. |
471 | */ | 467 | */ |
472 | fdt = files_fdtable(files); | 468 | fdt = files_fdtable(files); |
473 | if (fdt == &files->fdtab) | 469 | if (fdt != &files->fdtab) |
474 | fdt->free_files = files; | ||
475 | else | ||
476 | kmem_cache_free(files_cachep, files); | 470 | kmem_cache_free(files_cachep, files); |
477 | free_fdtable(fdt); | 471 | call_rcu(&fdt->rcu, free_fdtable_rcu); |
478 | } | 472 | } |
479 | } | 473 | } |
480 | 474 | ||
@@ -649,10 +643,11 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
649 | * outside, so the child pgrp is now orphaned. | 643 | * outside, so the child pgrp is now orphaned. |
650 | */ | 644 | */ |
651 | if ((process_group(p) != process_group(father)) && | 645 | if ((process_group(p) != process_group(father)) && |
652 | (p->signal->session == father->signal->session)) { | 646 | (process_session(p) == process_session(father))) { |
653 | int pgrp = process_group(p); | 647 | int pgrp = process_group(p); |
654 | 648 | ||
655 | if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { | 649 | if (will_become_orphaned_pgrp(pgrp, NULL) && |
650 | has_stopped_jobs(pgrp)) { | ||
656 | __kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp); | 651 | __kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp); |
657 | __kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp); | 652 | __kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp); |
658 | } | 653 | } |
@@ -663,7 +658,8 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
663 | * When we die, we re-parent all our children. | 658 | * When we die, we re-parent all our children. |
664 | * Try to give them to another thread in our thread | 659 | * Try to give them to another thread in our thread |
665 | * group, and if no such member exists, give it to | 660 | * group, and if no such member exists, give it to |
666 | * the global child reaper process (ie "init") | 661 | * the child reaper process (ie "init") in our pid |
662 | * space. | ||
667 | */ | 663 | */ |
668 | static void | 664 | static void |
669 | forget_original_parent(struct task_struct *father, struct list_head *to_release) | 665 | forget_original_parent(struct task_struct *father, struct list_head *to_release) |
@@ -674,7 +670,7 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release) | |||
674 | do { | 670 | do { |
675 | reaper = next_thread(reaper); | 671 | reaper = next_thread(reaper); |
676 | if (reaper == father) { | 672 | if (reaper == father) { |
677 | reaper = child_reaper; | 673 | reaper = child_reaper(father); |
678 | break; | 674 | break; |
679 | } | 675 | } |
680 | } while (reaper->exit_state); | 676 | } while (reaper->exit_state); |
@@ -786,7 +782,7 @@ static void exit_notify(struct task_struct *tsk) | |||
786 | t = tsk->real_parent; | 782 | t = tsk->real_parent; |
787 | 783 | ||
788 | if ((process_group(t) != process_group(tsk)) && | 784 | if ((process_group(t) != process_group(tsk)) && |
789 | (t->signal->session == tsk->signal->session) && | 785 | (process_session(t) == process_session(tsk)) && |
790 | will_become_orphaned_pgrp(process_group(tsk), tsk) && | 786 | will_become_orphaned_pgrp(process_group(tsk), tsk) && |
791 | has_stopped_jobs(process_group(tsk))) { | 787 | has_stopped_jobs(process_group(tsk))) { |
792 | __kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk)); | 788 | __kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk)); |
@@ -860,8 +856,13 @@ fastcall NORET_TYPE void do_exit(long code) | |||
860 | panic("Aiee, killing interrupt handler!"); | 856 | panic("Aiee, killing interrupt handler!"); |
861 | if (unlikely(!tsk->pid)) | 857 | if (unlikely(!tsk->pid)) |
862 | panic("Attempted to kill the idle task!"); | 858 | panic("Attempted to kill the idle task!"); |
863 | if (unlikely(tsk == child_reaper)) | 859 | if (unlikely(tsk == child_reaper(tsk))) { |
864 | panic("Attempted to kill init!"); | 860 | if (tsk->nsproxy->pid_ns != &init_pid_ns) |
861 | tsk->nsproxy->pid_ns->child_reaper = init_pid_ns.child_reaper; | ||
862 | else | ||
863 | panic("Attempted to kill init!"); | ||
864 | } | ||
865 | |||
865 | 866 | ||
866 | if (unlikely(current->ptrace & PT_TRACE_EXIT)) { | 867 | if (unlikely(current->ptrace & PT_TRACE_EXIT)) { |
867 | current->ptrace_message = code; | 868 | current->ptrace_message = code; |