| From foo@baz Fri Feb 23 12:01:27 CET 2018 |
| From: Nikolay Borisov <nborisov@suse.com> |
| Date: Fri, 1 Dec 2017 11:19:42 +0200 |
| Subject: btrfs: Fix possible off-by-one in btrfs_search_path_in_tree |
| |
| From: Nikolay Borisov <nborisov@suse.com> |
| |
| |
| [ Upstream commit c8bcbfbd239ed60a6562964b58034ac8a25f4c31 ] |
| |
| 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> |
| |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/btrfs/ioctl.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/fs/btrfs/ioctl.c |
| +++ b/fs/btrfs/ioctl.c |
| @@ -2233,7 +2233,7 @@ static noinline int btrfs_search_path_in |
| 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; |