btrfs: tree-checker: Add check for INODE_REF
For INODE_REF we will check: - Objectid (ino) against previous key To detect missing INODE_ITEM. - No overflow/padding in the data payload Much like DIR_ITEM, but with less members to check. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
c18679ebd8
commit
71bf92a9b8
@ -1247,6 +1247,56 @@ static int check_extent_data_ref(struct extent_buffer *leaf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define inode_ref_err(fs_info, eb, slot, fmt, args...) \
|
||||
inode_item_err(fs_info, eb, slot, fmt, ##args)
|
||||
static int check_inode_ref(struct extent_buffer *leaf,
|
||||
struct btrfs_key *key, struct btrfs_key *prev_key,
|
||||
int slot)
|
||||
{
|
||||
struct btrfs_inode_ref *iref;
|
||||
unsigned long ptr;
|
||||
unsigned long end;
|
||||
|
||||
/* namelen can't be 0, so item_size == sizeof() is also invalid */
|
||||
if (btrfs_item_size_nr(leaf, slot) <= sizeof(*iref)) {
|
||||
inode_ref_err(fs_info, leaf, slot,
|
||||
"invalid item size, have %u expect (%zu, %u)",
|
||||
btrfs_item_size_nr(leaf, slot),
|
||||
sizeof(*iref), BTRFS_LEAF_DATA_SIZE(leaf->fs_info));
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
ptr = btrfs_item_ptr_offset(leaf, slot);
|
||||
end = ptr + btrfs_item_size_nr(leaf, slot);
|
||||
while (ptr < end) {
|
||||
u16 namelen;
|
||||
|
||||
if (ptr + sizeof(iref) > end) {
|
||||
inode_ref_err(fs_info, leaf, slot,
|
||||
"inode ref overflow, ptr %lu end %lu inode_ref_size %zu",
|
||||
ptr, end, sizeof(iref));
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
iref = (struct btrfs_inode_ref *)ptr;
|
||||
namelen = btrfs_inode_ref_name_len(leaf, iref);
|
||||
if (ptr + sizeof(*iref) + namelen > end) {
|
||||
inode_ref_err(fs_info, leaf, slot,
|
||||
"inode ref overflow, ptr %lu end %lu namelen %u",
|
||||
ptr, end, namelen);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: In theory we should record all found index numbers
|
||||
* to find any duplicated indexes, but that will be too time
|
||||
* consuming for inodes with too many hard links.
|
||||
*/
|
||||
ptr += sizeof(*iref) + namelen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common point to switch the item-specific validation.
|
||||
*/
|
||||
@ -1269,6 +1319,9 @@ static int check_leaf_item(struct extent_buffer *leaf,
|
||||
case BTRFS_XATTR_ITEM_KEY:
|
||||
ret = check_dir_item(leaf, key, prev_key, slot);
|
||||
break;
|
||||
case BTRFS_INODE_REF_KEY:
|
||||
ret = check_inode_ref(leaf, key, prev_key, slot);
|
||||
break;
|
||||
case BTRFS_BLOCK_GROUP_ITEM_KEY:
|
||||
ret = check_block_group_item(leaf, key, slot);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user