]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/exit.c
sched/headers: Prepare for new header dependencies before moving code to <linux/sched...
[mirror_ubuntu-artful-kernel.git] / kernel / exit.c
index 580da79e38ee89992a93e6cb61f2c16232d580a6..48649ccbb649d3d0b5391eae760047e2f2a83db3 100644 (file)
@@ -6,6 +6,8 @@
 
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/sched/autogroup.h>
+#include <linux/sched/mm.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/capability.h>
@@ -45,6 +47,7 @@
 #include <linux/task_io_accounting_ops.h>
 #include <linux/tracehook.h>
 #include <linux/fs_struct.h>
+#include <linux/userfaultfd_k.h>
 #include <linux/init_task.h>
 #include <linux/perf_event.h>
 #include <trace/events/sched.h>
@@ -538,7 +541,7 @@ static void exit_mm(void)
                __set_current_state(TASK_RUNNING);
                down_read(&mm->mmap_sem);
        }
-       atomic_inc(&mm->mm_count);
+       mmgrab(mm);
        BUG_ON(mm != current->active_mm);
        /* more a memory barrier than a real lock */
        task_lock(current);
@@ -547,6 +550,7 @@ static void exit_mm(void)
        enter_lazy_tlb(mm, current);
        task_unlock(current);
        mm_update_next_owner(mm);
+       userfaultfd_exit(mm);
        mmput(mm);
        if (test_thread_flag(TIF_MEMDIE))
                exit_oom_victim();
@@ -607,15 +611,18 @@ static struct task_struct *find_new_reaper(struct task_struct *father,
                return thread;
 
        if (father->signal->has_child_subreaper) {
+               unsigned int ns_level = task_pid(father)->level;
                /*
                 * Find the first ->is_child_subreaper ancestor in our pid_ns.
-                * We start from father to ensure we can not look into another
-                * namespace, this is safe because all its threads are dead.
+                * We can't check reaper != child_reaper to ensure we do not
+                * cross the namespaces, the exiting parent could be injected
+                * by setns() + fork().
+                * We check pid->level, this is slightly more efficient than
+                * task_active_pid_ns(reaper) != task_active_pid_ns(father).
                 */
-               for (reaper = father;
-                    !same_thread_group(reaper, child_reaper);
+               for (reaper = father->real_parent;
+                    task_pid(reaper)->level == ns_level;
                     reaper = reaper->real_parent) {
-                       /* call_usermodehelper() descendants need this check */
                        if (reaper == &init_task)
                                break;
                        if (!reaper->signal->is_child_subreaper)