diff options
author | Mark Fasheh <mfasheh@suse.com> | 2008-07-24 12:20:14 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | 5516e5957f4b99b19fffffa53bf9fbe7cc793249 (patch) | |
tree | d5d0b0d3850fc37093300920a672b3b051c86a82 /fs/btrfs/ioctl.c | |
parent | 9652480bf48500885a30754b4a5c436b5b34456d (diff) |
Btrfs: Null terminate strings passed in from userspace
The 'char name[BTRFS_PATH_NAME_MAX]' member of struct btrfs_ioctl_vol_args
is passed directly to strlen() after being copied from user. I haven't
verified this, but in theory a userspace program could pass in an
unterminated string and cause a kernel crash as strlen walks off the end of
the array.
This patch terminates the ->name string in all btrfs ioctl functions which
currently use a 'struct btrfs_ioctl_vol_args'. Since the string is now
properly terminated, it's length will never be longer than
BTRFS_PATH_NAME_MAX so that error check has been removed.
By the way, it might be better overall to just have the ioctl pass an
unterminated string + length structure but I didn't bother with that since
it'd change the kernel/user interface.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 7d40778a90e4..5e627746c4e8 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -310,11 +310,9 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
310 | ret = -EFAULT; | 310 | ret = -EFAULT; |
311 | goto out; | 311 | goto out; |
312 | } | 312 | } |
313 | |||
314 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | ||
313 | namelen = strlen(vol_args->name); | 315 | namelen = strlen(vol_args->name); |
314 | if (namelen > BTRFS_VOL_NAME_MAX) { | ||
315 | ret = -EINVAL; | ||
316 | goto out; | ||
317 | } | ||
318 | 316 | ||
319 | mutex_lock(&root->fs_info->volume_mutex); | 317 | mutex_lock(&root->fs_info->volume_mutex); |
320 | sizestr = vol_args->name; | 318 | sizestr = vol_args->name; |
@@ -412,11 +410,8 @@ static noinline int btrfs_ioctl_snap_create(struct btrfs_root *root, | |||
412 | goto out; | 410 | goto out; |
413 | } | 411 | } |
414 | 412 | ||
413 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | ||
415 | namelen = strlen(vol_args->name); | 414 | namelen = strlen(vol_args->name); |
416 | if (namelen > BTRFS_VOL_NAME_MAX) { | ||
417 | ret = -EINVAL; | ||
418 | goto out; | ||
419 | } | ||
420 | if (strchr(vol_args->name, '/')) { | 415 | if (strchr(vol_args->name, '/')) { |
421 | ret = -EINVAL; | 416 | ret = -EINVAL; |
422 | goto out; | 417 | goto out; |
@@ -487,6 +482,7 @@ long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | |||
487 | ret = -EFAULT; | 482 | ret = -EFAULT; |
488 | goto out; | 483 | goto out; |
489 | } | 484 | } |
485 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | ||
490 | ret = btrfs_init_new_device(root, vol_args->name); | 486 | ret = btrfs_init_new_device(root, vol_args->name); |
491 | 487 | ||
492 | out: | 488 | out: |
@@ -508,6 +504,7 @@ long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | |||
508 | ret = -EFAULT; | 504 | ret = -EFAULT; |
509 | goto out; | 505 | goto out; |
510 | } | 506 | } |
507 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | ||
511 | ret = btrfs_rm_device(root, vol_args->name); | 508 | ret = btrfs_rm_device(root, vol_args->name); |
512 | 509 | ||
513 | out: | 510 | out: |