Re: [PATCH] btrfs: correctly validate compression type

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

 



On 2019/06/06 17:01, Johannes Thumshirn wrote:
> Nikolay reported the following KASAN splat when running btrfs/048:
> 
(snip)
> 
> This is caused by supplying a too short compression value ('lz') in the
> test-case and comparing it to 'lzo' with strncmp() and a length of 3.
> strncmp() read past the 'lz' when looking for the 'o' and thus caused an
> out-of-bounds read.
> 
> Introduce a new check 'btrfs_compress_is_valid_type()' which not only
> checks the user-supplied value against known compression types, but also
> employs checks for too short values.
> 
> Fixes: 272e5326c783 ("btrfs: prop: fix vanished compression property after failed set")
> Reported-by: Nikolay Borisov <nborisov@xxxxxxxx>
> Signed-off-by: Johannes Thumshirn <jthumshirn@xxxxxxx>
> ---
>   fs/btrfs/compression.c | 16 ++++++++++++++++
>   fs/btrfs/compression.h |  1 +
>   fs/btrfs/props.c       |  6 +-----
>   3 files changed, 18 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
> index 66e21a4e9ea2..d21ae92c172c 100644
> --- a/fs/btrfs/compression.c
> +++ b/fs/btrfs/compression.c
> @@ -43,6 +43,22 @@ const char* btrfs_compress_type2str(enum btrfs_compression_type type)
>   	return NULL;
>   }
>   
> +bool btrfs_compress_is_valid_type(const char *str, size_t len)
> +{
> +	int i;
> +
> +	for (i = 1; i < ARRAY_SIZE(btrfs_compress_types); i++) {
> +		size_t comp_len = strlen(btrfs_compress_types[i]);
> +
> +		if (comp_len != len)

Should this be "if (comp_len > len)"?

a7164fa4e055 ("btrfs: prepare for extensions in compression options") 
allowed compression property to have compression options. If we have the 
options, we will have "len" larger than "comp_len".

> +			continue;
> +
> +		if (!strncmp(btrfs_compress_types[i], str, comp_len))
> +			return true;
> +	}
> +	return false;
> +}
> +
>   static int btrfs_decompress_bio(struct compressed_bio *cb);
>   
>   static inline int compressed_bio_size(struct btrfs_fs_info *fs_info,
> diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h
> index 191e5f4e3523..2035b8eb1290 100644
> --- a/fs/btrfs/compression.h
> +++ b/fs/btrfs/compression.h
> @@ -173,6 +173,7 @@ extern const struct btrfs_compress_op btrfs_lzo_compress;
>   extern const struct btrfs_compress_op btrfs_zstd_compress;
>   
>   const char* btrfs_compress_type2str(enum btrfs_compression_type type);
> +bool btrfs_compress_is_valid_type(const char *str, size_t len);
>   
>   int btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end);
>   
> diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
> index a9e2e66152ee..af109c0ba720 100644
> --- a/fs/btrfs/props.c
> +++ b/fs/btrfs/props.c
> @@ -257,11 +257,7 @@ static int prop_compression_validate(const char *value, size_t len)
>   	if (!value)
>   		return 0;
>   
> -	if (!strncmp("lzo", value, 3))
> -		return 0;
> -	else if (!strncmp("zlib", value, 4))
> -		return 0;
> -	else if (!strncmp("zstd", value, 4))
> +	if (btrfs_compress_is_valid_type(value, len))
>   		return 0;
>   
>   	return -EINVAL;
> 





[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