Skip to content

Commit 125cca1

Browse files
yuwatabluca
authored andcommitted
btrfs-util: check current offset before read
Fixes #32936.
1 parent 1d640a0 commit 125cca1

File tree

1 file changed

+37
-12
lines changed

1 file changed

+37
-12
lines changed

src/shared/btrfs-util.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -262,24 +262,49 @@ static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args
262262
}
263263

264264
typedef struct BtrfsForeachIterator {
265-
const void *p;
266-
size_t i;
265+
const struct btrfs_ioctl_search_args *args;
266+
size_t offset;
267+
unsigned index;
268+
struct btrfs_ioctl_search_header *header;
269+
const void **body;
267270
} BtrfsForeachIterator;
268271

272+
static int btrfs_iterate(BtrfsForeachIterator *i) {
273+
assert(i);
274+
assert(i->args);
275+
assert(i->header);
276+
assert(i->body);
277+
278+
if (i->index >= i->args->key.nr_items)
279+
return 0; /* end */
280+
281+
assert_cc(BTRFS_SEARCH_ARGS_BUFSIZE >= sizeof(struct btrfs_ioctl_search_header));
282+
if (i->offset > BTRFS_SEARCH_ARGS_BUFSIZE - sizeof(struct btrfs_ioctl_search_header))
283+
return -EBADMSG;
284+
285+
struct btrfs_ioctl_search_header h;
286+
memcpy(&h, (const uint8_t*) i->args->buf + i->offset, sizeof(struct btrfs_ioctl_search_header));
287+
288+
if (i->offset > BTRFS_SEARCH_ARGS_BUFSIZE - sizeof(struct btrfs_ioctl_search_header) - h.len)
289+
return -EBADMSG;
290+
291+
*i->body = (const uint8_t*) i->args->buf + i->offset + sizeof(struct btrfs_ioctl_search_header);
292+
*i->header = h;
293+
i->offset += sizeof(struct btrfs_ioctl_search_header) + h.len;
294+
i->index++;
295+
296+
return 1;
297+
}
298+
269299
/* Iterates through a series of struct btrfs_file_extent_item elements. They are unfortunately not aligned,
270300
* hence we copy out the header from them */
271-
#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(sh, body, args) \
301+
#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(_sh, _body, _args) \
272302
for (BtrfsForeachIterator iterator = { \
273-
.p = ({ \
274-
memcpy(&(sh), (args).buf, sizeof(struct btrfs_ioctl_search_header)); \
275-
(body) = (const void*) ((const uint8_t*) (args).buf + sizeof(struct btrfs_ioctl_search_header)); \
276-
(args).buf; \
277-
}), \
303+
.args = &(_args), \
304+
.header = &(_sh), \
305+
.body = &(_body), \
278306
}; \
279-
iterator.i < (args).key.nr_items; \
280-
iterator.i++, \
281-
memcpy(&(sh), iterator.p = (const uint8_t*) iterator.p + sizeof(struct btrfs_ioctl_search_header) + (sh).len, sizeof(struct btrfs_ioctl_search_header)), \
282-
(body) = (const void*) ((const uint8_t*) iterator.p + sizeof(struct btrfs_ioctl_search_header)))
307+
btrfs_iterate(&iterator) > 0; )
283308

284309
int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
285310
struct btrfs_ioctl_search_args args = {

0 commit comments

Comments
 (0)