bcachefs: Ancient versions with bad bkey_formats are no longer supported

Syzbot found an assertion pop, by generating an ancient filesystem
version with an invalid bkey_format (with fields that can overflow) as
well as packed keys that aren't representable unpacked.

This breaks key comparisons in all sorts of painful ways.

Filesystems have been automatically rewriting nodes with such invalid
formats for years; we can safely drop support for them.

Reported-by: syzbot+8a0109511de9d4b61217@syzkaller.appspotmail.com
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-10-31 02:36:21 -04:00
parent 72acab3a7c
commit d335bb3fd3

View File

@ -643,7 +643,7 @@ int bch2_bkey_format_invalid(struct bch_fs *c,
enum bch_validate_flags flags, enum bch_validate_flags flags,
struct printbuf *err) struct printbuf *err)
{ {
unsigned i, bits = KEY_PACKED_BITS_START; unsigned bits = KEY_PACKED_BITS_START;
if (f->nr_fields != BKEY_NR_FIELDS) { if (f->nr_fields != BKEY_NR_FIELDS) {
prt_printf(err, "incorrect number of fields: got %u, should be %u", prt_printf(err, "incorrect number of fields: got %u, should be %u",
@ -655,9 +655,8 @@ int bch2_bkey_format_invalid(struct bch_fs *c,
* Verify that the packed format can't represent fields larger than the * Verify that the packed format can't represent fields larger than the
* unpacked format: * unpacked format:
*/ */
for (i = 0; i < f->nr_fields; i++) { for (unsigned i = 0; i < f->nr_fields; i++) {
if ((!c || c->sb.version_min >= bcachefs_metadata_version_snapshot) && if (bch2_bkey_format_field_overflows(f, i)) {
bch2_bkey_format_field_overflows(f, i)) {
unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i]; unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1)); u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1));
unsigned packed_bits = min(64, f->bits_per_field[i]); unsigned packed_bits = min(64, f->bits_per_field[i]);