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

acpi_asus probe/attach mutate the driver-wide static model tables (non-idempotent probe, cross-device state contamination)

Summary

The look-alike quirk branches write directly into the matched entry of the shared static acpi_asus_models[] (L2B probe sets L3C's lcd_get; A3G overwrites M6R's; M2N/W1N set xxN's wled_set; M5N/S5N clear xxN's mled_set; attach writes n_func). Probe is non-idempotent: a second device or reprobe observes contaminated entries, silently disabling genuine features; concurrent probes race on unsynchronized stores. Also the enabler of the DF-4409 removal mismatch. Const-tables + per-instance-copy fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

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

DF-4411 β€” acpi_asus probe/attach mutate the driver-wide static model tables (cross-device state contamination)

  • File: sys/dev/acpica/acpi_asus/acpi_asus.c (pass 2)
  • Class: CWE-1284 / CWE-1285 family (improper handling of inconsistent data / mutation of what should be immutable configuration) β€” hygiene/correctness, no memory corruption
  • Severity: Info β€” feature corruption on multi-device/reprobe scenarios only; requires matching ASUS/Samsung/EeePC firmware.

Defect (path:line)

acpi_asus_models[] and friends are static struct acpi_asus_model β€” one shared copy for the whole driver β€” yet acpi_asus_probe writes into the matched entry while quirking look-alike models:

  • acpi_asus.c:682 β€” model->lcd_get = NULL; (L2B borrows L3C's entry β€” permanently disables L3C's lcd_get for every later probe)
  • acpi_asus.c:689 β€” model->lcd_get = "\_SB.PCI0.SBSM.SEO4" style override for A3G borrowing M6R
  • acpi_asus.c:697 β€” model->wled_set = "WLED"; (M2N/W1N borrow xxN)
  • acpi_asus.c:705 β€” model->mled_set = NULL; (M5N/S5N borrow xxN)

and acpi_asus_attach does the same:

  • acpi_asus.c:807-808 β€” if (sc->model->n_func == NULL) sc->model->n_func = acpi_asus_notify; β€” writes the static entry.

Consequences: - probe is not idempotent: a DSDT exposing two ATK0100 devices (or a bus re-scan after resume/driver reload) probes entries in mutated state β€” e.g. first device "L2B" kills L3C's lcd_get, so a genuine L3C second device silently loses its LCD sysctl (acpi_asus_sysctl_init returns FALSE when lcd_get == NULL, acpi_asus.c:1134-1166); conversely an A3G device leaves M6R's entry pointing at A3G's method; - two concurrent probes (newbus children probing on different CPUs) race on unsynchronized pointer stores into shared statics; - makes handler-removal correctness depend on hidden table state (see DF-4409, whose workaround exists only because of this mutation).

Build / run

Not runnable on the audit guest (no ATK0100/ASUS010 nodes β€” env.txt). Code-reading exercise; no runtime PoC exists that an unprivileged user (or any user short of root + matching firmware + multiple devices) could drive.

Copy the matched entry into a per-instance struct acpi_asus_model in the softc and apply the quirks to the copy (see fix.diff sketch).

VERDICT.md
↓ download raw

DF-4411 VERDICT β€” untested (source-verified hygiene defect; firmware-gated)

Reproduced?

No. Status untested: requires matching ASUS/Samsung/EeePC firmware with (at least) two ATK0100-class devices or a reprobe cycle β€” the audit guest has zero such nodes (env.txt). No unprivileged trigger; impact is feature loss / silent model misconfiguration, not memory corruption.

Defect (certain from source)

Static driver-wide tables are mutated during probe/attach:

  • acpi_asus.c:682, 689, 697, 705 β€” the "looks like" quirk branches write model->lcd_get, model->wled_set, model->mled_set directly into the matched entry of static struct acpi_asus_model acpi_asus_models[] (acpi_asus.c:146) β€” and crucially they mutate the borrowed entry (L3C, M6R, xxN), not a copy.
  • acpi_asus.c:807-808 β€” attach writes sc->model->n_func (same class).

Because the entries are shared driver-wide and probe can run more than once (multiple children, bus rescan), the second probe of an actually-matching model observes the mutated entry: an L2B probe leaves L3C.lcd_get == NULL forever, so a real L3C loses dev.acpi.N.asus.lcd_backlight (acpi_asus_sysctl_init, acpi_asus.c:1133-1166, returns FALSE on NULL lcd_get). An A3G probe leaves M6R.lcd_get pointing at a method that only exists on A3G firmware. Concurrent probes on SMP additionally race on these unsynchronized stores (word-sized pointer writes; not exploitable, but technically a data race).

Also note the borrowed-entry mutation is per-boot-persistent: the driver cannot be detached and re-attached to recover the original table.

Impact ceiling

Info: silent feature loss/misconfiguration on multi-device or reprobe scenarios; enables the DF-4409 removal-mismatch hazard class. No security impact beyond that.

Fix

fix.diff sketch: keep the tables const, copy the matched entry into a softc-embedded struct acpi_asus_model model_copy in probe, and apply all quirks (including the n_func default from attach) to the copy. Not validated (no applicable hardware on the guest) β†’ 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 (driver requires ASUS/Samsung/EeePC firmware).

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

Confirmed kernel references

Detail

Evidence (decisive lines)

findings/poc/DF-4411/VERDICT.md, README.md, env.txt, fix.diff (per-softc model copy)

Verified recommended fix

Make the model tables const and apply quirks (incl. n_func default) to a per-instance copy in the softc (sc->model_copy); see fix.diff sketch.

Verdict

Source-verified hygiene defect: acpi_asus_probe mutates the driver-wide static model tables in place when applying look-alike quirks (acpi_asus.c:682 lcd_get=NULL for L2B-on-L3C, :689 A3G-on-M6R override, :697 wled_set, :705 mled_set=NULL) and attach writes sc->model->n_func (:807-808). The borrowed entry is modified, not a copy, so probe is non-idempotent: multi-ATK0100-device or reprobe scenarios observe contaminated entries (a prior L2B permanently disables a genuine L3C lcd sysctl via acpi_asus_sysctl_init :1133-1166 returning FALSE on NULL lcd_get), and concurrent probes race on unsynchronized stores. Info severity: silent feature loss / model misconfiguration, no memory corruption, no unprivileged trigger (firmware-gated, verified absent on guest - env.txt).