mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	btrfs: tree-checker: add inode extref checks
Like inode refs, inode extrefs have a variable length name, which means we have to do a proper check to make sure no header nor name can exceed the item limits. The check itself is very similar to check_inode_ref(), just a different structure (btrfs_inode_extref vs btrfs_inode_ref). Reviewed-by: Filipe Manana <fdmanana@suse.com> 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
							
								
									0dc93e4652
								
							
						
					
					
						commit
						aab9458b9f
					
				
					 1 changed files with 37 additions and 0 deletions
				
			
		| 
						 | 
					@ -183,6 +183,7 @@ static bool check_prev_ino(struct extent_buffer *leaf,
 | 
				
			||||||
	/* Only these key->types needs to be checked */
 | 
						/* Only these key->types needs to be checked */
 | 
				
			||||||
	ASSERT(key->type == BTRFS_XATTR_ITEM_KEY ||
 | 
						ASSERT(key->type == BTRFS_XATTR_ITEM_KEY ||
 | 
				
			||||||
	       key->type == BTRFS_INODE_REF_KEY ||
 | 
						       key->type == BTRFS_INODE_REF_KEY ||
 | 
				
			||||||
 | 
						       key->type == BTRFS_INODE_EXTREF_KEY ||
 | 
				
			||||||
	       key->type == BTRFS_DIR_INDEX_KEY ||
 | 
						       key->type == BTRFS_DIR_INDEX_KEY ||
 | 
				
			||||||
	       key->type == BTRFS_DIR_ITEM_KEY ||
 | 
						       key->type == BTRFS_DIR_ITEM_KEY ||
 | 
				
			||||||
	       key->type == BTRFS_EXTENT_DATA_KEY);
 | 
						       key->type == BTRFS_EXTENT_DATA_KEY);
 | 
				
			||||||
| 
						 | 
					@ -1782,6 +1783,39 @@ static int check_inode_ref(struct extent_buffer *leaf,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int check_inode_extref(struct extent_buffer *leaf,
 | 
				
			||||||
 | 
								      struct btrfs_key *key, struct btrfs_key *prev_key,
 | 
				
			||||||
 | 
								      int slot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long ptr = btrfs_item_ptr_offset(leaf, slot);
 | 
				
			||||||
 | 
						unsigned long end = ptr + btrfs_item_size(leaf, slot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (unlikely(!check_prev_ino(leaf, key, slot, prev_key)))
 | 
				
			||||||
 | 
							return -EUCLEAN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (ptr < end) {
 | 
				
			||||||
 | 
							struct btrfs_inode_extref *extref = (struct btrfs_inode_extref *)ptr;
 | 
				
			||||||
 | 
							u16 namelen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (unlikely(ptr + sizeof(*extref)) > end) {
 | 
				
			||||||
 | 
								inode_ref_err(leaf, slot,
 | 
				
			||||||
 | 
								"inode extref overflow, ptr %lu end %lu inode_extref size %zu",
 | 
				
			||||||
 | 
									      ptr, end, sizeof(*extref));
 | 
				
			||||||
 | 
								return -EUCLEAN;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							namelen = btrfs_inode_extref_name_len(leaf, extref);
 | 
				
			||||||
 | 
							if (unlikely(ptr + sizeof(*extref) + namelen > end)) {
 | 
				
			||||||
 | 
								inode_ref_err(leaf, slot,
 | 
				
			||||||
 | 
									"inode extref overflow, ptr %lu end %lu namelen %u",
 | 
				
			||||||
 | 
									ptr, end, namelen);
 | 
				
			||||||
 | 
								return -EUCLEAN;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ptr += sizeof(*extref) + namelen;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int check_raid_stripe_extent(const struct extent_buffer *leaf,
 | 
					static int check_raid_stripe_extent(const struct extent_buffer *leaf,
 | 
				
			||||||
				    const struct btrfs_key *key, int slot)
 | 
									    const struct btrfs_key *key, int slot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1893,6 +1927,9 @@ static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf,
 | 
				
			||||||
	case BTRFS_INODE_REF_KEY:
 | 
						case BTRFS_INODE_REF_KEY:
 | 
				
			||||||
		ret = check_inode_ref(leaf, key, prev_key, slot);
 | 
							ret = check_inode_ref(leaf, key, prev_key, slot);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case BTRFS_INODE_EXTREF_KEY:
 | 
				
			||||||
 | 
							ret = check_inode_extref(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