On 2019/06/06 17:05, Nikolay Borisov wrote:
>
>
> On 6.06.19 г. 10:49 ч., Naohiro Aota wrote:
>> xattr value is not NULL-terminated string. When you specify "lz" as the
>> property value, strncmp("lzo", value, 3) will try to read one byte after
>> the value buffer, causing the following OOB access. Fix this out-of-bound
>> by explicitly check the required length.
>>
>>(snip)
>>
>> Fixes: 272e5326c783 ("btrfs: prop: fix vanished compression property after failed set")
>> Fixes: 50398fde997f ("btrfs: prop: fix zstd compression parameter validation")
>> Cc: stable@xxxxxxxxxxxxxxx # 4.14+: 802a5c69584a: btrfs: prop: use common helper for type to string conversion
>> Cc: stable@xxxxxxxxxxxxxxx # 4.14+: 3dcf96c7b9fe: btrfs: drop redundant forward declaration in props.c
>> Cc: stable@xxxxxxxxxxxxxxx # 4.14+
>> Signed-off-by: Naohiro Aota <naohiro.aota@xxxxxxx>
>
> We caught that one yesterday and were testing various fixes for it
> Johannes just sent his version which IMO makes the code a bit more
> maintainable.
>
yeah, that looks good to me. It's much more easy to add new compression
type. Please pick that one.
>
>> ---
>> fs/btrfs/props.c | 12 ++++++------
>> 1 file changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
>> index a9e2e66152ee..428141bf545d 100644
>> --- a/fs/btrfs/props.c
>> +++ b/fs/btrfs/props.c
>> @@ -257,11 +257,11 @@ static int prop_compression_validate(const char *value, size_t len)
>> if (!value)
>> return 0;
>>
>> - if (!strncmp("lzo", value, 3))
>> + if (len >= 3 && !strncmp("lzo", value, 3))
>> return 0;
>> - else if (!strncmp("zlib", value, 4))
>> + else if (len >= 4 && !strncmp("zlib", value, 4))
>> return 0;
>> - else if (!strncmp("zstd", value, 4))
>> + else if (len >= 4 && !strncmp("zstd", value, 4))
>> return 0;
>>
>> return -EINVAL;
>> @@ -281,12 +281,12 @@ static int prop_compression_apply(struct inode *inode, const char *value,
>> return 0;
>> }
>>
>> - if (!strncmp("lzo", value, 3)) {
>> + if (len >= 3 && !strncmp("lzo", value, 3)) {
>> type = BTRFS_COMPRESS_LZO;
>> btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
>> - } else if (!strncmp("zlib", value, 4)) {
>> + } else if (len >= 4 && !strncmp("zlib", value, 4)) {
>> type = BTRFS_COMPRESS_ZLIB;
>> - } else if (!strncmp("zstd", value, 4)) {
>> + } else if (len >= 4 && !strncmp("zstd", value, 4)) {
>> type = BTRFS_COMPRESS_ZSTD;
>> btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
>> } else {
>
> This seems redundant as ->validates is supposed to always be called
> before calling ->apply.
>
Indeed.