DragonFlyBSD Kernel Audit
DF-0006 / leak_sample.txt
← back to finding ↓ download raw
# 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.