mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
bcachefs: Fix shift-by-64 in bformat_needs_redo()
Ancient versions of bcachefs produced packed formats that could represent keys that our in memory format cannot represent; bformat_needs_redo() has some tricky shifts to check for this sort of overflow. Reported-by: syzbot+594427aebfefeebe91c6@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
2bb9600d5d
commit
0ec5b3b7cc
@ -968,24 +968,30 @@ static bool migrate_btree_pred(struct bch_fs *c, void *arg,
|
||||
return migrate_pred(c, arg, bkey_i_to_s_c(&b->key), io_opts, data_opts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ancient versions of bcachefs produced packed formats which could represent
|
||||
* keys that the in memory format cannot represent; this checks for those
|
||||
* formats so we can get rid of them.
|
||||
*/
|
||||
static bool bformat_needs_redo(struct bkey_format *f)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < f->nr_fields; i++) {
|
||||
for (unsigned i = 0; i < f->nr_fields; i++) {
|
||||
unsigned f_bits = f->bits_per_field[i];
|
||||
unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
|
||||
u64 unpacked_mask = ~((~0ULL << 1) << (unpacked_bits - 1));
|
||||
u64 field_offset = le64_to_cpu(f->field_offset[i]);
|
||||
|
||||
if (f->bits_per_field[i] > unpacked_bits)
|
||||
if (f_bits > unpacked_bits)
|
||||
return true;
|
||||
|
||||
if ((f->bits_per_field[i] == unpacked_bits) && field_offset)
|
||||
if ((f_bits == unpacked_bits) && field_offset)
|
||||
return true;
|
||||
|
||||
if (((field_offset + ((1ULL << f->bits_per_field[i]) - 1)) &
|
||||
unpacked_mask) <
|
||||
field_offset)
|
||||
u64 f_mask = f_bits
|
||||
? ~((~0ULL << (f_bits - 1)) << 1)
|
||||
: 0;
|
||||
|
||||
if (((field_offset + f_mask) & unpacked_mask) < field_offset)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user