]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - kernel/fork.c
Merge branch 'next' into for-linus
[net-next-2.6.git] / kernel / fork.c
index af0d0f04585ca65b0cd02629733b61bc4c74a6d0..4e8ca23c0ede9cdf57b656ff6600cfee033aa299 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/jiffies.h>
 #include <linux/tracehook.h>
 #include <linux/futex.h>
+#include <linux/compat.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/rcupdate.h>
 #include <linux/ptrace.h>
@@ -313,17 +314,20 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                file = tmp->vm_file;
                if (file) {
                        struct inode *inode = file->f_path.dentry->d_inode;
+                       struct address_space *mapping = file->f_mapping;
+
                        get_file(file);
                        if (tmp->vm_flags & VM_DENYWRITE)
                                atomic_dec(&inode->i_writecount);
-
-                       /* insert tmp into the share list, just after mpnt */
-                       spin_lock(&file->f_mapping->i_mmap_lock);
+                       spin_lock(&mapping->i_mmap_lock);
+                       if (tmp->vm_flags & VM_SHARED)
+                               mapping->i_mmap_writable++;
                        tmp->vm_truncate_count = mpnt->vm_truncate_count;
-                       flush_dcache_mmap_lock(file->f_mapping);
+                       flush_dcache_mmap_lock(mapping);
+                       /* insert tmp into the share list, just after mpnt */
                        vma_prio_tree_add(tmp, mpnt);
-                       flush_dcache_mmap_unlock(file->f_mapping);
-                       spin_unlock(&file->f_mapping->i_mmap_lock);
+                       flush_dcache_mmap_unlock(mapping);
+                       spin_unlock(&mapping->i_mmap_lock);
                }
 
                /*
@@ -518,6 +522,16 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
 {
        struct completion *vfork_done = tsk->vfork_done;
 
+       /* Get rid of any futexes when releasing the mm */
+#ifdef CONFIG_FUTEX
+       if (unlikely(tsk->robust_list))
+               exit_robust_list(tsk);
+#ifdef CONFIG_COMPAT
+       if (unlikely(tsk->compat_robust_list))
+               compat_exit_robust_list(tsk);
+#endif
+#endif
+
        /* Get rid of any cached register state */
        deactivate_mm(tsk, mm);
 
@@ -965,7 +979,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        if (atomic_read(&p->real_cred->user->processes) >=
                        p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
                if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
-                   p->real_cred->user != current->nsproxy->user_ns->root_user)
+                   p->real_cred->user != INIT_USER)
                        goto bad_fork_free;
        }
 
@@ -1323,6 +1337,21 @@ long do_fork(unsigned long clone_flags,
        int trace = 0;
        long nr;
 
+       /*
+        * Do some preliminary argument and permissions checking before we
+        * actually start allocating stuff
+        */
+       if (clone_flags & CLONE_NEWUSER) {
+               if (clone_flags & CLONE_THREAD)
+                       return -EINVAL;
+               /* hopefully this check will go away when userns support is
+                * complete
+                */
+               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||
+                               !capable(CAP_SETGID))
+                       return -EPERM;
+       }
+
        /*
         * We hope to recycle these flags after 2.6.26
         */
@@ -1367,6 +1396,7 @@ long do_fork(unsigned long clone_flags,
                        init_completion(&vfork);
                }
 
+               audit_finish_fork(p);
                tracehook_report_clone(trace, regs, clone_flags, nr, p);
 
                /*
@@ -1570,8 +1600,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
        err = -EINVAL;
        if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
                                CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
-                               CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER|
-                               CLONE_NEWNET))
+                               CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
                goto bad_unshare_out;
 
        /*