diff options
author | Nikolay Borisov <nborisov@suse.com> | 2017-12-01 11:19:42 +0200 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-12-07 00:35:15 +0100 |
commit | c8bcbfbd239ed60a6562964b58034ac8a25f4c31 (patch) | |
tree | 28650c41a17935d5c3a1483adb6ccdefe9f87760 /fs | |
parent | 1b9e619c5bc8235cfba3dc4ced2fb0e3554a05d4 (diff) | |
download | linux-stable-c8bcbfbd239ed60a6562964b58034ac8a25f4c31.tar.gz linux-stable-c8bcbfbd239ed60a6562964b58034ac8a25f4c31.tar.bz2 linux-stable-c8bcbfbd239ed60a6562964b58034ac8a25f4c31.zip |
btrfs: Fix possible off-by-one in btrfs_search_path_in_tree
The name char array passed to btrfs_search_path_in_tree is of size
BTRFS_INO_LOOKUP_PATH_MAX (4080). So the actual accessible char indexes
are in the range of [0, 4079]. Currently the code uses the define but this
represents an off-by-one.
Implications:
Size of btrfs_ioctl_ino_lookup_args is 4096, so the new byte will be
written to extra space, not some padding that could be provided by the
allocator.
btrfs-progs store the arguments on stack, but kernel does own copy of
the ioctl buffer and the off-by-one overwrite does not affect userspace,
but the ending 0 might be lost.
Kernel ioctl buffer is allocated dynamically so we're overwriting
somebody else's memory, and the ioctl is privileged if args.objectid is
not 256. Which is in most cases, but resolving a subvolume stored in
another directory will trigger that path.
Before this patch the buffer was one byte larger, but then the -1 was
not added.
Fixes: ac8e9819d71f907 ("Btrfs: add search and inode lookup ioctls")
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ added implications ]
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ioctl.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index fd172a93d11a..1a508fff7afe 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2206,7 +2206,7 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info, if (!path) return -ENOMEM; - ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX]; + ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX - 1]; key.objectid = tree_id; key.type = BTRFS_ROOT_ITEM_KEY; |