mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
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:
parent
72acab3a7c
commit
d335bb3fd3
@ -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]);
|
||||||
|
Loading…
Reference in New Issue
Block a user