diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 96 |
1 files changed, 70 insertions, 26 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 26a8f5c25805..ca9a3845ef3e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -194,6 +194,7 @@ void __put_task_struct(struct task_struct *tsk) | |||
194 | WARN_ON(atomic_read(&tsk->usage)); | 194 | WARN_ON(atomic_read(&tsk->usage)); |
195 | WARN_ON(tsk == current); | 195 | WARN_ON(tsk == current); |
196 | 196 | ||
197 | security_task_free(tsk); | ||
197 | exit_creds(tsk); | 198 | exit_creds(tsk); |
198 | delayacct_tsk_free(tsk); | 199 | delayacct_tsk_free(tsk); |
199 | put_signal_struct(tsk->signal); | 200 | put_signal_struct(tsk->signal); |
@@ -356,7 +357,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
356 | charge = 0; | 357 | charge = 0; |
357 | if (mpnt->vm_flags & VM_ACCOUNT) { | 358 | if (mpnt->vm_flags & VM_ACCOUNT) { |
358 | unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; | 359 | unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; |
359 | if (security_vm_enough_memory(len)) | 360 | if (security_vm_enough_memory_mm(oldmm, len)) /* sic */ |
360 | goto fail_nomem; | 361 | goto fail_nomem; |
361 | charge = len; | 362 | charge = len; |
362 | } | 363 | } |
@@ -515,6 +516,23 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) | |||
515 | return NULL; | 516 | return NULL; |
516 | } | 517 | } |
517 | 518 | ||
519 | static void check_mm(struct mm_struct *mm) | ||
520 | { | ||
521 | int i; | ||
522 | |||
523 | for (i = 0; i < NR_MM_COUNTERS; i++) { | ||
524 | long x = atomic_long_read(&mm->rss_stat.count[i]); | ||
525 | |||
526 | if (unlikely(x)) | ||
527 | printk(KERN_ALERT "BUG: Bad rss-counter state " | ||
528 | "mm:%p idx:%d val:%ld\n", mm, i, x); | ||
529 | } | ||
530 | |||
531 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
532 | VM_BUG_ON(mm->pmd_huge_pte); | ||
533 | #endif | ||
534 | } | ||
535 | |||
518 | /* | 536 | /* |
519 | * Allocate and initialize an mm_struct. | 537 | * Allocate and initialize an mm_struct. |
520 | */ | 538 | */ |
@@ -542,9 +560,7 @@ void __mmdrop(struct mm_struct *mm) | |||
542 | mm_free_pgd(mm); | 560 | mm_free_pgd(mm); |
543 | destroy_context(mm); | 561 | destroy_context(mm); |
544 | mmu_notifier_mm_destroy(mm); | 562 | mmu_notifier_mm_destroy(mm); |
545 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 563 | check_mm(mm); |
546 | VM_BUG_ON(mm->pmd_huge_pte); | ||
547 | #endif | ||
548 | free_mm(mm); | 564 | free_mm(mm); |
549 | } | 565 | } |
550 | EXPORT_SYMBOL_GPL(__mmdrop); | 566 | EXPORT_SYMBOL_GPL(__mmdrop); |
@@ -673,6 +689,38 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) | |||
673 | return mm; | 689 | return mm; |
674 | } | 690 | } |
675 | 691 | ||
692 | static void complete_vfork_done(struct task_struct *tsk) | ||
693 | { | ||
694 | struct completion *vfork; | ||
695 | |||
696 | task_lock(tsk); | ||
697 | vfork = tsk->vfork_done; | ||
698 | if (likely(vfork)) { | ||
699 | tsk->vfork_done = NULL; | ||
700 | complete(vfork); | ||
701 | } | ||
702 | task_unlock(tsk); | ||
703 | } | ||
704 | |||
705 | static int wait_for_vfork_done(struct task_struct *child, | ||
706 | struct completion *vfork) | ||
707 | { | ||
708 | int killed; | ||
709 | |||
710 | freezer_do_not_count(); | ||
711 | killed = wait_for_completion_killable(vfork); | ||
712 | freezer_count(); | ||
713 | |||
714 | if (killed) { | ||
715 | task_lock(child); | ||
716 | child->vfork_done = NULL; | ||
717 | task_unlock(child); | ||
718 | } | ||
719 | |||
720 | put_task_struct(child); | ||
721 | return killed; | ||
722 | } | ||
723 | |||
676 | /* Please note the differences between mmput and mm_release. | 724 | /* Please note the differences between mmput and mm_release. |
677 | * mmput is called whenever we stop holding onto a mm_struct, | 725 | * mmput is called whenever we stop holding onto a mm_struct, |
678 | * error success whatever. | 726 | * error success whatever. |
@@ -688,8 +736,6 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) | |||
688 | */ | 736 | */ |
689 | void mm_release(struct task_struct *tsk, struct mm_struct *mm) | 737 | void mm_release(struct task_struct *tsk, struct mm_struct *mm) |
690 | { | 738 | { |
691 | struct completion *vfork_done = tsk->vfork_done; | ||
692 | |||
693 | /* Get rid of any futexes when releasing the mm */ | 739 | /* Get rid of any futexes when releasing the mm */ |
694 | #ifdef CONFIG_FUTEX | 740 | #ifdef CONFIG_FUTEX |
695 | if (unlikely(tsk->robust_list)) { | 741 | if (unlikely(tsk->robust_list)) { |
@@ -711,17 +757,15 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) | |||
711 | /* Get rid of any cached register state */ | 757 | /* Get rid of any cached register state */ |
712 | deactivate_mm(tsk, mm); | 758 | deactivate_mm(tsk, mm); |
713 | 759 | ||
714 | /* notify parent sleeping on vfork() */ | 760 | if (tsk->vfork_done) |
715 | if (vfork_done) { | 761 | complete_vfork_done(tsk); |
716 | tsk->vfork_done = NULL; | ||
717 | complete(vfork_done); | ||
718 | } | ||
719 | 762 | ||
720 | /* | 763 | /* |
721 | * If we're exiting normally, clear a user-space tid field if | 764 | * If we're exiting normally, clear a user-space tid field if |
722 | * requested. We leave this alone when dying by signal, to leave | 765 | * requested. We leave this alone when dying by signal, to leave |
723 | * the value intact in a core dump, and to save the unnecessary | 766 | * the value intact in a core dump, and to save the unnecessary |
724 | * trouble otherwise. Userland only wants this done for a sys_exit. | 767 | * trouble, say, a killed vfork parent shouldn't touch this mm. |
768 | * Userland only wants this done for a sys_exit. | ||
725 | */ | 769 | */ |
726 | if (tsk->clear_child_tid) { | 770 | if (tsk->clear_child_tid) { |
727 | if (!(tsk->flags & PF_SIGNALED) && | 771 | if (!(tsk->flags & PF_SIGNALED) && |
@@ -1015,6 +1059,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
1015 | sig->oom_score_adj = current->signal->oom_score_adj; | 1059 | sig->oom_score_adj = current->signal->oom_score_adj; |
1016 | sig->oom_score_adj_min = current->signal->oom_score_adj_min; | 1060 | sig->oom_score_adj_min = current->signal->oom_score_adj_min; |
1017 | 1061 | ||
1062 | sig->has_child_subreaper = current->signal->has_child_subreaper || | ||
1063 | current->signal->is_child_subreaper; | ||
1064 | |||
1018 | mutex_init(&sig->cred_guard_mutex); | 1065 | mutex_init(&sig->cred_guard_mutex); |
1019 | 1066 | ||
1020 | return 0; | 1067 | return 0; |
@@ -1026,7 +1073,6 @@ static void copy_flags(unsigned long clone_flags, struct task_struct *p) | |||
1026 | 1073 | ||
1027 | new_flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER); | 1074 | new_flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER); |
1028 | new_flags |= PF_FORKNOEXEC; | 1075 | new_flags |= PF_FORKNOEXEC; |
1029 | new_flags |= PF_STARTING; | ||
1030 | p->flags = new_flags; | 1076 | p->flags = new_flags; |
1031 | } | 1077 | } |
1032 | 1078 | ||
@@ -1203,6 +1249,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1203 | #ifdef CONFIG_CPUSETS | 1249 | #ifdef CONFIG_CPUSETS |
1204 | p->cpuset_mem_spread_rotor = NUMA_NO_NODE; | 1250 | p->cpuset_mem_spread_rotor = NUMA_NO_NODE; |
1205 | p->cpuset_slab_spread_rotor = NUMA_NO_NODE; | 1251 | p->cpuset_slab_spread_rotor = NUMA_NO_NODE; |
1252 | seqcount_init(&p->mems_allowed_seq); | ||
1206 | #endif | 1253 | #endif |
1207 | #ifdef CONFIG_TRACE_IRQFLAGS | 1254 | #ifdef CONFIG_TRACE_IRQFLAGS |
1208 | p->irq_events = 0; | 1255 | p->irq_events = 0; |
@@ -1322,7 +1369,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1322 | clear_all_latency_tracing(p); | 1369 | clear_all_latency_tracing(p); |
1323 | 1370 | ||
1324 | /* ok, now we should be set up.. */ | 1371 | /* ok, now we should be set up.. */ |
1325 | p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL); | 1372 | if (clone_flags & CLONE_THREAD) |
1373 | p->exit_signal = -1; | ||
1374 | else if (clone_flags & CLONE_PARENT) | ||
1375 | p->exit_signal = current->group_leader->exit_signal; | ||
1376 | else | ||
1377 | p->exit_signal = (clone_flags & CSIGNAL); | ||
1378 | |||
1326 | p->pdeath_signal = 0; | 1379 | p->pdeath_signal = 0; |
1327 | p->exit_state = 0; | 1380 | p->exit_state = 0; |
1328 | 1381 | ||
@@ -1557,16 +1610,9 @@ long do_fork(unsigned long clone_flags, | |||
1557 | if (clone_flags & CLONE_VFORK) { | 1610 | if (clone_flags & CLONE_VFORK) { |
1558 | p->vfork_done = &vfork; | 1611 | p->vfork_done = &vfork; |
1559 | init_completion(&vfork); | 1612 | init_completion(&vfork); |
1613 | get_task_struct(p); | ||
1560 | } | 1614 | } |
1561 | 1615 | ||
1562 | /* | ||
1563 | * We set PF_STARTING at creation in case tracing wants to | ||
1564 | * use this to distinguish a fully live task from one that | ||
1565 | * hasn't finished SIGSTOP raising yet. Now we clear it | ||
1566 | * and set the child going. | ||
1567 | */ | ||
1568 | p->flags &= ~PF_STARTING; | ||
1569 | |||
1570 | wake_up_new_task(p); | 1616 | wake_up_new_task(p); |
1571 | 1617 | ||
1572 | /* forking complete and child started to run, tell ptracer */ | 1618 | /* forking complete and child started to run, tell ptracer */ |
@@ -1574,10 +1620,8 @@ long do_fork(unsigned long clone_flags, | |||
1574 | ptrace_event(trace, nr); | 1620 | ptrace_event(trace, nr); |
1575 | 1621 | ||
1576 | if (clone_flags & CLONE_VFORK) { | 1622 | if (clone_flags & CLONE_VFORK) { |
1577 | freezer_do_not_count(); | 1623 | if (!wait_for_vfork_done(p, &vfork)) |
1578 | wait_for_completion(&vfork); | 1624 | ptrace_event(PTRACE_EVENT_VFORK_DONE, nr); |
1579 | freezer_count(); | ||
1580 | ptrace_event(PTRACE_EVENT_VFORK_DONE, nr); | ||
1581 | } | 1625 | } |
1582 | } else { | 1626 | } else { |
1583 | nr = PTR_ERR(p); | 1627 | nr = PTR_ERR(p); |