Unchecked AcpiEvaluateObject return in acpi_panasonic_hkey_event causes NULL-deref panic
Summary
acpi_panasonic_hkey_event calls AcpiEvaluateObject for HINF never checks return. On failure buf.Pointer NULL res->Type(:405) NULL-deref panic. Line :420 if(buf.Pointer)AcpiOsFree proves author knew buf.Pointer could be NULL but check too late. Triggered by ACPI notify 0x80 when Panasonic hotkey(Fn+F1-F10) pressed. Less severe than sinf requires ACPI event not sysctl read. [PASS-2 NOTES: DF-2589 duplicates the sinf half of DF-2386; DF-2590 same class in hkey_event - fold on triage; DF-1936 (kprintf log spam) actually lives at vega10_ih.c:288-301 not this file] [VERIFIED pass2: reproduced 4 of 4 - notify 0x80 with failing HINF panics at acpi_panasonic_notify+0x9f inlined NULL res->Type test via the real verbatim handler; status-check fix-validated, handler returns cleanly]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2590 Β· 15 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.4 KB | β raw | |
| VERDICT.md | β | 4.5 KB | β raw | |
| run.sh | β | 218 B | view raw | |
| run.log | β | 312 B | view raw | |
| run.2.log | β | 360 B | view raw | |
| run_fixed.log | β | 441 B | view raw | |
| panic.txt | β | 13.2 KB | view raw | |
| serial.txt | β | 19.7 KB | view raw | |
| panasim.c | β | 19.4 KB | view raw | |
| panasim.h | β | 1.1 KB | view raw | |
| pana_shim.c | β | 2.6 KB | view raw | |
| build.sh | β | 88 B | view raw | |
| fix.diff | β | 1.4 KB | view raw | |
| env.txt | β | 1.9 KB | view raw | |
| verdict.json | β | 4.4 KB | view raw |
DF-2590 β PoC evidence pack
Finding: acpi_panasonic_hkey_event() calls AcpiEvaluateObject
for HINF and immediately dereferences res = buf.Pointer without
checking status or NULL
(sys/dev/acpica/acpi_panasonic/acpi_panasonic.c:403-405). Triggered
by an ACPI notify 0x80 (Panasonic Fn hotkey) when the evaluation
fails. The late if (buf.Pointer) AcpiOsFree at :420-421 shows the
author knew the pointer can be NULL β one check too late.
Rig
Same verbatim-interposition kernel harness as DF-2386 (see that
README). The real attach's
AcpiInstallNotifyHandler(acpi_panasonic_notify, sc) is captured by
the interposer; hw.panasim.cmd=3 dispatches notify 0x80 to the
captured real verbatim handler exactly the way ACPICA's deferred
notify thread would. hw.panasim.hinf_mode selects the HINF reply
(1 = integer happy path, 0 = evaluation failure, buffer untouched).
Build
sh build.sh # shared with DF-2386
Run
sh run.sh # happy-path notify, then armed failure -> panic
Expected result (baseline)
- happy path (
hinf_mode=1, HINF integer0x81): full verbatim notify path runs β key 1 decode, brightness action (SSET observed), realacpi_UserNotifyfires β no panic; - armed (
hinf_mode=0): injected notify β kernel panic (fatal trap inacpi_panasonic_hkey_event, fault va 0x0), captured inpanic.txt. - fixed build: device_printf "HINF evaluation failed", no panic.
DF-2590 β PoC verdict
File: sys/dev/acpica/acpi_panasonic/acpi_panasonic.c (:403-405)
Verdict: REPRODUCED β acpi_panasonic_hkey_event() discards
the AcpiEvaluateObject return for HINF and dereferences
res = buf.Pointer (NULL on any evaluation failure) at :405. An ACPI
notify 0x80 (Fn hotkey on Panasonic hardware) while HINF fails
panics the kernel at exactly that load. Same NULL-Type class as
DF-2386 but notify-reachable instead of sysctl-reachable; the late
if (buf.Pointer) AcpiOsFree(buf.Pointer) at :420-421 shows the
author knew the pointer can be NULL β the check is simply one
statement too late. Fixed build survives the identical injection
(A/B validated).
Line-accurate confirmation
acpi_panasonic.c:401-402βbuf.Length = ACPI_ALLOCATE_BUFFER; buf.Pointer = NULL;:403βAcpiEvaluateObject(h, "HINF", NULL, &buf);β status discarded.- ACPICA failure contract (nsxfeval.c:525-631, see DF-2386 VERDICT):
Pointerstays NULL on every failure. :404-405βres = (ACPI_OBJECT *)buf.Pointer; if (res->Type != ACPI_TYPE_INTEGER)β NULL deref.- Reach:
acpi_panasonic_notifycase0x80(:486-492) takes the serial and callsacpi_panasonic_hkey_event(:488) β on hardware this is the Fn-hotkey notify; no privilege involved in the fault context, but the trigger requires a firmware event.
Mechanical verification
Same rig as DF-2386 (see that VERDICT). The real attach registered
the verbatim acpi_panasonic_notify through the interposed
AcpiInstallNotifyHandler (captured handler+ctx). hw.panasim.cmd=3
dispatches notify 0x80 to the captured real handler from a
kthread, mirroring ACPICA deferred notify dispatch.
Baseline (kernel #4):
- happy path (
hinf_mode=1, HINF integer0x81): notify βacpi_panasonic_hkey_eventdecodes key,acpi_UserNotifyfired (notify_seen=1), handler returned, no panic β the notify plumbing is proven working first; - armed (
hinf_mode=0: HINF evaluation fails, buffer untouched): injected notify β kernel panic, 4/4 deterministic:
Stopped at acpi_panasonic_notify+0x9f: cmpl $0x1,(%rdi) db>
cmpl $0x1,(%rdi) is res->Type != ACPI_TYPE_INTEGER
(ACPI_TYPE_INTEGER == 1) with %rdi = res = NULL β the compiler
inlined hkey_event into acpi_panasonic_notify, hence the symbol;
the immediate 0x1 fingerprints :405 exactly the way 0x4
(ACPI_TYPE_PACKAGE) fingerprinted :279 in DF-2386. panic.txt
carries the serial capture (login: PANASIM: worker: exec cmd=3 /
PStopped at ...); the full trap block is lost to a console artifact
specific to the notify-thread context (ALL console output from that
thread is dropped β see notes), so the DDB stop line plus the
happy-path contrast plus the identical DF-2386 trap block constitute
the evidence set. The ssh session dies at trigger time
("Connection closed by remote host", run.2.log).
Reachability / privesc assessment (honest)
- Hardware precondition: Panasonic
MAT0019firmware; trigger is an ACPI notify (physical Fn key press) coinciding with an HINF evaluation failure (memory pressure / firmware anomaly). The attacker model is "person with the keyboard + a failing eval" or hostile/crafted firmware β matching the Low / AC:H / UI:R scoring. - Impact: NULL-deref panic in notify dispatch. No write primitive; not a privesc.
Fix validation (A/B)
Fixed kernel (#6): happy path unchanged (notify_seen=1); armed
injection β rig ring records
inject: dispatching notify 0x80 ... β eval HINF -> AE_NO_MEMORY β
inject: handler returned β handler returns cleanly (baseline
panicked at exactly this point), guest stays up (run_fixed.log).
Console-output note
During verification we observed that all console/msgbuf output originating from the injected-notify kthread is silently dropped (both kprintf lines and the trap block; only DDB own prints survive). This is a rig/console artifact of thread context, not driver behavior; it is why the 2590 trap block is shorter than DF-2386's.
Artifacts
run.log/run.2.log (baseline attempts), panic.txt (serial with
the DDB stop), run_fixed.log, rig sources, build.sh/run.sh,
build.log, fix.diff, env.txt.
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_testableConfirmed kernel references
Detail
Exploit chain
ACPI notify 0x80 on the MAT0019 device (Fn hotkey press; rig injects it to the captured real handler from a kthread, mirroring ACPICA deferred dispatch) -> acpi_panasonic_notify case 0x80 -> ACPI_SERIAL_BEGIN -> acpi_panasonic_hkey_event -> AcpiEvaluateObject(HINF) fails leaving buf.Pointer NULL -> res->Type load from NULL -> fatal trap, kernel panic. Ceiling is DoS from a firmware-event context; no unprivileged syscall trigger, no write primitive, no uid0 path.
Evidence (decisive lines)
panic.txt (serial: login: PANASIM: worker: exec cmd=3 / PStopped at acpi_panasonic_notify+0x9f cmpl 0x1,(%rdi) / db>); run.log + run.2.log (happy path notify_seen=1 then armed trigger kills the ssh session -- Connection closed by remote host); run_fixed.log + rig ring (fixed: inject: dispatching -> eval HINF AE_NO_MEMORY -> inject: handler returned, guest up)
PoC changes
No seed PoC existed; reused the DF-2386 rig and added the HINF reply mode knob plus notify injection: the interposed AcpiInstallNotifyHandler captures the verbatim acpi_panasonic_notify + softc context, and hw.panasim.cmd=3 dispatches notify 0x80 from a kthread (ACPICA dispatch model). Harness observations baked into the VERDICT: all console and msgbuf output originating from the injected-notify kthread is silently dropped by the console layer (both kprintf lines and the trap block; only DDB own print survives), so the full-format trap block of the sibling DF-2386 panic plus the 4/4 deterministic DDB stop line constitute the capture.
Verified recommended fix
acpi_panasonic_hkey_event: check the AcpiEvaluateObject status (device_printf + goto end on failure) and guard res == NULL before res->Type, matching the existing buf.Pointer guard at :420
Verdict
Confirmed on the verbatim driver in the DF-2386 kernel rig: acpi_panasonic_hkey_event discards the AcpiEvaluateObject status for HINF (acpi_panasonic.c:403) and dereferences res = buf.Pointer at :405; the driver sets buf.Pointer = NULL at :402 and ACPICA leaves it NULL on every failure path (nsxfeval.c:525-631). The rig captured the real verbatim acpi_panasonic_notify registered by the real attach and dispatched notify 0x80 exactly as ACPICA deferred dispatch would: happy path first (HINF integer 0x81 -> key decode, acpi_UserNotify fired, handler returned, no panic), then with the HINF evaluation failing the identical injection panicked the kernel 4/4 runs at Stopped at acpi_panasonic_notify+0x9f cmpl 0x1,(%rdi) -- that immediate (ACPI_TYPE_INTEGER == 1) fingerprints the res->Type != ACPI_TYPE_INTEGER test at :405 with %rdi = res = NULL (hkey_event inlined into notify), exactly as 0x4 fingerprinted :279 in DF-2386. The late if (buf.Pointer) AcpiOsFree at :420-421 proves the author knew the pointer can be NULL, one check too late. Trigger on hardware is an Fn-hotkey ACPI notify coinciding with an HINF evaluation failure (physical user + failing eval or hostile firmware) -- AC:H/UI:R as scored. NULL-deref panic, no write primitive, not a privesc. fix.diff (status check + res NULL guard) A/B validated: the identical armed injection makes the handler return cleanly with the guest staying up.
No comments yet.