From 125cca1b51e19d9209a229fca4fb9d94d34c3e78 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 21 May 2024 01:34:34 +0900 Subject: [PATCH] btrfs-util: check current offset before read Fixes #32936. --- src/shared/btrfs-util.c | 49 +++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c index 5db88221f37..d6b218d842f 100644 --- a/src/shared/btrfs-util.c +++ b/src/shared/btrfs-util.c @@ -262,24 +262,49 @@ static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args } typedef struct BtrfsForeachIterator { - const void *p; - size_t i; + const struct btrfs_ioctl_search_args *args; + size_t offset; + unsigned index; + struct btrfs_ioctl_search_header *header; + const void **body; } BtrfsForeachIterator; +static int btrfs_iterate(BtrfsForeachIterator *i) { + assert(i); + assert(i->args); + assert(i->header); + assert(i->body); + + if (i->index >= i->args->key.nr_items) + return 0; /* end */ + + assert_cc(BTRFS_SEARCH_ARGS_BUFSIZE >= sizeof(struct btrfs_ioctl_search_header)); + if (i->offset > BTRFS_SEARCH_ARGS_BUFSIZE - sizeof(struct btrfs_ioctl_search_header)) + return -EBADMSG; + + struct btrfs_ioctl_search_header h; + memcpy(&h, (const uint8_t*) i->args->buf + i->offset, sizeof(struct btrfs_ioctl_search_header)); + + if (i->offset > BTRFS_SEARCH_ARGS_BUFSIZE - sizeof(struct btrfs_ioctl_search_header) - h.len) + return -EBADMSG; + + *i->body = (const uint8_t*) i->args->buf + i->offset + sizeof(struct btrfs_ioctl_search_header); + *i->header = h; + i->offset += sizeof(struct btrfs_ioctl_search_header) + h.len; + i->index++; + + return 1; +} + /* Iterates through a series of struct btrfs_file_extent_item elements. They are unfortunately not aligned, * hence we copy out the header from them */ -#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(sh, body, args) \ +#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(_sh, _body, _args) \ for (BtrfsForeachIterator iterator = { \ - .p = ({ \ - memcpy(&(sh), (args).buf, sizeof(struct btrfs_ioctl_search_header)); \ - (body) = (const void*) ((const uint8_t*) (args).buf + sizeof(struct btrfs_ioctl_search_header)); \ - (args).buf; \ - }), \ + .args = &(_args), \ + .header = &(_sh), \ + .body = &(_body), \ }; \ - iterator.i < (args).key.nr_items; \ - iterator.i++, \ - memcpy(&(sh), iterator.p = (const uint8_t*) iterator.p + sizeof(struct btrfs_ioctl_search_header) + (sh).len, sizeof(struct btrfs_ioctl_search_header)), \ - (body) = (const void*) ((const uint8_t*) iterator.p + sizeof(struct btrfs_ioctl_search_header))) + btrfs_iterate(&iterator) > 0; ) int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) { struct btrfs_ioctl_search_args args = { -- 2.47.3