DF-2606 / fix.diff
--- a/sys/vfs/hammer2/hammer2_chain.c +++ b/sys/vfs/hammer2/hammer2_chain.c @@ -938,6 +938,24 @@ if ((chain->bref.data_off & ~HAMMER2_OFF_MASK_RADIX) == 0) return; + /* + * Media integrity check. keybits must be 0..63. A larger value + * cannot encode a valid radix for a 64-bit key and makes every + * (hammer2_key_t)1 << keybits computation in the chain code + * undefined behavior. Refuse to load the chain. + */ + if (chain->bref.keybits > 63) { + krateprintf(&krate_h2chk, + "chain %016jx.%02x (%s) keybits=%d CHECK FAIL " + "(> 63, illegal radix)\n", + chain->bref.data_off, + chain->bref.type, + hammer2_bref_type_str(chain->bref.type), + chain->bref.keybits); + chain->error = HAMMER2_ERROR_CHECK; + return; + } + hmp = chain->hmp; KKASSERT(hmp != NULL); @@ -4974,6 +4992,19 @@ */ while (i < count) { if (scan->type != HAMMER2_BREF_TYPE_EMPTY) { + /* + * Media integrity check. keybits > 63 is illegal + * (it cannot encode a radix for a 64-bit key) and + * any range computed from it would be undefined + * behavior. Skip the entry entirely. + */ + if (scan->keybits > 63) { + if (i >= limit) + return (count); + ++scan; + ++i; + continue; + } scan_end = scan->key + ((hammer2_key_t)1 << scan->keybits) - 1; if (scan->key > key_beg || scan_end >= key_beg) @@ -5353,6 +5384,12 @@ key_next = 0; for (l = 0; l < count; ++l) { if (base[l].type != HAMMER2_BREF_TYPE_EMPTY) { + /* + * Illegal radix; ordering cannot be checked without + * undefined behavior (see hammer2_base_find). + */ + if (base[l].keybits > 63) + continue; key_next = base[l].key + ((hammer2_key_t)1 << base[l].keybits) - 1; break; @@ -5362,6 +5399,12 @@ if (base[l].type != HAMMER2_BREF_TYPE_EMPTY) { if (base[l].key <= key_next) panic("base_insert %d %d,%d,%d fail %p:%d", u, i, j, k, base, l); + /* + * Illegal radix; do not update key_next (would be + * undefined behavior, see hammer2_base_find). + */ + if (base[l].keybits > 63) + continue; key_next = base[l].key + ((hammer2_key_t)1 << base[l].keybits) - 1; |