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

Kernel heap address leak via incomplete pointer fix-up in ACPIIO_DO_MCALL Package results

Summary

acpi_call_fixup_pointers() only rewrites top-level String.Pointer/Buffer.Pointer when translating ACPICA result buffer for copyout. Does not handle ACPI_TYPE_PACKAGE nor recurse into nested Package elements. When ACPI method invoked via ACPIIO_DO_MCALL returns a Package (_BIF _BIX _PSL _PSS _CST _PCT) entire result buffer copyout()d with every internal pointer (Package.Elements nested Package.Elements nested String.Pointer nested Buffer.Pointer) left as raw kernel virtual addresses defeating KASLR/leaking kernel heap layout. ACPICA allocates single buffer whose internal pointers reference locations within same buffer. For Package with N elements user receives N+1 raw kernel heap addresses. Requires FWRITE on /dev/acpi (root) + debug.acpi.allow_method_calls=1 (boot-only loader tunable default 0). [VERIFIED pass2: reproduced on STOCK kernel via ACPIIO_DO_MCALL - Package method copyouts 7 plus raw kernel heap pointers per run 3 of 3; root plus FWRITE plus tunable gated so no unpriv reach; recursive pointer-scrub fix compile-validated]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2373 Β· 7 files
FileTypeDescriptionSize
README.md β€” 912 B ↓ raw
VERDICT.md β€” 1.3 KB ↓ raw
env.txt β€” 145 B view raw
fix.diff β€” 686 B view raw
reach.log β€” 564 B view raw
run.sh β€” 121 B view raw
verdict.json β€” 1.7 KB view raw

DF-2373 - ACPIIO_DO_MCALL leaks kernel heap pointers for Package results

acpi_call_fixup_pointers (acpi.c:3391-3401) only rewrites top-level String.Pointer/Buffer.Pointer. A Package result (e.g. _SB.PCI0._PRT from the stock QEMU DSDT) is copyout()d with Package.Elements and every nested sub-package Elements left as raw kernel virtual addresses.

Reproduce (STOCK kernel)

  1. echo "debug.acpi.allow_method_calls=1" >> /boot/loader.conf ; reboot
  2. cc -O -o mcall_leak mcall_leak.c -I/usr/src/sys/contrib/dev/acpica/source/include \ -I/usr/src/sys/contrib/dev/acpica/source/include/platform -I/usr/src/sys
  3. ./mcall_leak '_SB.PCI0._PRT' (root)

Expected (3/3 runs, see run.log): LEAKED-KERNEL-POINTERS: 7, e.g. Package.Elements = 0xfffff80118684018.

Reachability: /dev/acpi is 0644, but ACPIIO_DO_MCALL is a core ioctl behind the FWRITE gate - an unprivileged O_RDONLY fd gets EPERM (reach.log).

VERDICT.md
↓ download raw

DF-2373 VERDICT

Status: reproduced (reproduced) Impact: leak Confidence: certain Attempts: 3

Stock X86_64_GENERIC kernel with debug.acpi.allow_method_calls=1: ACPIIO_DO_MCALL on a Package-returning method hands the caller the full ACPICA result buffer with every internal pointer unfixed - top-level Package.Elements plus each nested sub-package Elements remain raw kernel virtual addresses. 3/3 runs leaked 7+ KVA pointers each (0xfffff801... heap layout). Gated: root FWRITE on /dev/acpi plus the boot-time loader tunable (unprivileged O_RDONLY ioctl returns EPERM - verified).

Kernel references

Guest

DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64

Fix validation

See fix.diff and README.md for the baseline/fixed A/B outputs (run.log / fixed.log).

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
↓ fix.diffper-fix-DF-2373

Confirmed kernel references

Detail

Exploit chain

root-gated kernel heap address disclosure (KASLR defeat primitive); no direct memory corruption

Evidence (decisive lines)

run.log runs 1-3 (Package.Elements = 0xfffff80118684018, elem[0..5] nested Elements all raw KVA); reach.log (unpriv ioctl EPERM)

PoC changes

seed mcall_leak.c from the pack was already runnable; re-ran on a fresh stock boot with the loader tunable, added the unprivileged-reachability probe

Verified recommended fix

see fix.diff

Verdict

Stock X86_64_GENERIC kernel with debug.acpi.allow_method_calls=1: ACPIIO_DO_MCALL on a Package-returning method hands the caller the full ACPICA result buffer with every internal pointer unfixed - top-level Package.Elements plus each nested sub-package Elements remain raw kernel virtual addresses. 3/3 runs leaked 7+ KVA pointers each (0xfffff801... heap layout). Gated: root FWRITE on /dev/acpi plus the boot-time loader tunable (unprivileged O_RDONLY ioctl returns EPERM - verified).