Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+43 -21
+13 -9
fs/btrfs/compression.c
··· 1616 1616 } 1617 1617 1618 1618 /* 1619 - * Convert the compression suffix (eg. after "zlib" starting with ":") to 1620 - * level, unrecognized string will set the default level. Negative level 1621 - * numbers are allowed. 1619 + * Convert the compression suffix (eg. after "zlib" starting with ":") to level. 1620 + * 1621 + * If the resulting level exceeds the algo's supported levels, it will be clamped. 1622 + * 1623 + * Return <0 if no valid string can be found. 1624 + * Return 0 if everything is fine. 1622 1625 */ 1623 - int btrfs_compress_str2level(unsigned int type, const char *str) 1626 + int btrfs_compress_str2level(unsigned int type, const char *str, int *level_ret) 1624 1627 { 1625 1628 int level = 0; 1626 1629 int ret; 1627 1630 1628 - if (!type) 1631 + if (!type) { 1632 + *level_ret = btrfs_compress_set_level(type, level); 1629 1633 return 0; 1634 + } 1630 1635 1631 1636 if (str[0] == ':') { 1632 1637 ret = kstrtoint(str + 1, 10, &level); 1633 1638 if (ret) 1634 - level = 0; 1639 + return ret; 1635 1640 } 1636 1641 1637 - level = btrfs_compress_set_level(type, level); 1638 - 1639 - return level; 1642 + *level_ret = btrfs_compress_set_level(type, level); 1643 + return 0; 1640 1644 }
+1 -1
fs/btrfs/compression.h
··· 102 102 bool writeback); 103 103 void btrfs_submit_compressed_read(struct btrfs_bio *bbio); 104 104 105 - int btrfs_compress_str2level(unsigned int type, const char *str); 105 + int btrfs_compress_str2level(unsigned int type, const char *str, int *level_ret); 106 106 107 107 struct folio *btrfs_alloc_compr_folio(void); 108 108 void btrfs_free_compr_folio(struct folio *folio);
+8 -1
fs/btrfs/ref-verify.c
··· 980 980 if (!btrfs_test_opt(fs_info, REF_VERIFY)) 981 981 return 0; 982 982 983 + extent_root = btrfs_extent_root(fs_info, 0); 984 + /* If the extent tree is damaged we cannot ignore it (IGNOREBADROOTS). */ 985 + if (IS_ERR(extent_root)) { 986 + btrfs_warn(fs_info, "ref-verify: extent tree not available, disabling"); 987 + btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); 988 + return 0; 989 + } 990 + 983 991 path = btrfs_alloc_path(); 984 992 if (!path) 985 993 return -ENOMEM; 986 994 987 - extent_root = btrfs_extent_root(fs_info, 0); 988 995 eb = btrfs_read_lock_root_node(extent_root); 989 996 level = btrfs_header_level(eb); 990 997 path->nodes[level] = eb;
+19 -8
fs/btrfs/super.c
··· 276 276 const struct fs_parameter *param, int opt) 277 277 { 278 278 const char *string = param->string; 279 + int ret; 279 280 280 281 /* 281 282 * Provide the same semantics as older kernels that don't use fs ··· 295 294 btrfs_clear_opt(ctx->mount_opt, NODATASUM); 296 295 } else if (btrfs_match_compress_type(string, "zlib", true)) { 297 296 ctx->compress_type = BTRFS_COMPRESS_ZLIB; 298 - ctx->compress_level = btrfs_compress_str2level(BTRFS_COMPRESS_ZLIB, 299 - string + 4); 297 + ret = btrfs_compress_str2level(BTRFS_COMPRESS_ZLIB, string + 4, 298 + &ctx->compress_level); 299 + if (ret < 0) 300 + goto error; 300 301 btrfs_set_opt(ctx->mount_opt, COMPRESS); 301 302 btrfs_clear_opt(ctx->mount_opt, NODATACOW); 302 303 btrfs_clear_opt(ctx->mount_opt, NODATASUM); 303 304 } else if (btrfs_match_compress_type(string, "lzo", true)) { 304 305 ctx->compress_type = BTRFS_COMPRESS_LZO; 305 - ctx->compress_level = btrfs_compress_str2level(BTRFS_COMPRESS_LZO, 306 - string + 3); 306 + ret = btrfs_compress_str2level(BTRFS_COMPRESS_LZO, string + 3, 307 + &ctx->compress_level); 308 + if (ret < 0) 309 + goto error; 307 310 if (string[3] == ':' && string[4]) 308 311 btrfs_warn(NULL, "Compression level ignored for LZO"); 309 312 btrfs_set_opt(ctx->mount_opt, COMPRESS); ··· 315 310 btrfs_clear_opt(ctx->mount_opt, NODATASUM); 316 311 } else if (btrfs_match_compress_type(string, "zstd", true)) { 317 312 ctx->compress_type = BTRFS_COMPRESS_ZSTD; 318 - ctx->compress_level = btrfs_compress_str2level(BTRFS_COMPRESS_ZSTD, 319 - string + 4); 313 + ret = btrfs_compress_str2level(BTRFS_COMPRESS_ZSTD, string + 4, 314 + &ctx->compress_level); 315 + if (ret < 0) 316 + goto error; 320 317 btrfs_set_opt(ctx->mount_opt, COMPRESS); 321 318 btrfs_clear_opt(ctx->mount_opt, NODATACOW); 322 319 btrfs_clear_opt(ctx->mount_opt, NODATASUM); ··· 329 322 btrfs_clear_opt(ctx->mount_opt, COMPRESS); 330 323 btrfs_clear_opt(ctx->mount_opt, FORCE_COMPRESS); 331 324 } else { 332 - btrfs_err(NULL, "unrecognized compression value %s", string); 333 - return -EINVAL; 325 + ret = -EINVAL; 326 + goto error; 334 327 } 335 328 return 0; 329 + error: 330 + btrfs_err(NULL, "failed to parse compression option '%s'", string); 331 + return ret; 332 + 336 333 } 337 334 338 335 static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
+2 -2
fs/btrfs/tree-checker.c
··· 1756 1756 while (ptr < end) { 1757 1757 u16 namelen; 1758 1758 1759 - if (unlikely(ptr + sizeof(iref) > end)) { 1759 + if (unlikely(ptr + sizeof(*iref) > end)) { 1760 1760 inode_ref_err(leaf, slot, 1761 1761 "inode ref overflow, ptr %lu end %lu inode_ref_size %zu", 1762 - ptr, end, sizeof(iref)); 1762 + ptr, end, sizeof(*iref)); 1763 1763 return -EUCLEAN; 1764 1764 } 1765 1765