--- a/sys/vfs/hammer/hammer_btree.c 2026-09-08 03:14:36.652256326 +0000 +++ b/sys/vfs/hammer/hammer_btree.c 2026-09-08 04:02:12.442889107 +0000 @@ -732,8 +732,28 @@ /* * Load the data + * + * The on-disk data_offset/data_len are attacker controllable (a + * corrupted or forged filesystem image). Reject out-of-range + * lengths, non-data zones, and extents that are not contained + * within the referenced 16K data buffer before touching the + * buffer cache or the CRC engine. */ - KKASSERT(data_len >= 0 && data_len <= HAMMER_XBUFSIZE); + { + int zone = (int)((data_off >> 60) & 15); + + if (data_len <= 0 || data_len > HAMMER_BUFSIZE || + (zone != HAMMER_ZONE_META_INDEX && + zone != HAMMER_ZONE_LARGE_DATA_INDEX && + zone != HAMMER_ZONE_SMALL_DATA_INDEX) || + (int)(data_off & HAMMER_BUFMASK) + data_len > + HAMMER_BUFSIZE) { + hdkprintf("bad record data %d @ %016jx\n", + data_len, (intmax_t)data_off); + cursor->data = NULL; + return (EIO); + } + } cursor->data = hammer_bread_ext(hmp, data_off, data_len, &error, &cursor->data_buffer); --- a/sys/vfs/hammer/hammer_pfs.c 2026-09-08 03:14:36.652256326 +0000 +++ b/sys/vfs/hammer/hammer_pfs.c 2026-09-08 03:14:45.780124506 +0000 @@ -359,8 +359,15 @@ if (error == 0) { error = hammer_ip_resolve_data(&cursor); if (error == 0) { + int bytes = cursor.leaf->data_len; + + if (bytes < 0) + bytes = 0; + if (bytes > sizeof(struct hammer_pseudofs_data)) + bytes = sizeof(struct hammer_pseudofs_data); if (pfs->ondisk) - copyout(cursor.data, pfs->ondisk, cursor.leaf->data_len); + error = copyout(cursor.data, pfs->ondisk, + bytes); localization = cursor.leaf->base.key; pfs->pfs_id = lo_to_pfs(localization); }