From: Kent Overstreet Date: Thu, 24 Jun 2021 17:19:25 +0000 (-0400) Subject: bcachefs: Fix shift-by-64 in bch2_bkey_format_validate() X-Git-Tag: Ubuntu-6.8.0-17.17~2238^2~1494 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=fdc6b08451167bfc1ae260b252ad2bf2f9735f50;p=mirror_ubuntu-kernels.git 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: Kent Overstreet --- diff --git a/fs/bcachefs/bkey.c b/fs/bcachefs/bkey.c index 5de88a93f33f..3e62eeb6774e 100644 --- a/fs/bcachefs/bkey.c +++ b/fs/bcachefs/bkey.c @@ -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]; }