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

acpi_asus_detach removes the wrong ACPI notify handler: installed handler survives detach and fires into freed/unloaded driver state (use-after-free)

Summary

attach installs sc->model->n_func (acpi_asus_eeepc_notify for the EeePC model) but detach removes hardcoded acpi_asus_notify - ACPICA removal matches the triple so it fails with an ignored error and the real handler stays registered. After the softc is freed, the next firmware notify runs the EeePC handler over freed memory (UAF read/write) or into unmapped module text after kldunload. Record-and-remove-the-installed-handler fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4409 Β· 5 files
FileTypeDescriptionSize
README.md β€” 2.4 KB ↓ raw
VERDICT.md β€” 2.4 KB ↓ raw
env.txt β€” 1.9 KB view raw
fix.diff β€” 1.3 KB view raw
verdict.json β€” 2.5 KB view raw

DF-4409 β€” acpi_asus detach removes the wrong notify handler: installed handler survives and keeps firing into freed/unloaded driver state (use-after-free)

  • File: sys/dev/acpica/acpi_asus/acpi_asus.c (pass 2)
  • Class: CWE-416 (use after free) / CWE-666 (mismatched removal)
  • Severity: Low β€” trigger requires root-initiated device detach or module unload while an ACPI notify fires (hotkey press on an EeePC/ASUS laptop); no unprivileged path to the detach itself.

Defect (path:line)

attach (acpi_asus.c:807-811):

if (sc->model->n_func == NULL)
        sc->model->n_func = acpi_asus_notify;

AcpiInstallNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
    sc->model->n_func, dev);            /* installs acpi_asus_eeepc_notify
                                           for the EeePC model */

detach (acpi_asus.c:859-861):

/* Remove notify handler */
AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
    acpi_asus_notify);                   /* removes a DIFFERENT handler */

AcpiRemoveNotifyHandler matches on the (device, type, handler) triple. For the EeePC model (acpi_eeepc_models[0].n_func = acpi_asus_eeepc_notify, acpi_asus.c:455) the removal fails with AE_BAD_PARAMETER, which is ignored. After detach completes:

  • the newbus softc (context dev / sc) is freed β€” the still-installed handler's context now dangles; the next ACPI notify runs acpi_asus_eeepc_notify β†’ device_get_softc((device_t)context) (acpi_asus.c:1268) β†’ use-after-free read/write of freed memory, under whatever now occupies the softc slot;
  • if the module was also unloaded (kldunload acpi_asus), the handler address itself points into unmapped text β†’ control-flow into freed kernel memory.

Secondary correctness note: even for non-EeePC models the pattern works only by accident because attach overwrote the static table's n_func with acpi_asus_notify (see DF-4411 β€” mutating acpi_asus_models[]/acpi_eeepc_models[]).

Build / run

Not runnable on the audit guest: no ATK0100/ASUS010 ACPI nodes (see env.txt), so acpi_asus never attaches; kldunload/devctl detach requires root. On matching hardware the PoC would be: kldunload acpi_asus (or devctl detach) immediately followed by hotkey presses β†’ panic in acpi_asus_eeepc_notify or acpi_asus_notify.

Remember the handler actually installed and remove exactly that β€” see fix.diff.

VERDICT.md
↓ download raw

DF-4409 VERDICT β€” untested (source-verified use-after-free; root-gated, firmware-gated)

Reproduced?

No. Status untested: requires (a) an ASUS/Samsung/EeePC laptop whose ACPI exposes ATK0100/ASUS010 (the audit guest has none β€” verified live, env.txt) and (b) a root-initiated detach / kldunload acpi_asus racing a firmware notify. No unprivileged trigger.

Defect (certain from source)

  • attach installs sc->model->n_func as the ACPI_SYSTEM_NOTIFY handler with dev as context (acpi_asus.c:810-811). For the EeePC model that is acpi_asus_eeepc_notify (acpi_asus.c:455, table entry "EEE").
  • detach removes acpi_asus_notify β€” a different function pointer (acpi_asus.c:860-861). ACPICA removes handlers by the (device, handler-type, handler) triple, so the call returns AE_BAD_PARAMETER and the installed handler remains registered; the ignored return value hides this.
  • After acpi_asus_detach returns, newbus frees the softc. The surviving handler's next invocation (any hotkey/notify event) executes acpi_asus_eeepc_notify (acpi_asus.c:1261-1281): sc = device_get_softc((device_t)context) on freed memory, then acpi_device_get_parent_softc(sc->dev) and acpi_asus_sysctl_set(sc, ...) writing sc->s_brn β€” use-after-free read/write. With the module also unloaded, the handler text itself is gone β€” control transfer into unmapped memory.
  • Window: not merely theoretical β€” ACPI notifies are asynchronous EC events (lid/hotkey), and detach of a laptop-extra driver under an active ACPI namespace receives events routinely.

Impact ceiling

Root-gated panic / kernel memory corruption in freed softc (attacker needs root to detach; the freed-slot reuse is not attacker-shaped). DoS-class in practice; the UAF class justifies a memcorrupt-bucket filing for upstream correctness, but it is not an escalation primitive.

Fix

fix.diff: store the handler that was installed (sc->n_func) and remove exactly that in detach. Also stops attach from writing into the shared static model table (see DF-4411). Not validated on hardware (fix_status: not_testable).

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
baseline no→ patch + rebuild →patched clean

fix.diff authored from source analysis; cannot be validated on the audit guest - acpi_asus only attaches on ATK0100/ASUS010 firmware, absent from the guest namespace.

findings/poc/DF-4409/fix.diff; env.txt
↓ fix.diffper-fix-DF-4409

Confirmed kernel references

Detail

Exploit chain

root: kldunload acpi_asus (or devctl detach) while firmware notify pending -> handler survives removal -> notify fires into freed softc (UAF) / unmapped text. No unprivileged chain.

Evidence (decisive lines)

findings/poc/DF-4409/VERDICT.md (path:line trace), README.md, env.txt, fix.diff

Verified recommended fix

Record the installed handler in the softc (sc->n_func) and pass it to AcpiRemoveNotifyHandler verbatim in detach; see fix.diff.

Verdict

Source-verified use-after-free: acpi_asus_attach installs sc->model->n_func (= acpi_asus_eeepc_notify on EeePC, acpi_asus.c:455,810-811) with dev as context, but acpi_asus_detach removes hardcoded acpi_asus_notify (acpi_asus.c:860-861). ACPICA removal matches the (device,type,handler) triple, so it fails with an ignored AE_BAD_PARAMETER and the real handler survives detach. The next ACPI notify then runs acpi_asus_eeepc_notify over the freed softc (device_get_softc(context), acpi_asus.c:1268) - UAF read/write - or jumps into unloaded module text after kldunload. Untested at runtime: audit guest has zero ATK0100/ASUS010 ACPI nodes (env.txt) and the detach must be root-initiated, so no unprivileged trigger exists; practical ceiling is root-gated panic/corruption of freed softc memory.