]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/fork.c
genirq/cpuhotplug: Add sanity check for effective affinity mask
[mirror_ubuntu-artful-kernel.git] / kernel / fork.c
index e075b7780421dee1d8243b9dc178248398c5f189..8efc6b4466e3bfbb76b13a2206d7cba69cde1b53 100644 (file)
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/task.h>
+#ifdef CONFIG_USER_NS
+extern int unprivileged_userns_clone;
+#else
+#define unprivileged_userns_clone 0
+#endif
 
 /*
  * Minimum number of threads to boot the kernel
@@ -663,7 +668,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
                        struct inode *inode = file_inode(file);
                        struct address_space *mapping = file->f_mapping;
 
-                       get_file(file);
+                       vma_get_file(tmp);
                        if (tmp->vm_flags & VM_DENYWRITE)
                                atomic_dec(&inode->i_writecount);
                        i_mmap_lock_write(mapping);
@@ -785,6 +790,13 @@ static void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
 #endif
 }
 
+static void mm_init_uprobes_state(struct mm_struct *mm)
+{
+#ifdef CONFIG_UPROBES
+       mm->uprobes_state.xol_area = NULL;
+#endif
+}
+
 static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
        struct user_namespace *user_ns)
 {
@@ -806,11 +818,13 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
        mm_init_cpumask(mm);
        mm_init_aio(mm);
        mm_init_owner(mm, p);
+       RCU_INIT_POINTER(mm->exe_file, NULL);
        mmu_notifier_mm_init(mm);
        init_tlb_flush_pending(mm);
 #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS
        mm->pmd_huge_pte = NULL;
 #endif
+       mm_init_uprobes_state(mm);
 
        if (current->mm) {
                mm->flags = current->mm->flags & MMF_INIT_MASK;
@@ -1530,6 +1544,10 @@ static __latent_entropy struct task_struct *copy_process(
        if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
                return ERR_PTR(-EINVAL);
 
+       if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
+               if (!capable(CAP_SYS_ADMIN))
+                       return ERR_PTR(-EPERM);
+
        /*
         * Thread groups must share signals as well, and detached threads
         * can only be started up within the thread group.
@@ -1700,6 +1718,9 @@ static __latent_entropy struct task_struct *copy_process(
        p->sequential_io        = 0;
        p->sequential_io_avg    = 0;
 #endif
+#ifdef CONFIG_SECURITY
+       p->security = NULL;
+#endif
 
        /* Perform scheduler related setup. Assign this task to a CPU. */
        retval = sched_fork(clone_flags, p);
@@ -2325,6 +2346,12 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
        if (unshare_flags & CLONE_NEWNS)
                unshare_flags |= CLONE_FS;
 
+       if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
+               err = -EPERM;
+               if (!capable(CAP_SYS_ADMIN))
+                       goto bad_unshare_out;
+       }
+
        err = check_unshare_flags(unshare_flags);
        if (err)
                goto bad_unshare_out;