for-6.17-rc6-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmjPff0ACgkQxWXV+ddt WDvaVRAAqcPlR07B5Y1S+73JlqVXx5g9S77uarkn48FS5OGJ97ad7NFF79LdFKaQ d5OpD2aZRzi+XLQTlD7Wz9udmr2OvHLnTih6E6KOa7ukL+bJMsK6CXw4usLW5ke0 nHNPNCLnEtIbQ5hKFpsjfsUrJaNtGcFNoWlnkl0iG1E0vjJQFBYqTNzBytv/ygc/ jVDdoftA7vqnUeXemVGhnfvLqyP5g374jnUB3CIejMQfzSJXCS07DXwmn/eeRoxl HdJre+kjavV3WL/fvAqq0f6wEBlYRXXiLUnSt2xRr5a70svy0eWhx8ggE6gBqlyR fo4UC8hsETZdQAW35ZgUfJBtUVqx+bwNLZ5xVFlDKv8uix7B9x7Fgcmhsin+GovN JowBYe28FTctU4x3IBqyweXZOn2815HvvZlIbU/D9jVSB7RSQ/2nUKAec1tYBk2G dy9TRxxE+N3/csJ3J+VqvFEMnGorVDN1GBXFPwIgy2OTpNi6dM7s3909lO2ebp2+ Kw2vBFtwEVdGk7ZkYVkHtsPa/Rn+uXLSCp+m08eqIJKTPxbTn2W6XXsoptHt5iXL t43oRP/wq9qUKgYJUd8242nQp/Sf+zEvIjHYDpbsDHajPsTfUo0nuCN8ZojceWat RRJclWk7KXdicQT4JiWp19mQakn9gjM+vOoMriGZwRf4ZGkO1PE= =Oj5R -----END PGP SIGNATURE----- Merge tag 'for-6.17-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux Pull a few more btrfs fixes from David Sterba: - in tree-checker, fix wrong size of check for inode ref item - in ref-verify, handle combination of mount options that allow partially damaged extent tree (reported by syzbot) - additional validation of compression mount option to catch invalid string as level * tag 'for-6.17-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: reject invalid compression level btrfs: ref-verify: handle damaged extent root tree btrfs: tree-checker: fix the incorrect inode ref size check
This commit is contained in:
commit
f975f08c2e
|
@ -1616,25 +1616,29 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Convert the compression suffix (eg. after "zlib" starting with ":") to
|
||||
* level, unrecognized string will set the default level. Negative level
|
||||
* numbers are allowed.
|
||||
* Convert the compression suffix (eg. after "zlib" starting with ":") to level.
|
||||
*
|
||||
* If the resulting level exceeds the algo's supported levels, it will be clamped.
|
||||
*
|
||||
* Return <0 if no valid string can be found.
|
||||
* Return 0 if everything is fine.
|
||||
*/
|
||||
int btrfs_compress_str2level(unsigned int type, const char *str)
|
||||
int btrfs_compress_str2level(unsigned int type, const char *str, int *level_ret)
|
||||
{
|
||||
int level = 0;
|
||||
int ret;
|
||||
|
||||
if (!type)
|
||||
if (!type) {
|
||||
*level_ret = btrfs_compress_set_level(type, level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (str[0] == ':') {
|
||||
ret = kstrtoint(str + 1, 10, &level);
|
||||
if (ret)
|
||||
level = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
level = btrfs_compress_set_level(type, level);
|
||||
|
||||
return level;
|
||||
*level_ret = btrfs_compress_set_level(type, level);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ void btrfs_submit_compressed_write(struct btrfs_ordered_extent *ordered,
|
|||
bool writeback);
|
||||
void btrfs_submit_compressed_read(struct btrfs_bio *bbio);
|
||||
|
||||
int btrfs_compress_str2level(unsigned int type, const char *str);
|
||||
int btrfs_compress_str2level(unsigned int type, const char *str, int *level_ret);
|
||||
|
||||
struct folio *btrfs_alloc_compr_folio(void);
|
||||
void btrfs_free_compr_folio(struct folio *folio);
|
||||
|
|
|
@ -980,11 +980,18 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
|
|||
if (!btrfs_test_opt(fs_info, REF_VERIFY))
|
||||
return 0;
|
||||
|
||||
extent_root = btrfs_extent_root(fs_info, 0);
|
||||
/* If the extent tree is damaged we cannot ignore it (IGNOREBADROOTS). */
|
||||
if (IS_ERR(extent_root)) {
|
||||
btrfs_warn(fs_info, "ref-verify: extent tree not available, disabling");
|
||||
btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
extent_root = btrfs_extent_root(fs_info, 0);
|
||||
eb = btrfs_read_lock_root_node(extent_root);
|
||||
level = btrfs_header_level(eb);
|
||||
path->nodes[level] = eb;
|
||||
|
|
|
@ -276,6 +276,7 @@ static int btrfs_parse_compress(struct btrfs_fs_context *ctx,
|
|||
const struct fs_parameter *param, int opt)
|
||||
{
|
||||
const char *string = param->string;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Provide the same semantics as older kernels that don't use fs
|
||||
|
@ -294,15 +295,19 @@ static int btrfs_parse_compress(struct btrfs_fs_context *ctx,
|
|||
btrfs_clear_opt(ctx->mount_opt, NODATASUM);
|
||||
} else if (btrfs_match_compress_type(string, "zlib", true)) {
|
||||
ctx->compress_type = BTRFS_COMPRESS_ZLIB;
|
||||
ctx->compress_level = btrfs_compress_str2level(BTRFS_COMPRESS_ZLIB,
|
||||
string + 4);
|
||||
ret = btrfs_compress_str2level(BTRFS_COMPRESS_ZLIB, string + 4,
|
||||
&ctx->compress_level);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
btrfs_set_opt(ctx->mount_opt, COMPRESS);
|
||||
btrfs_clear_opt(ctx->mount_opt, NODATACOW);
|
||||
btrfs_clear_opt(ctx->mount_opt, NODATASUM);
|
||||
} else if (btrfs_match_compress_type(string, "lzo", true)) {
|
||||
ctx->compress_type = BTRFS_COMPRESS_LZO;
|
||||
ctx->compress_level = btrfs_compress_str2level(BTRFS_COMPRESS_LZO,
|
||||
string + 3);
|
||||
ret = btrfs_compress_str2level(BTRFS_COMPRESS_LZO, string + 3,
|
||||
&ctx->compress_level);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
if (string[3] == ':' && string[4])
|
||||
btrfs_warn(NULL, "Compression level ignored for LZO");
|
||||
btrfs_set_opt(ctx->mount_opt, COMPRESS);
|
||||
|
@ -310,8 +315,10 @@ static int btrfs_parse_compress(struct btrfs_fs_context *ctx,
|
|||
btrfs_clear_opt(ctx->mount_opt, NODATASUM);
|
||||
} else if (btrfs_match_compress_type(string, "zstd", true)) {
|
||||
ctx->compress_type = BTRFS_COMPRESS_ZSTD;
|
||||
ctx->compress_level = btrfs_compress_str2level(BTRFS_COMPRESS_ZSTD,
|
||||
string + 4);
|
||||
ret = btrfs_compress_str2level(BTRFS_COMPRESS_ZSTD, string + 4,
|
||||
&ctx->compress_level);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
btrfs_set_opt(ctx->mount_opt, COMPRESS);
|
||||
btrfs_clear_opt(ctx->mount_opt, NODATACOW);
|
||||
btrfs_clear_opt(ctx->mount_opt, NODATASUM);
|
||||
|
@ -322,10 +329,14 @@ static int btrfs_parse_compress(struct btrfs_fs_context *ctx,
|
|||
btrfs_clear_opt(ctx->mount_opt, COMPRESS);
|
||||
btrfs_clear_opt(ctx->mount_opt, FORCE_COMPRESS);
|
||||
} else {
|
||||
btrfs_err(NULL, "unrecognized compression value %s", string);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
btrfs_err(NULL, "failed to parse compression option '%s'", string);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||
|
|
|
@ -1756,10 +1756,10 @@ static int check_inode_ref(struct extent_buffer *leaf,
|
|||
while (ptr < end) {
|
||||
u16 namelen;
|
||||
|
||||
if (unlikely(ptr + sizeof(iref) > end)) {
|
||||
if (unlikely(ptr + sizeof(*iref) > end)) {
|
||||
inode_ref_err(leaf, slot,
|
||||
"inode ref overflow, ptr %lu end %lu inode_ref_size %zu",
|
||||
ptr, end, sizeof(iref));
|
||||
ptr, end, sizeof(*iref));
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue