diff options
| -rw-r--r-- | fs/ext4/ioctl.c | 30 | ||||
| -rw-r--r-- | fs/ext4/move_extent.c | 7 |
2 files changed, 25 insertions, 12 deletions
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 31e5ee0c858f..b63d193126db 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -221,32 +221,38 @@ setversion_out: | |||
| 221 | struct file *donor_filp; | 221 | struct file *donor_filp; |
| 222 | int err; | 222 | int err; |
| 223 | 223 | ||
| 224 | if (!(filp->f_mode & FMODE_READ) || | ||
| 225 | !(filp->f_mode & FMODE_WRITE)) | ||
| 226 | return -EBADF; | ||
| 227 | |||
| 224 | if (copy_from_user(&me, | 228 | if (copy_from_user(&me, |
| 225 | (struct move_extent __user *)arg, sizeof(me))) | 229 | (struct move_extent __user *)arg, sizeof(me))) |
| 226 | return -EFAULT; | 230 | return -EFAULT; |
| 231 | me.moved_len = 0; | ||
| 227 | 232 | ||
| 228 | donor_filp = fget(me.donor_fd); | 233 | donor_filp = fget(me.donor_fd); |
| 229 | if (!donor_filp) | 234 | if (!donor_filp) |
| 230 | return -EBADF; | 235 | return -EBADF; |
| 231 | 236 | ||
| 232 | if (!capable(CAP_DAC_OVERRIDE)) { | 237 | if (!(donor_filp->f_mode & FMODE_WRITE)) { |
| 233 | if ((current->real_cred->fsuid != inode->i_uid) || | 238 | err = -EBADF; |
| 234 | !(inode->i_mode & S_IRUSR) || | 239 | goto mext_out; |
| 235 | !(donor_filp->f_dentry->d_inode->i_mode & | ||
| 236 | S_IRUSR)) { | ||
| 237 | fput(donor_filp); | ||
| 238 | return -EACCES; | ||
| 239 | } | ||
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | me.moved_len = 0; | 242 | err = mnt_want_write(filp->f_path.mnt); |
| 243 | if (err) | ||
| 244 | goto mext_out; | ||
| 245 | |||
| 243 | err = ext4_move_extents(filp, donor_filp, me.orig_start, | 246 | err = ext4_move_extents(filp, donor_filp, me.orig_start, |
| 244 | me.donor_start, me.len, &me.moved_len); | 247 | me.donor_start, me.len, &me.moved_len); |
| 245 | fput(donor_filp); | 248 | mnt_drop_write(filp->f_path.mnt); |
| 249 | if (me.moved_len > 0) | ||
| 250 | file_remove_suid(donor_filp); | ||
| 246 | 251 | ||
| 247 | if (copy_to_user((struct move_extent *)arg, &me, sizeof(me))) | 252 | if (copy_to_user((struct move_extent *)arg, &me, sizeof(me))) |
| 248 | return -EFAULT; | 253 | err = -EFAULT; |
| 249 | 254 | mext_out: | |
| 255 | fput(donor_filp); | ||
| 250 | return err; | 256 | return err; |
| 251 | } | 257 | } |
| 252 | 258 | ||
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index cad1e2edda7e..82c415be87a4 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
| @@ -957,6 +957,13 @@ mext_check_arguments(struct inode *orig_inode, | |||
| 957 | return -EINVAL; | 957 | return -EINVAL; |
| 958 | } | 958 | } |
| 959 | 959 | ||
| 960 | if (donor_inode->i_mode & (S_ISUID|S_ISGID)) { | ||
| 961 | ext4_debug("ext4 move extent: suid or sgid is set" | ||
| 962 | " to donor file [ino:orig %lu, donor %lu]\n", | ||
| 963 | orig_inode->i_ino, donor_inode->i_ino); | ||
| 964 | return -EINVAL; | ||
| 965 | } | ||
| 966 | |||
| 960 | /* Ext4 move extent does not support swapfile */ | 967 | /* Ext4 move extent does not support swapfile */ |
| 961 | if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { | 968 | if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { |
| 962 | ext4_debug("ext4 move extent: The argument files should " | 969 | ext4_debug("ext4 move extent: The argument files should " |
