[PATCH v3 3/5] btrfs: also validate compression levels in btrfs_compress_is_valid_type()
koraynilay <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
Change btrfs_compress_is_valid_type() to use btrfs_match_compress_type() and btrfs_compress_str2level() instead of a simple strncmp(), which would validate even incorrect strings (e.g. "zstd:invalid" or "zstdinvalid"). This also makes the function validate levels in the same way the compress= option gets parsed, allowing bigger or smaller values, but still clamping them to the min or max supported. Furthermore, remove the len parameter, since now it requires a NUL-terminated string because of btrfs_compress_str2level(); this change is fine because btrfs_compress_is_valid_type() is used only once in props.c by prop_compression_validate(), which now uses kmemdup_nul() to convert the user-supplied xattr value to a NUL-terminated string. Assisted-by: Gemini:3.1-pro antigravity-cli-1.1.5 Signed-off-by: koraynilay <[email protected]> --- fs/btrfs/compression.c | 18 +++++++++++++++--- fs/btrfs/compression.h | 2 +- fs/btrfs/props.c | 16 ++++++++++++---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 58138f300b58..e723cef3b5dc 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -70,18 +70,30 @@ static struct compressed_bio *alloc_compressed_bio(struct btrfs_inode *inode, return to_compressed_bio(bbio); } -bool btrfs_compress_is_valid_type(const char *str, size_t len) +/** + * btrfs_compress_is_valid_type - Check if a string is a valid compression type. + * @str: The compression string to check. Must be null-terminated. + * + * Return: %true if the string is a valid compression algorithm (optionally with + * a level suffix, e.g. "zstd" or "zstd:9"), %false otherwise. + */ +bool btrfs_compress_is_valid_type(const char *str) { + size_t len = strlen(str); int i; for (i = 1; i < ARRAY_SIZE(btrfs_compress_types); i++) { size_t comp_len = strlen(btrfs_compress_types[i]); + const char *comp_type = btrfs_compress_types[i]; + int tmp_level; if (len < comp_len) continue; - if (!strncmp(btrfs_compress_types[i], str, comp_len)) - return true; + if (btrfs_match_compress_type(str, comp_type, true)) { + if (btrfs_compress_str2level(i, str + comp_len, &tmp_level) == 0) + return true; + } } return false; } diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h index e67ba47b4cdc..c63bed9f4152 100644 --- a/fs/btrfs/compression.h +++ b/fs/btrfs/compression.h @@ -132,7 +132,7 @@ extern const struct btrfs_compress_levels btrfs_lzo_compress; extern const struct btrfs_compress_levels 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); +bool btrfs_compress_is_valid_type(const char *str); int btrfs_compress_heuristic(struct btrfs_inode *inode, u64 start, u64 end); diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c index bb77d46376d4..a269124c3b92 100644 --- a/fs/btrfs/props.c +++ b/fs/btrfs/props.c @@ -295,20 +295,28 @@ int btrfs_load_inode_props(struct btrfs_inode *inode, struct btrfs_path *path) static int prop_compression_validate(const struct btrfs_inode *inode, const char *value, size_t len) { + int ret = -EINVAL; + const char *value_str; + if (!btrfs_inode_can_compress(inode)) return -EINVAL; if (!value) return 0; - if (btrfs_compress_is_valid_type(value, len)) - return 0; - if ((len == 2 && strncmp("no", value, 2) == 0) || (len == 4 && strncmp("none", value, 4) == 0)) return 0; - return -EINVAL; + value_str = kmemdup_nul(value, len, GFP_KERNEL); + if (!value_str) + return -ENOMEM; + + if (btrfs_compress_is_valid_type(value_str)) + ret = 0; + + kfree(value_str); + return ret; } static int prop_compression_apply(struct btrfs_inode *inode, const char *value, -- 2.55.0