Commit fdc6b084 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Fix shift-by-64 in bch2_bkey_format_validate()

We need to ensure that packed formats can't represent fields larger than
the unpacked format, which is a bit tricky since the calculations can
also overflow a u64. This patch fixes a shift and simplifies the overall
calculations.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
parent 78d66ab1
......@@ -623,22 +623,22 @@ const char *bch2_bkey_format_validate(struct bkey_format *f)
if (f->nr_fields != BKEY_NR_FIELDS)
return "incorrect number of fields";
/*
* Verify that the packed format can't represent fields larger than the
* unpacked format:
*/
for (i = 0; i < f->nr_fields; i++) {
unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
u64 unpacked_mask = ~((~0ULL << 1) << (unpacked_bits - 1));
u64 unpacked_max = ~((~0ULL << 1) << (unpacked_bits - 1));
u64 packed_max = f->bits_per_field[i]
? ~((~0ULL << 1) << (f->bits_per_field[i] - 1))
: 0;
u64 field_offset = le64_to_cpu(f->field_offset[i]);
if (f->bits_per_field[i] > unpacked_bits)
if (packed_max + field_offset < packed_max ||
packed_max + field_offset > unpacked_max)
return "field too large";
if ((f->bits_per_field[i] == unpacked_bits) && field_offset)
return "offset + bits overflow";
if (((field_offset + ((1ULL << f->bits_per_field[i]) - 1)) &
unpacked_mask) <
field_offset)
return "offset + bits overflow";
bits += f->bits_per_field[i];
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment