DragonFlyBSD Kernel Audit
DF-0592 / leak_sample.txt
← back to finding ↓ download raw
# DF-0592 — variance of uninitialized kernel stack bytes leaked
# across 4 separate DIOCGETQSTATS invocations (unpatched #0 baseline).
# Each run re-creates the FAIRQ discipline+queue from scratch and re-issues
# DIOCGETQSTATS.  The non-zero count varies run-to-run, proving the leaked
# bytes are stale kernel stack residue and not deterministic struct contents.
# All samples taken as root with pf.ko loaded on vtnet0; class qtype=Q_DROPTAIL.

# Layout reminder: struct fairq_classstats (224 bytes total on amd64)
#   off  0..11  : fully initialized (class_handle, qlength, qlimit)
#   off 12..15  : compiler-inserted padding  (4 bytes) [LEAK]
#   off 16..47  : fully initialized (xmit_cnt, drop_cnt)
#   off 48..51  : fully initialized (qtype)
#   off 52..55  : compiler-inserted padding  (4 bytes) [LEAK]
#   off 56..223 : red[3] array (168 bytes), untouched for Q_DROPTAIL [LEAK]
# Total leak surface: 176 bytes per call.

RUN 1 (138/176 non-zero):
  region [ 12.. 15]   padding(qlimit->xmit_cnt) : 4 non-zero bytes
     ff@12 ff@13 ff@14 ff@15
  region [ 52.. 55]   padding(qtype->red[0])    : 4 non-zero bytes
     01@52 f8@53 ff@54 ff@55
  region [ 56..223]   red[3]                    : 130 non-zero bytes
     fe@57 9a@58 89@59 f8@61 ff@62 ff@63 b0@64 c8@65 67@66 80@67
     ff@68 ff@69 ff@70 ff@71 04@88 dd@89 6a@90 18@91 01@92 f8@93
     ff@94 ff@95 08@96 36@97 64@98 18@99 01@100 f8@101 ff@102 ff@103
  kernel-pointer-looking 8-byte windows in red[]: 29

RUN 2 (124/176 non-zero):
  region [ 12.. 15]   padding(qlimit->xmit_cnt) : 3 non-zero bytes
     f8@13 ff@14 ff@15
  region [ 52.. 55]   padding(qtype->red[0])    : 0 non-zero bytes
  region [ 56..223]   red[3]                    : 121 non-zero bytes
     01@56 cb@57 91@58 18@59 01@60 f8@61 ff@62 ff@63 f8@64 e5@65 da@66
     17@67 01@68 f8@69 ff@70 ff@71 87@72 63@73 9a@74 80@75 ff@76 ff@77
     ff@78 ff@79 02@82 5c@88 80@89 65@90 80@91 ff@92 ff@93 ff@94
  kernel-pointer-looking 8-byte windows in red[]: 27

RUN 3 (126/176 non-zero):
  region [ 12.. 15]   padding(qlimit->xmit_cnt) : 0 non-zero bytes
  region [ 52.. 55]   padding(qtype->red[0])    : 0 non-zero bytes
  region [ 56..223]   red[3]                    : 122 non-zero bytes
     01@56 dd@57 8a@58 18@59 01@60 f8@61 ff@62 ff@63 f8@64 45@65 6a@66
     18@67 01@68 f8@69 ff@70 ff@71 87@72 63@73 9a@74 80@75 ff@76 ff@77
     ff@78 ff@79 02@82 c0@88 a5@89 0e@90 8e@91 f8@93 ff@94 ff@95
  kernel-pointer-looking 8-byte windows in red[]: 27

RUN 4 (133/176 non-zero):
  region [ 12.. 15]   padding(qlimit->xmit_cnt) : 0 non-zero bytes
  region [ 52.. 55]   padding(qtype->red[0])    : 0 non-zero bytes
  region [ 56..223]   red[3]                    : 129 non-zero bytes
     01@56 dd@57 8a@58 18@59 01@60 f8@61 ff@62 ff@63 f8@64 f5@65 33@66
     18@67 01@68 f8@69 ff@70 ff@71 87@72 63@73 9a@74 80@75 ff@76 ff@77
     ff@78 ff@79 08@80 f6@81 33@82 18@83 01@84 f8@85 ff@86 ff@87
  kernel-pointer-looking 8-byte windows in red[]: 28

# OBSERVATIONS:
#  * Bytes consistent across runs at offsets 56-71, 75-79 (re-occurring kernel
#    text/data pointers 0xffffffff80xxxxxx, 0xffffffff81xxxxxx, 0xffff...).
#  * Byte-for-byte variance at offsets 80-87, 88-95, 96-103 across runs proves
#    these are stale stack frames, not static struct contents.
#  * With KASLR OFF, these recovered pointers are LIVE kernel addresses
#    (useful for KASLR bypass / as input to a separate primitive).