diff options
author | Lukas Czerner <lczerner@redhat.com> | 2011-09-05 10:34:54 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2011-10-20 12:10:40 -0400 |
commit | f4c697e6406da5dd445eda8d923c53e1138793dd (patch) | |
tree | a572fcd0b9db22177d74c8fd3276ccb6a05c028c | |
parent | 008873eafbc77deb1702aedece33756c58486c6a (diff) |
btrfs: return EINVAL if start > total_bytes in fitrim ioctl
We should retirn EINVAL if the start is beyond the end of the file
system in the btrfs_ioctl_fitrim(). Fix that by adding the appropriate
check for it.
Also in the btrfs_trim_fs() it is possible that len+start might overflow
if big values are passed. Fix it by decrementing the len so that start+len
is equal to the file system size in the worst case.
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
-rw-r--r-- | fs/btrfs/ioctl.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index d524b6697ad9..136a2f980e21 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -282,6 +282,7 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
282 | struct fstrim_range range; | 282 | struct fstrim_range range; |
283 | u64 minlen = ULLONG_MAX; | 283 | u64 minlen = ULLONG_MAX; |
284 | u64 num_devices = 0; | 284 | u64 num_devices = 0; |
285 | u64 total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
285 | int ret; | 286 | int ret; |
286 | 287 | ||
287 | if (!capable(CAP_SYS_ADMIN)) | 288 | if (!capable(CAP_SYS_ADMIN)) |
@@ -300,12 +301,15 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
300 | } | 301 | } |
301 | } | 302 | } |
302 | rcu_read_unlock(); | 303 | rcu_read_unlock(); |
304 | |||
303 | if (!num_devices) | 305 | if (!num_devices) |
304 | return -EOPNOTSUPP; | 306 | return -EOPNOTSUPP; |
305 | |||
306 | if (copy_from_user(&range, arg, sizeof(range))) | 307 | if (copy_from_user(&range, arg, sizeof(range))) |
307 | return -EFAULT; | 308 | return -EFAULT; |
309 | if (range.start > total_bytes) | ||
310 | return -EINVAL; | ||
308 | 311 | ||
312 | range.len = min(range.len, total_bytes - range.start); | ||
309 | range.minlen = max(range.minlen, minlen); | 313 | range.minlen = max(range.minlen, minlen); |
310 | ret = btrfs_trim_fs(root, &range); | 314 | ret = btrfs_trim_fs(root, &range); |
311 | if (ret < 0) | 315 | if (ret < 0) |