Merge tag 'for-6.8-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / fs / btrfs / ioctl.c
index fb2323b..ac3316e 100644 (file)
@@ -1293,6 +1293,15 @@ static noinline int __btrfs_ioctl_snap_create(struct file *file,
                         * are limited to own subvolumes only
                         */
                        ret = -EPERM;
+               } else if (btrfs_ino(BTRFS_I(src_inode)) != BTRFS_FIRST_FREE_OBJECTID) {
+                       /*
+                        * Snapshots must be made with the src_inode referring
+                        * to the subvolume inode, otherwise the permission
+                        * checking above is useless because we may have
+                        * permission on a lower directory but not the subvol
+                        * itself.
+                        */
+                       ret = -EINVAL;
                } else {
                        ret = btrfs_mksnapshot(&file->f_path, idmap,
                                               name, namelen,
@@ -4536,29 +4545,29 @@ static int btrfs_ioctl_encoded_write(struct file *file, void __user *argp, bool
        if (ret < 0)
                goto out_acct;
 
-       file_start_write(file);
-
        if (iov_iter_count(&iter) == 0) {
                ret = 0;
-               goto out_end_write;
+               goto out_iov;
        }
        pos = args.offset;
        ret = rw_verify_area(WRITE, file, &pos, args.len);
        if (ret < 0)
-               goto out_end_write;
+               goto out_iov;
 
        init_sync_kiocb(&kiocb, file);
        ret = kiocb_set_rw_flags(&kiocb, 0);
        if (ret)
-               goto out_end_write;
+               goto out_iov;
        kiocb.ki_pos = pos;
 
+       file_start_write(file);
+
        ret = btrfs_do_write_iter(&kiocb, &iter, &args);
        if (ret > 0)
                fsnotify_modify(file);
 
-out_end_write:
        file_end_write(file);
+out_iov:
        kfree(iov);
 out_acct:
        if (ret > 0)