]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/btrfs-util.c
btrfs-util: check current offset before read
[thirdparty/systemd.git] / src / shared / btrfs-util.c
index 5db88221f37f74cf90570256f8bbb1299046cb3e..d6b218d842f69189146098bf937206002bdc6c58 100644 (file)
@@ -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 = {