struct btrfs_root_ref *rref;
struct extent_buffer *leaf;
unsigned long item_off;
- unsigned long item_len;
int slot;
int ret = 0;
btrfs_item_key_to_cpu(leaf, &key, slot);
if (key.objectid == subvol_info->treeid &&
key.type == BTRFS_ROOT_BACKREF_KEY) {
+ u16 name_len;
+
subvol_info->parent_id = key.offset;
rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref);
+ name_len = btrfs_root_ref_name_len(leaf, rref);
subvol_info->dirid = btrfs_root_ref_dirid(leaf, rref);
- item_off = btrfs_item_ptr_offset(leaf, slot)
- + sizeof(struct btrfs_root_ref);
- item_len = btrfs_item_size(leaf, slot)
- - sizeof(struct btrfs_root_ref);
+ item_off = btrfs_item_ptr_offset(leaf, slot) + sizeof(*rref);
read_extent_buffer(leaf, subvol_info->name,
- item_off, item_len);
+ item_off, name_len);
} else {
ret = -ENOENT;
goto out;
return 0;
}
+static int check_root_ref(struct extent_buffer *leaf, struct btrfs_key *key, int slot)
+{
+ struct btrfs_root_ref *rref;
+ u32 item_size = btrfs_item_size(leaf, slot);
+ u32 name_len;
+
+ if (unlikely(item_size <= sizeof(*rref))) {
+ generic_err(leaf, slot,
+ "invalid root ref item size for key type %u, have %u expect > %zu",
+ key->type, item_size, sizeof(*rref));
+ return -EUCLEAN;
+ }
+
+ rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref);
+ name_len = btrfs_root_ref_name_len(leaf, rref);
+ if (unlikely(name_len > BTRFS_NAME_LEN)) {
+ generic_err(leaf, slot,
+ "root ref name too long for key type %u, have %u max %u",
+ key->type, name_len, BTRFS_NAME_LEN);
+ return -EUCLEAN;
+ }
+ if (unlikely(item_size != sizeof(*rref) + name_len)) {
+ generic_err(leaf, slot,
+ "invalid root ref item size for key type %u, have %u expect %zu",
+ key->type, item_size, sizeof(*rref) + name_len);
+ return -EUCLEAN;
+ }
+
+ return 0;
+}
+
__printf(3,4)
__cold
static void extent_err(const struct extent_buffer *eb, int slot,
case BTRFS_ROOT_ITEM_KEY:
ret = check_root_item(leaf, key, slot);
break;
+ case BTRFS_ROOT_REF_KEY:
+ case BTRFS_ROOT_BACKREF_KEY:
+ ret = check_root_ref(leaf, key, slot);
+ break;
case BTRFS_EXTENT_ITEM_KEY:
case BTRFS_METADATA_ITEM_KEY:
ret = check_extent_item(leaf, key, slot, prev_key);