fuse: copy_file_range should truncate cache
[linux-2.6-microblaze.git] / kernel / fork.c
index d2a967b..8c700f8 100644 (file)
@@ -361,6 +361,7 @@ struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig)
        if (new) {
                *new = *orig;
                INIT_LIST_HEAD(&new->anon_vma_chain);
+               new->vm_next = new->vm_prev = NULL;
        }
        return new;
 }
@@ -553,14 +554,15 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
                if (retval)
                        goto fail_nomem_anon_vma_fork;
                if (tmp->vm_flags & VM_WIPEONFORK) {
-                       /* VM_WIPEONFORK gets a clean slate in the child. */
+                       /*
+                        * VM_WIPEONFORK gets a clean slate in the child.
+                        * Don't prepare anon_vma until fault since we don't
+                        * copy page for current vma.
+                        */
                        tmp->anon_vma = NULL;
-                       if (anon_vma_prepare(tmp))
-                               goto fail_nomem_anon_vma_fork;
                } else if (anon_vma_fork(tmp, mpnt))
                        goto fail_nomem_anon_vma_fork;
                tmp->vm_flags &= ~(VM_LOCKED | VM_LOCKONFAULT);
-               tmp->vm_next = tmp->vm_prev = NULL;
                file = tmp->vm_file;
                if (file) {
                        struct inode *inode = file_inode(file);
@@ -2603,6 +2605,14 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
        struct clone_args args;
        pid_t *kset_tid = kargs->set_tid;
 
+       BUILD_BUG_ON(offsetofend(struct clone_args, tls) !=
+                    CLONE_ARGS_SIZE_VER0);
+       BUILD_BUG_ON(offsetofend(struct clone_args, set_tid_size) !=
+                    CLONE_ARGS_SIZE_VER1);
+       BUILD_BUG_ON(offsetofend(struct clone_args, cgroup) !=
+                    CLONE_ARGS_SIZE_VER2);
+       BUILD_BUG_ON(sizeof(struct clone_args) != CLONE_ARGS_SIZE_VER2);
+
        if (unlikely(usize > PAGE_SIZE))
                return -E2BIG;
        if (unlikely(usize < CLONE_ARGS_SIZE_VER0))
@@ -2629,7 +2639,8 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
                     !valid_signal(args.exit_signal)))
                return -EINVAL;
 
-       if ((args.flags & CLONE_INTO_CGROUP) && args.cgroup < 0)
+       if ((args.flags & CLONE_INTO_CGROUP) &&
+           (args.cgroup > INT_MAX || usize < CLONE_ARGS_SIZE_VER2))
                return -EINVAL;
 
        *kargs = (struct kernel_clone_args){