DF-0006 / leak_sample.txt
# DF-0006 leak sample — kernel function/heap pointers leaked via kern.ttys # Guest: DragonFly 6.5-DEVELOPMENT #0 (Thu Jul 2 06:02:54 UTC 2026), amd64 # Reader: uid=1001 (maxx), NOT in wheel. Node: kern.ttys (CTLFLAG_RD, world-read) # # sysctl_kern_ttys (sys/kern/tty.c:2891-2921) does t = *tp; (whole struct), # sanitizes ONLY t_dev, then SYSCTL_OUT(&t, sizeof(t)). struct tty is 376 bytes; # 10 ttys -> 3760 bytes leaked. Scanned at 8-byte stride for canonical-upper-half # kernel addresses (>= 0xffff800000000000). # # 102 kernel-range pointer-sized values leaked per run on the UNPATCHED #0 kernel. # On the single-fix #1 kernel (improved fix.diff) the count is 0 (exit 2, x3 runs). ## leaked value classes (struct tty intra-offset -> field, by struct layout) ## ## .text-segment function pointers (0xffffffff80??????) -> KASLR .text base ## offset 256 t_oproc 0xffffffff80b8c0f0 (syscons start-output cb) ## offset 264 t_stop 0xffffffff806b87a0 (nottystop region) ## offset 272 t_param 0xffffffff80b87220 (syscons param cb) ## All three lie inside the kernel .text segment ## [0xffffffff802aabb0 .. 0xffffffff80fce540] (per readelf -l /boot/kernel/kernel), ## so they disclose the precise kernel .text base -> KASLR defeated. ## ## .rodata / token-internal pointer ## offset 24 t_token.t_desc 0xffffffff80c64d8d (const char * in lwkt_token, ## sys/sys/thread.h:163) ## ## heap / direct-map pointers (0xfffff8??????????) -> slab + clist layout ## offset 48 t_rawq.c_data 0xfffff8008bbbb400 (clist short * buffer) ## offset 80 t_canq.c_data 0xfffff8008dcf1000 ## offset 112 t_outq.c_data 0xfffff8008d202600 ## offset 160 t_pgrp 0xfffff8004f1c6190 (pgrp slab object) ## offset 168 t_session 0xfffff8008bb1f320 (session slab object) ## ## global-list linkage pointers (the field the FIRST fix.diff missed) ## offset 352 t_list.tqe_next 0xfffff801182eb600 (== &marker, identical across ## all 10 ttys: the handler ## inserts a stack marker after ## each tp, tty.c:2905-2908) ## offset 360 t_list.tqe_prev 0xffffffff810e5200 (== &tty_list.tqh_first for ## the head tty; tty_list is a ## global at 0xffffffff810e5280) ## => 2 pointers/tty x 10 ttys = the 20-pointer residual left by the first fix. ## nm cross-reference (this #0 build) ## nm /boot/kernel/kernel | grep -E ' [Tt] ' shows: ## ffffffff80b8c1c0 t scstart ffffffff806b8870 T nottystop ## ffffffff80b872f0 t scparam ffffffff80c2f370 t comstart ## The leaked offsets 256/264/272 carry the corresponding tty driver callbacks ## (scstart/nottystop/scparam family); all are kernel .text addresses. ## decisive excerpt from run.log (UNPATCHED #0 baseline) got 3760 bytes from kern.ttys raw blob written to ttys.bin (3760 bytes) blob offset 24 (word 3): 0xffffffff80c64d8d blob offset 48 (word 6): 0xfffff8008bbbb400 blob offset 80 (word 10): 0xfffff8008dcf1000 blob offset 112 (word 14): 0xfffff8008d202600 blob offset 160 (word 20): 0xfffff8004f1c6190 blob offset 168 (word 21): 0xfffff8008bb1f320 blob offset 256 (word 32): 0xffffffff80b8c0f0 blob offset 264 (word 33): 0xffffffff806b87a0 blob offset 272 (word 34): 0xffffffff80b87220 blob offset 352 (word 44): 0xfffff801182eb600 blob offset 360 (word 45): 0xffffffff810e5200 ... total kernel-range pointer-sized values leaked: 102 RUN_EXIT=0 ## decisive excerpt from fix_run.log (SINGLE-FIX #1 kernel, improved fix.diff) got 3760 bytes from kern.ttys raw blob written to ttys.bin (3760 bytes) total kernel-range pointer-sized values leaked: 0 RUN_EXIT=2 (reproduced 3x on the patched kernel — deterministic) ## interpretation The leaked 0xffffffff80?????? values are kernel .text-segment addresses (the tty driver start/stop/param callbacks + the lwkt_token descriptive string pointer), so an unprivileged attacker recovers the precise kernel .text base (KASLR defeat). The 0xfffff8?????????? values are live slab/direct-map addresses (clist buffers, pgrp/session objects, the per-iteration marker), revealing kernel heap layout for grooming a separate heap-corruption bug. The improved fix.diff zeroes every pointer-bearing field of the local copy (including the previously-missed t_list TAILQ_ENTRY linkage) before SYSCTL_OUT, closing the leak to 0.