]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Check for extent crc uncompressed/compressed size mismatch
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 29 Nov 2024 00:02:18 +0000 (19:02 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:21 +0000 (01:36 -0500)
When not compressed, these must be equal - this fixes an assertion pop
in bch2_rechecksum_bio().

Reported-by: syzbot+50d3544c9b8db9c99fd2@syzkaller.appspotmail.com
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/extents.c
fs/bcachefs/sb-errors_format.h

index aa3b8829181437395c6bc66ee82636352ab1a20e..2fc9ace5533c332030638769d1e848bb951711e9 100644 (file)
@@ -1323,9 +1323,6 @@ int bch2_bkey_ptrs_validate(struct bch_fs *c, struct bkey_s_c k,
                case BCH_EXTENT_ENTRY_crc128:
                        crc = bch2_extent_crc_unpack(k.k, entry_to_crc(entry));
 
-                       bkey_fsck_err_on(crc.offset + crc.live_size > crc.uncompressed_size,
-                                        c, ptr_crc_uncompressed_size_too_small,
-                                        "checksum offset + key size > uncompressed size");
                        bkey_fsck_err_on(!bch2_checksum_type_valid(c, crc.csum_type),
                                         c, ptr_crc_csum_type_unknown,
                                         "invalid checksum type");
@@ -1333,6 +1330,19 @@ int bch2_bkey_ptrs_validate(struct bch_fs *c, struct bkey_s_c k,
                                         c, ptr_crc_compression_type_unknown,
                                         "invalid compression type");
 
+                       bkey_fsck_err_on(crc.offset + crc.live_size > crc.uncompressed_size,
+                                        c, ptr_crc_uncompressed_size_too_small,
+                                        "checksum offset + key size > uncompressed size");
+                       bkey_fsck_err_on(crc_is_encoded(crc) &&
+                                        (crc.uncompressed_size > c->opts.encoded_extent_max >> 9) &&
+                                        (from.flags & (BCH_VALIDATE_write|BCH_VALIDATE_commit)),
+                                        c, ptr_crc_uncompressed_size_too_big,
+                                        "too large encoded extent");
+                       bkey_fsck_err_on(!crc_is_compressed(crc) &&
+                                        crc.compressed_size != crc.uncompressed_size,
+                                        c, ptr_crc_uncompressed_size_mismatch,
+                                        "not compressed but compressed != uncompressed size");
+
                        if (bch2_csum_type_is_encryption(crc.csum_type)) {
                                if (nonce == UINT_MAX)
                                        nonce = crc.offset + crc.nonce;
@@ -1346,12 +1356,6 @@ int bch2_bkey_ptrs_validate(struct bch_fs *c, struct bkey_s_c k,
                                         "redundant crc entry");
                        crc_since_last_ptr = true;
 
-                       bkey_fsck_err_on(crc_is_encoded(crc) &&
-                                        (crc.uncompressed_size > c->opts.encoded_extent_max >> 9) &&
-                                        (from.flags & (BCH_VALIDATE_write|BCH_VALIDATE_commit)),
-                                        c, ptr_crc_uncompressed_size_too_big,
-                                        "too large encoded extent");
-
                        size_ondisk = crc.compressed_size;
                        break;
                case BCH_EXTENT_ENTRY_stripe_ptr:
index 342eda8ab69f46e4c58d6496cb47aa5d8e37076e..3bbda181f3147927c70e1c609cc52b8afaec604d 100644 (file)
@@ -172,10 +172,11 @@ enum bch_fsck_flags {
        x(ptr_bucket_data_type_mismatch,                        155,    0)              \
        x(ptr_cached_and_erasure_coded,                         156,    0)              \
        x(ptr_crc_uncompressed_size_too_small,                  157,    0)              \
+       x(ptr_crc_uncompressed_size_too_big,                    161,    0)              \
+       x(ptr_crc_uncompressed_size_mismatch,                   300,    0)              \
        x(ptr_crc_csum_type_unknown,                            158,    0)              \
        x(ptr_crc_compression_type_unknown,                     159,    0)              \
        x(ptr_crc_redundant,                                    160,    0)              \
-       x(ptr_crc_uncompressed_size_too_big,                    161,    0)              \
        x(ptr_crc_nonce_mismatch,                               162,    0)              \
        x(ptr_stripe_redundant,                                 163,    0)              \
        x(reservation_key_nr_replicas_invalid,                  164,    0)              \
@@ -310,7 +311,7 @@ enum bch_fsck_flags {
        x(logged_op_but_clean,                                  283,    FSCK_AUTOFIX)   \
        x(compression_opt_not_marked_in_sb,                     295,    FSCK_AUTOFIX)   \
        x(compression_type_not_marked_in_sb,                    296,    FSCK_AUTOFIX)   \
-       x(MAX,                                                  300,    0)
+       x(MAX,                                                  301,    0)
 
 enum bch_sb_error_id {
 #define x(t, n, ...) BCH_FSCK_ERR_##t = n,