Re: [PATCH 1/2] btrfs-progs: check: Detect file extent end overflow

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 19.02.20 г. 9:04 ч., Qu Wenruo wrote:
> There is a report about tree-checker rejecting some leaves due to bad
> EXTENT_DATA.
> 
> The offending EXTENT_DATA looks like:
> 	item 72 key (1359622 EXTENT_DATA 475136) itemoff 11140 itemsize 53
> 		generation 954719 type 1 (regular)
> 		extent data disk byte 0 nr 0
> 		extent data offset 0 nr 18446744073709486080 ram 18446744073709486080
> 		extent compression 0 (none)
> 
> Add such check to both original and lowmem mode to detect such problem.
> 
> Reported-by: Samir Benmendil <me@xxxxxx>
> Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
> ---
>  check/main.c          | 4 ++++
>  check/mode-common.h   | 7 +++++++
>  check/mode-lowmem.c   | 7 +++++++
>  check/mode-original.h | 1 +
>  4 files changed, 19 insertions(+)
> 
> diff --git a/check/main.c b/check/main.c
> index d02dd1636852..f71bf4f74129 100644
> --- a/check/main.c
> +++ b/check/main.c
> @@ -597,6 +597,8 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
>  		fprintf(stderr, ", odd file extent");
>  	if (errors & I_ERR_BAD_FILE_EXTENT)
>  		fprintf(stderr, ", bad file extent");
> +	if (errors & I_ERR_FILE_EXTENT_OVERFLOW)
> +		fprintf(stderr, ", file extent end overflow");
>  	if (errors & I_ERR_FILE_EXTENT_OVERLAP)
>  		fprintf(stderr, ", file extent overlap");
>  	if (errors & I_ERR_FILE_EXTENT_TOO_LARGE)
> @@ -1595,6 +1597,8 @@ static int process_file_extent(struct btrfs_root *root,
>  		num_bytes = btrfs_file_extent_num_bytes(eb, fi);
>  		disk_bytenr = btrfs_file_extent_disk_bytenr(eb, fi);
>  		extent_offset = btrfs_file_extent_offset(eb, fi);
> +		if (u64_add_overflow(key->offset, num_bytes))
> +			rec->errors |= I_ERR_FILE_EXTENT_OVERFLOW;
>  		if (num_bytes == 0 || (num_bytes & mask))
>  			rec->errors |= I_ERR_BAD_FILE_EXTENT;
>  		if (num_bytes + extent_offset >
> diff --git a/check/mode-common.h b/check/mode-common.h
> index edf9257edaf0..daa5741e1d67 100644
> --- a/check/mode-common.h
> +++ b/check/mode-common.h
> @@ -173,4 +173,11 @@ static inline u32 btrfs_type_to_imode(u8 type)
>  
>  	return imode_by_btrfs_type[(type)];
>  }
> +
> +static inline bool u64_add_overflow(u64 a, u64 b)

Rename this to check_add_overflow and use the generic version from the
kernel :

#define check_add_overflow(a, b, d) ({          \

        typeof(a) __a = (a);                    \

        typeof(b) __b = (b);                    \

        typeof(d) __d = (d);                    \

        (void) (&__a == &__b);                  \

        (void) (&__a == __d);                   \

        __builtin_add_overflow(__a, __b, __d);  \

})

> +{
> +	if (a > (u64)-1 - b)
> +		return true;
> +	return false;
> +}
>  #endif
> diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
> index 630fabf66919..d257a44f3086 100644
> --- a/check/mode-lowmem.c
> +++ b/check/mode-lowmem.c
> @@ -2085,6 +2085,13 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_path *path,
>  		err |= INVALID_GENERATION;
>  	}
>  
> +	/* Extent end shouldn't overflow */
> +	if (u64_add_overflow(fkey.offset, extent_num_bytes)) {
> +		error(
> +	"file extent end over flow, file offset %llu extent num bytes %llu",
> +			fkey.offset, extent_num_bytes);
> +		err |= FILE_EXTENT_ERROR;
> +	}
>  	/*
>  	 * Check EXTENT_DATA csum
>  	 *
> diff --git a/check/mode-original.h b/check/mode-original.h
> index b075a95c9757..07d741f4a1b5 100644
> --- a/check/mode-original.h
> +++ b/check/mode-original.h
> @@ -186,6 +186,7 @@ struct unaligned_extent_rec_t {
>  #define I_ERR_MISMATCH_DIR_HASH		(1 << 18)
>  #define I_ERR_INVALID_IMODE		(1 << 19)
>  #define I_ERR_INVALID_GEN		(1 << 20)
> +#define I_ERR_FILE_EXTENT_OVERFLOW	(1 << 21)
>  
>  struct inode_record {
>  	struct list_head backrefs;
> 



[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux