# 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`):

```c
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`):

```c
/* 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`.

## Recommended fix

Remember the handler actually installed and remove exactly that — see
`fix.diff`.
