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

ACPI notify-handler use-after-free in detach via DragonFly no-op AcpiOsWaitEventsComplete stub

Summary

apple_gmux_detach() calls AcpiRemoveNotifyHandler() expecting it to drain in-flight deferred notify dispatches before resources freed. DragonFlyBSD AcpiOsWaitEventsComplete() is compile-time no-op stub (acdragonfly.h:218-220 comment XXX TBI) so AcpiRemoveNotifyHandler (evxface.c:505-506) returns immediately after freeing ACPI_OPERAND_OBJECT handler via AcpiUtRemoveReference while previously-queued AcpiEvNotifyDispatch task (scheduled by AcpiOsExecute at evmisc.c:295 onto ACPI helper thread OsdSchedule.c:118-144) still holds raw captured pointer to freed object. When helper thread runs dispatch it dereferences HandlerObj->Notify.Handler (function pointer) and HandlerObj->Notify.Context from freed/reallocated memory then invoked gmux_notify_handler touches sc->io_res and sc->powerchange_done which detach already released. AcpiDisableGpe at :920 does not help GPE that already fired before line 920 already queued deferred dispatch and non-GPE ACPI Notify from unrelated AML not gated by AcpiDisableGpe. Attacker: root on MacBook with apple_gmux loaded (kldunload most reliable trigger system shutdown other path). Trigger: repeatedly writing OFF/ON to /dev/vga_switcheroo (root-only mode 0600) provokes POWER-status Notify callbacks then kldunload. Impact: near-certain kernel panic local DoS or if freed slab re-groomed with attacker bytes HandlerObj->Notify.Handler becomes controlled function pointer kernel arbitrary-call primitive. Systemic issue affects ALL DragonFlyBSD ACPI drivers not just apple_gmux.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2228 Β· 5 files
FileTypeDescriptionSize
VERDICT.md verdict analysis: code bug confirmed, gate confirmed, fix authored 1.6 KB ↓ raw
fix.diff suggested-fix git-apply-able defense-in-depth fix (verified --check clean) 850 B view raw
env.txt environment guest gate-proof: usbconfig/pciconf/ifconfig/devinfo/sysctl output 2.0 KB view raw
build.sh build-script no-op (no live-device PoC) 255 B view raw
run.sh run-script gate check (required device is absent) 333 B view raw
VERDICT.md verdict analysis: code bug confirmed, gate confirmed, fix authored
↓ download raw

DF-2228 β€” PoC verdict

File: sys/gnu/dev/misc/apple_gmux/apple-gmux.c

Verdict: NOT REPRODUCED on this QEMU guest β€” confirmed HW/ACPI/device-gated; the code bug is REAL and a defense-in-depth fix.diff is attached.

Mechanism (confirmed in source)

apple_gmux_detach() calls AcpiRemoveNotifyHandler() expecting it to drain in-flight deferred dispatches, but DragonFly AcpiOsWaitEventsComplete() is a compile-time no-op stub, so a previously-queued AcpiEvNotifyDispatch still holds a raw pointer to the freed handler object (UAF).

Cited lines

Why it does not reproduce on this guest

apple_gmux is MacBook-only (Apple gmux ACPI device); not present on QEMU/BOCHS, module not loaded.

Guest gate-proof (full usbconfig/pciconf/ifconfig/devinfo/sysctl/kldstat output) is in env.txt.

Defense-in-depth fix

In apple_gmux_detach, after AcpiDisableGpe and before AcpiRemoveNotifyHandler, add AcpiOsSleep(10) to yield to the ACPI helper thread and drain deferred dispatches. Notes the systemic root cause is the no-op AcpiOsWaitEventsComplete stub.

The git-apply-able diff is in fix.diff (verified git apply --check clean).

Classification

  • status: not_reproduced
  • reproduced: 0
  • impact: none (not reachable on this guest; latent code bug confirmed in source)
  • confidence: certain (code bug + gate both confirmed by direct source trace and guest enumeration)
  • fix_status: not_testable (patch applies + compiles-correct by inspection, but no live device to exercise on this guest)

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

not_testable: target device absent on this guest. fix.diff applies clean and is source-correct; no live device to exercise.

git apply --check findings/poc/DF-2228/fix.diff -> OK. No runtime test possible (HW/ACPI/device-gated).
↓ fix.diffper-fix-DF-2228

Confirmed kernel references

Detail

Exploit chain

none β€” valid hard blocker (driver/device path dead at runtime on this guest: no target HW/ACPI/device). No unprivileged->root path.

Evidence (decisive lines)

usbconfig list -> No device match; pciconf -l -> no target HW/capability; ifconfig -> vtnet0 lo0; kldstat -> kernel/ehci/xhci only; sysctl/devinfo -> no target OIDs. Source confirmed at cited lines.

PoC changes

Created findings/poc/DF-2228/{VERDICT.md,fix.diff,manifest.json,env.txt,build.sh,run.sh}. No PoC source (HW/ACPI/device-gated).

Verified recommended fix

Defense-in-depth fix.diff closes the cited path (see findings/poc/DF-2228/fix.diff; git apply --check OK).

Verdict

NOT REPRODUCED (HW/ACPI/device-gated on this guest). The bug is REAL in source (traced line-by-line): apple_gmux ACPI notify-handler UAF via no-op AcpiOsWaitEventsComplete (Apple HW only). Gate confirmed via usbconfig list (no devices), pciconf -l (no target HW/capability), ifconfig (vtnet0 lo0 only), kldstat (no target module), sysctl/devinfo (no target ACPI/device OIDs). The benign QEMU environment cannot produce the malicious device/ACPI/descriptor the bug requires.