]> exis.tech > repos - linux.git/commitdiff
btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8
authorYou-Kai Zheng <ykzheng@synology.com>
Tue, 16 Jun 2026 10:39:07 +0000 (18:39 +0800)
committerDavid Sterba <dsterba@suse.com>
Tue, 14 Jul 2026 05:02:39 +0000 (07:02 +0200)
The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is
declared as __u64[], but it holds a packed byte stream of search results,
where all offsets into the buffer are in bytes.

Declaring buf as __u64[] makes it easy for user space to write incorrect
pointer arithmetic: adding a byte offset directly to a __u64 pointer
scales the offset by 8, landing at byte position offset*8 instead of
offset.

This recently caused an infinite loop in btrfs-progs: the accessor read
all-zero data from misaddressed items, which fed zeroed search keys back
into the ioctl loop and spun forever. The issue was worked around at the
time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854:
"btrfs-progs: temporarily disable usage of v2 of search tree ioctl").

The kernel side already treats buf as a byte buffer, so change the
declaration to __u8[] to match the actual semantics and prevent similar
misuse in user space. The change is ABI compatible: both the structure size
and alignment are unchanged.

Fixes: cc68a8a5a433 ("btrfs: new ioctl TREE_SEARCH_V2")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: You-Kai Zheng <ykzheng@synology.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
include/uapi/linux/btrfs.h

index 9b576603b3f14cc3c0bff28ee7173c5152787938..0a13baf3d8d1446d5a51a9cfecd8087e8ce3d2da 100644 (file)
@@ -598,7 +598,7 @@ struct btrfs_ioctl_search_args_v2 {
        __u64 buf_size;            /* in - size of buffer
                                            * out - on EOVERFLOW: needed size
                                            *       to store item */
-       __u64 buf[];                       /* out - found items */
+       __u8 buf[];                        /* out - found items */
 };
 
 /* With a @src_length of zero, the range from @src_offset->EOF is cloned! */