--- DF-0869 panic signature (unpatched #0 kernel, INVARIANTS on) --- --- Trigger: HAMMERIOC_ADD_VOLUME boot_area_size=-1 vol_size=2^49 --- --- Captured from dfbsd-qemu/boot.log before guest reset --- HAMMER(df0869) Initialize freemap volume 1 dscheck(vn2): bio_offset 262143 is not on a sector boundary (ssize 512) panic: assertion "error == 0" failed in hammer_ioc_volume_add at /usr/src/sys/vfs/hammer/hammer_volume.c:118 cpuid = 1 Trace beginning at frame 0xfffff801166dac48 hammer_ioc_volume_add() at hammer_ioc_volume_add+0x5c6 0xffffffff80930806 hammer_ioc_volume_add() at hammer_ioc_volume_add+0x5c6 0xffffffff80930806 hammer_ioctl() at hammer_ioctl+0xf0a 0xffffffff8093ed1a hammer_vop_ioctl() at hammer_vop_ioctl+0x48 0xffffffff80958978 vop_ioctl() at vop_ioctl+0x63 0xffffffff8070a793 vn_ioctl() at vn_ioctl+0xb1 0xffffffff807080e1 Debugger("panic") CPU1 stopping CPUs: 0x0000003d stopped Stopped at Debugger+0x7c: movb $0,0xbdaf09(%rip) db> --- Mechanism --- boot_area_size = -1 in the ioc propagates into hammer_format_volume_header: vol_alloc = root.vol_bot_beg; // 0x40000 = 256 KiB vol_alloc += ioc->boot_area_size; // -1 ondisk->vol_buf_beg = vol_alloc; // 0x3FFFF = 262143 (NOT sector-aligned) vol_buf_end = ioc->vol_size & ~HAMMER_BUFMASK = 2^49 (passes the only check `HAMMER_VOL_BUF_SIZE < 0` because vol_buf_size is a huge positive). hammer_format_freemap then issues hammer_bread() against the freshly installed volume at offsets derived from vol_buf_beg. The first such I/O is at bio_offset 262143 -- not a 512-byte boundary -- and dscheck() rejects it, hammer_bread returns EINVAL, and KKASSERT(error == 0) at hammer_volume.c:118 panics the kernel. The root cause is missing bounds + sanity validation in hammer_format_volume_header: boot_area_size, memory_log_size and vol_size are attacker-controlled int64s summed into vol_alloc with only a single signed-<0 check on the final vol_buf_size.