diff --git a/sys/vfs/hammer/hammer_btree.c b/sys/vfs/hammer/hammer_btree.c --- a/sys/vfs/hammer/hammer_btree.c +++ b/sys/vfs/hammer/hammer_btree.c @@ -731,9 +731,21 @@ return(0); /* - * Load the data + * Load the data. + * + * data_len is an int32_t read directly from the on-disk B-Tree leaf + * element and is attacker-controlled on a crafted filesystem image. + * Validate it explicitly here rather than relying on the KKASSERT + * below, which is compiled out on kernels built without INVARIANTS. + * A bogus data_len would otherwise drive an out-of-bounds read in + * hammer_bread_ext()/bcmp() and integer overflow in the blockmap + * DOALIGN macros (see DF-0929). */ - KKASSERT(data_len >= 0 && data_len <= HAMMER_XBUFSIZE); + if (data_len < 0 || data_len > HAMMER_XBUFSIZE) { + hdkprintf("bad data_len %d for leaf @ %016jx\n", + data_len, (intmax_t)elm->leaf.data_offset); + return (EIO); + } cursor->data = hammer_bread_ext(hmp, data_off, data_len, &error, &cursor->data_buffer);