DF-3368 / run.log
# Consolidated console/dmesg evidence, stock INVARIANTS kernel #0
# (DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026).
# Vulnerable module (/root/df3368/df3368.ko), safe modes:
df3368: mode 0 (CONTROL): nslots=16 end=8 ft=0xfffff801185b0040 (ft[] contract=1088 entries / 17408 bytes, alloc=52104)
df3368: RESULT slot-iters=8 final-ft_i=0 (max table index written: 7, <= NM_BDG_BATCH_MAX=1088; byte offset 128 <= alloc size 52104)
df3368: flush stub calls=1 lastn=8 underflow(ft[-1])write=0
df3368: CANARY bytes corrupted past ft[] contract: 0, first @ft+0 (ft[0]), last @ft+0 (ft[0])
df3368: pass-1 walk terminated after 8 steps
df3368: mode 1 (256-FRAG CHAIN -> uint8_t ft_frags truncation):
df3368: mode 1: nslots=257 end=256 ft=0xfffff801185b0040 (ft[] contract=1088 entries / 17408 bytes, alloc=52104)
df3368: RESULT slot-iters=256 final-ft_i=0 (max table index written: 255, <= NM_BDG_BATCH_MAX=1088; byte offset 4096 <= alloc size 52104)
df3368: CANARY bytes corrupted past ft[] contract: 0, first @ft+0 (ft[0]), last @ft+0 (ft[0])
df3368: mode1 ft[0].ft_frags = 0 (256 truncated to uint8_t)
df3368: pass-1 walk STUCK at i=0 (ft[i].ft_frags=0, iters>100000) <<< nm_bdg_flush pass-1 livelock (netmap_vale.c:1161)
df3368: mode 2 (2047-slot chain -> ft[] table overrun; chain terminated so the post-loop wild write is skipped):
df3368: mode 2: nslots=2048 end=2047 ft=0xfffff80118620040 (ft[] contract=1088 entries / 17408 bytes, alloc=52104)
df3368: RESULT slot-iters=2047 final-ft_i=0 (max table index written: 2046, OVER NM_BDG_BATCH_MAX=1088; byte offset 32752 <= alloc size 52104)
df3368: CANARY bytes corrupted past ft[] contract: 13418, first @ft+17408 (ft[1088]), last @ft+32751 (ft[2046])
^^^ 13418 bytes of attacker data (slot->len/flags/ptr) written past the
NM_BDG_BATCH_MAX-entry ft[] contract into the dst_ents/dsts region; on the
real driver the same indices beyond ft[3256] are past the 52104-byte kmalloc.
df3368: mode 3 (3300 slots, real kmalloc(52104) as nm_alloc_bdgfwd):
df3368: mode 3: nslots=3300 end=3299 ft=0xfffff801188a0000 (ft[] contract=1088 entries / 17408 bytes, alloc=52104)
df3368: RESULT slot-iters=3299 final-ft_i=0 (max table index written: 3298, OVER NM_BDG_BATCH_MAX=1088; byte offset 52784 PAST alloc size 52104)
^^^ 680 bytes written past the end of the 52104-byte kernel heap object
(bounded test: ring max 4096 slots would write up to offset 65520, 13416
bytes past). Guest survived -> silent heap corruption.
(prior run of same mode: ft=0xfffff80118880000, identical RESULT)
# all-MOREFRAG variant (wild write) -> see run.crash.log:
# Fatal trap 12, fault VA 0xfffff81118640038 == ft(0xfffff80118640040)+0xFFFFFFF8,
# Stopped at df3368_sysctl+0x401: movb %dl,0x8(%r8,%rax,1)
# == the verbatim store of netmap_vale.c:1013 ft[ft_i - frags].ft_frags = frags - 1;
# with ft_i - frags == -1 evaluated in 32-bit unsigned -> +4GiB wild write.
===== FIXED VARIANT (-DDD3368_FIXED: frags capped at NM_MULTISEG) =====
df3368: mode 1: nslots=257 end=256
df3368: RESULT slot-iters=256 final-ft_i=0 (max table index written: 255, <= NM_BDG_BATCH_MAX=1088; byte offset 4096 <= alloc size 52104)
df3368: CANARY bytes corrupted past ft[] contract: 0, first @ft+0 (ft[0]), last @ft+0 (ft[0])
df3368: mode1 ft[0].ft_frags = 64 (256 truncated to uint8_t)
df3368: pass-1 walk terminated after 4 steps
df3368: mode 2: nslots=2048 end=2047
df3368: RESULT slot-iters=2047 final-ft_i=0 (max table index written: 1023, <= NM_BDG_BATCH_MAX=1088; byte offset 16384 <= alloc size 52104)
df3368: flush stub calls=2 lastn=1023 underflow(ft[-1])write=0
df3368: CANARY bytes corrupted past ft[] contract: 0, first @ft+0 (ft[0]), last @ft+0 (ft[0])
df3368: mode 3: nslots=3300 end=3299 ft=0xfffff80118880000
df3368: RESULT slot-iters=3299 final-ft_i=0 (max table index written: 1023, <= NM_BDG_BATCH_MAX=1088; byte offset 16384 <= alloc size 52104)
df3368: flush stub calls=4 lastn=227 underflow(ft[-1])write=0