mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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
					
				
					 1 changed files with 53 additions and 0 deletions
				
			
		| 
						 | 
					@ -1247,6 +1247,56 @@ static int check_extent_data_ref(struct extent_buffer *leaf,
 | 
				
			||||||
	return 0;
 | 
						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.
 | 
					 * 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:
 | 
						case BTRFS_XATTR_ITEM_KEY:
 | 
				
			||||||
		ret = check_dir_item(leaf, key, prev_key, slot);
 | 
							ret = check_dir_item(leaf, key, prev_key, slot);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case BTRFS_INODE_REF_KEY:
 | 
				
			||||||
 | 
							ret = check_inode_ref(leaf, key, prev_key, slot);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case BTRFS_BLOCK_GROUP_ITEM_KEY:
 | 
						case BTRFS_BLOCK_GROUP_ITEM_KEY:
 | 
				
			||||||
		ret = check_block_group_item(leaf, key, slot);
 | 
							ret = check_block_group_item(leaf, key, slot);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue