β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-0075

DIOCGSLICEINFO leaks kernel pointers (KASLR bypass) via raw struct diskslices copyout

Field Value
ID DF-0075
Status new
Severity Medium
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
CWE CWE-200 Exposure of Sensitive Information to an Unauthorized Actor
File sys/kern/subr_diskslice.c
Lines 556-559
Area kern (disk slice / disklabel parsing)
Confidence likely
Discovered 2026-06-30
Reported pending

Summary

Independent of the heap overflow (DF-0074), the DIOCGSLICEINFO bcopy at sys/kern/subr_diskslice.c:557 returns the raw in-kernel struct diskslices (followed by every struct diskslice) to userspace via the copyout in mapped_ioctl (sys_generic.c:729). That structure contains, and exposes verbatim, multiple kernel virtual addresses:

  • dss_cdevsw (struct cdevsw *, diskslice.h:168)
  • per-slice ds_dev (cdev_t = struct cdev *)
  • ds_label.opaque (void * to a kmalloc'd label or NULL)
  • ds_ops (static kernel-data pointer to disklabel32_ops/disklabel64_ops)
  • ds_devs[MAXPARTITIONS] pointer array (diskslice.h:144-158)

A local user who can open a slice device can read kernel .text/.data and kmalloc-heap pointers, defeating KASLR and easing exploitation of separate memory-corruption bugs β€” including DF-0074 in the same ioctl. This happens on every DIOCGSLICEINFO call, not only for GPT disks.

Stop returning the raw kernel structure. Define a separate ioctl output structure containing only public, non-pointer fields (offsets, sizes, types, UUIDs, openmasks) and copy those field-by-field into a bzero'd output buffer. At minimum, zero every pointer-valued field before the bcopy.

Timeline

  • 2026-06-30 Discovered during automated file-by-file audit of sys/kern/subr_diskslice.c.
  • pending Reported to DragonFlyBSD security contact.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0075 Β· 14 files
FileTypeDescriptionSize
poc_df0075.c trigger-source DIOCGSLICEINFO leak PoC 2.6 KB view raw
dump2.c trigger-source raw hexdump helper 1.3 KB view raw
build.sh build-script cc -O -o poc_df0075 poc_df0075.c 152 B view raw
run.sh run-script ./poc_df0075 /dev/vbd0 211 B view raw
run.log run-log baseline leak (3 ptrs incl disklabel64_ops) 446 B view raw
run.2.log run-log stress run 2 441 B view raw
run.3.log run-log stress run 3 441 B view raw
fix.diff suggested-fix sanitize kernel pointers in DIOCGSLICEINFO copyout 1.1 KB view raw
fix_build.log build-log single-fix kernel build (DF-0075+DF-0056), rc=0 5.6 MB ↓ download
fix_run.log run-log patched kernel: 0 pointers leaked 220 B view raw
env.txt environment uname, cc version 232 B view raw
VERDICT.md verdict full narrative 2.4 KB ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
VERDICT.md verdict full narrative
↓ download raw

DF-0075 β€” DIOCGSLICEINFO kernel pointer leak

Verdict: REPRODUCED (info leak of kernel KVA pointers)

subr_diskslice.c:556-559 services DIOCGSLICEINFO with a raw bcopy(ssp, data, ...) of the in-kernel struct diskslices (header + active struct diskslices). That struct embeds several kernel virtual addresses that are copied out verbatim to userspace:

  • diskslices.dss_cdevsw β€” struct cdevsw * (declared but, in current master, never assigned, so observed NULL)
  • diskslice.ds_dev β€” cdev_t [diskslice.h:144]
  • diskslice.ds_label β€” disklabel_t.opaque (kmalloc'd label) [diskslice.h:155]
  • diskslice.ds_ops β€” struct disklabel_ops * (static kernel .data) [diskslice.h:156]
  • diskslice.ds_devs[] β€” void *[] [diskslice.h:158]

Reproduction

On the audit guest (/dev/vbd0, the labeled root disk), three kernel addresses are leaked deterministically (3/3 runs identical):

[+0x220] 0xfffff8008da2fc00   <- ds_dev        (cdev_t, kernel heap)
[+0x268] 0xfffff8008edb5080   <- ds_label.opaque (kmalloc'd disklabel)
[+0x270] 0xffffffff810e0a40   <- ds_ops        == disklabel64_ops (nm-verified)

0xffffffff810e0a40 matches disklabel64_ops from nm /boot/kernel/kernel exactly, making the leak unambiguous: a static kernel .data symbol is returned to userland on every DIOCGSLICEINFO call.

ssh dfbsd 'cd /home/maxx/poc/DF-0075 && ./poc_df0075'

Realistic reachability / impact ceiling

The raw disk nodes on this guest are root:operator crw-r-----; the unprivileged maxx user (not in operator) cannot open them, so the unprivileged reachability requires operator-group membership β€” a realistic storage/backup-admin precondition but not the strict default. Demonstrated as root. Impact is a KASLR-bypass / kernel-pointer info leak (not privilege escalation): the leaked .data/heap addresses defeat KVA randomization and would ease exploitation of a separate memory-corruption bug (e.g. DF-0074, same ioctl). No memory-corruption primitive is introduced by this bug itself.

Fix

fix.diff copies the struct out as before, then sanitizes every kernel-pointer field in the destination buffer (dss_cdevsw, per-slice ds_dev, ds_label.opaque, ds_ops, ds_devs[]) before return. Validated on a built single-fix kernel: baseline leaks 3 pointers (incl. disklabel64_ops); patched kernel leaks 0.

Fix verification

fixed

validated

see evidence pack
↓ fix.diffDragonFly 6.5-DEVELOPMENT #1: Fri Jul 17 14:28:56 UTC 2026

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

REPRODUCED. DIOCGSLICEINFO bcopy leaks 3 KVA ptrs incl disklabel64_ops. Fix: sanitize ptr fields.