Missing serial lock in acpi_panasonic_shutdown triggers KKASSERT panic on INVARIANTS kernels
Summary
acpi_panasonic_shutdown calls hkey_sound_mute without ACPI_SERIAL_BEGIN(panasonic). hkey_sound_mute asserts lock via ACPI_SERIAL_ASSERT(:374) expands KKASSERT(lockstatus==LK_EXCLUSIVE). INVARIANTS kernels panic on every shutdown. Production no-op but SSET evaluation races with concurrent sysctl/notify. All other callers properly acquire lock. Root reboot/halt triggers. Recursive panic prevents crash dumps. [VERIFIED pass2: reproduced both triggers - device_shutdown dispatch and REAL reboot panic at hkey_sound_mute+0xb9 assertion, reboot chain backtrace captured; serial-lock fix-validated - shutdown clean, guest cycles back unattended]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2591 Β· 14 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.5 KB | β raw | |
| VERDICT.md | β | 4.5 KB | β raw | |
| run.sh | β | 197 B | view raw | |
| run_fixed.log | β | 244 B | view raw | |
| panic_reboot.txt | β | 1.6 KB | view raw | |
| triggerA.txt | β | 525 B | view raw | |
| serial.txt | β | 19.3 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-2591 β PoC evidence pack
Finding: acpi_panasonic_shutdown() calls hkey_sound_mute()
without ACPI_SERIAL_BEGIN(panasonic)
(acpi_panasonic.c:231); hkey_sound_mute() opens with
ACPI_SERIAL_ASSERT(panasonic) (:374) which expands to
KKASSERT(lockstatus(&panasonic_serial, curthread) == LK_EXCLUSIVE)
(sys/dev/acpica/acpivar.h:172) β guaranteed panic on INVARIANTS
kernels at every shutdown/reboot of a system with this device.
Rig
Same verbatim-interposition kernel harness as DF-2386 (see that README). Two real triggers:
- A (
run.sh baseline cmd):hw.panasim.cmd=9makes the rig worker calldevice_shutdown(dev)β the same subr_bus dispatch (sys/kern/subr_bus.c:2154-2162) the reboot path uses for every device (MOD_SHUTDOWNβdevice_shutdown(root_bus)βbus_generic_shutdown, subr_bus.c:3549-3551, :2883-2890). - B (
run.sh baseline reboot): rootrebootend-to-end.
Build
sh build.sh # shared with DF-2386
Run
sh run.sh baseline cmd # trigger A: device_shutdown -> assert panic sh run.sh baseline reboot # trigger B: real reboot -> assert panic sh run.sh fixed cmd|reboot # fixed: no assert; clean shutdown
Expected result (baseline)
KKASSERT panic naming the panasonic serial (lockstatus β LK_EXCLUSIVE)
inside acpi_panasonic_shutdownβhkey_sound_mute, on the INVARIANTS
stock-style kernel. Fixed build: no assert, device_shutdown returns,
reboot completes cleanly.
DF-2591 β PoC verdict
File: sys/dev/acpica/acpi_panasonic/acpi_panasonic.c (:231, assert at :374)
Verdict: REPRODUCED β acpi_panasonic_shutdown() calls
hkey_sound_mute() without ACPI_SERIAL_BEGIN(panasonic); the callee
opens with ACPI_SERIAL_ASSERT(panasonic) (:374) which expands to
KKASSERT(lockstatus(&panasonic_serial, curthread) == LK_EXCLUSIVE)
(sys/dev/acpica/acpivar.h:172) β a guaranteed panic on INVARIANTS
kernels at every shutdown/reboot of a system with this device, plus
an unsynchronized SSET evaluation racing concurrent sysctl/notify on
production kernels. Both triggers verified through the real code path;
fixed build shuts down cleanly (A/B validated).
Line-accurate confirmation
acpi_panasonic.c:222-233βacpi_panasonic_shutdown:sc = device_get_softc(dev); mute = 1; hkey_sound_mute(sc->handle, HKEY_SET, &mute);β noACPI_SERIAL_BEGINanywhere in the function; every other caller path takes the serial (acpi_panasonic_sysctl:248/:262,acpi_panasonic_notify:487/ :492,acpi_panasonic_power_profile:509/:512).acpi_panasonic.c:370-374βhkey_sound_muteopens withACPI_SERIAL_ASSERT(panasonic).sys/dev/acpica/acpivar.h:172β the assert is a plainKKASSERT(unconditional in the header), active on INVARIANTS kernels.- Reboot chain: root
rebootβboot()β moduleMOD_SHUTDOWNβdevice_shutdown(root_bus)(sys/kern/subr_bus.c:3549-3551) βbus_generic_shutdown(:2883-2890) βDEVICE_SHUTDOWNdispatch (device_shutdown, :2154-2162) β verbatimacpi_panasonic_shutdown.
Mechanical verification
Same rig as DF-2386 (see that VERDICT). Two real triggers:
- A β
device_shutdown(dev)(the same subr_bus dispatch the reboot path uses;hw.panasim.cmd=9runs it in the rig worker):
panic: assertion "lockstatus(&panasonic_serial, curthread) == LK_EXCLUSIVE" failed in hkey_sound_mute at /usr/src/sys/dev/acpica/panasim/acpi_panasonic_verbatim.c:374
Debugger("panic")
Stopped at Debugger+0x7c: movb $0,0xbdd659(%rip)
The KKASSERT names the lock, the function, and line 374 of the verbatim file (path proves the assertion fired inside the verbatim driver code).
- B β real
rebootend-to-end (root), full backtrace captured (panic_reboot.txt):
boot() called on cpu#2
Switching to cpu #0 for shutdown
...
syncing disks... done
panic: assertion "lockstatus(&panasonic_serial, curthread) == LK_EXCLUSIVE" failed in hkey_sound_mute at ...acpi_panasonic_verbatim.c:374
Trace beginning at frame ...
hkey_sound_mute() at hkey_sound_mute+0xb9
acpi_panasonic_shutdown() at acpi_panasonic_shutdown+0x23
bus_generic_shutdown() at bus_generic_shutdown+0x53
acpi_shutdown() at acpi_shutdown+0x9
bus_generic_shutdown() at bus_generic_shutdown+0x53
Debugger("panic")
Exactly the claimed path: reboot β acpi bus shutdown β device shutdown β mute β assert. The panic fires mid-shutdown after disks synced (a recursive-panic-prone moment, as the finding notes).
Reachability / privesc assessment (honest)
- Hardware precondition: Panasonic
MAT0019firmware. Trigger: rootreboot/halt(PR:H in the CVSS) β on an INVARIANTS kernel with this driver attached, the assert fires on EVERY shutdown (deterministic, no race needed). - Production (non-INVARIANTS) kernels: the assert compiles out; the
residual defect is
acpi_panasonic_sset(SSET evaluation) running unlocked against concurrent sysctl/notify holders of the serial β a real but narrow protocol violation (CWE-667). - Impact: panic/DoS at shutdown; no memory corruption; not a privesc. Low severity upheld.
Fix validation (A/B)
Fixed kernel (#6), fix.diff hunk wrapping the mute in
ACPI_SERIAL_BEGIN/END:
- trigger A: rig ring records
worker: device_shutdown returned (no assert fired)(run_fixed.log); - trigger B: root
rebootβ clean shutdown,grep -c panicover the full serial log = 0, guest cycles and returns on its own.
Artifacts
run_fixed.log, panic_reboot.txt (trigger B, full assert +
backtrace), serial.txt (fixed-run serial), 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
- sys/dev/acpica/acpi_panasonic/acpi_panasonic.c:222-233
- sys/dev/acpica/acpi_panasonic/acpi_panasonic.c:370-374
- sys/dev/acpica/acpi_panasonic/acpi_panasonic.c:248
- sys/dev/acpica/acpi_panasonic/acpi_panasonic.c:487-492
- sys/dev/acpica/acpi_panasonic/acpi_panasonic.c:509-512
- sys/dev/acpica/acpivar.h:172
- sys/kern/subr_bus.c:3549-3551
- sys/kern/subr_bus.c:2154-2162
- sys/kern/subr_bus.c:2883-2890
Detail
Exploit chain
root reboot/halt -> boot() -> rootbus MOD_SHUTDOWN -> device_shutdown(root_bus) (subr_bus.c:3549-3551) -> bus_generic_shutdown (:2883-2890) -> DEVICE_SHUTDOWN -> verbatim acpi_panasonic_shutdown -> hkey_sound_mute without the panasonic serial -> ACPI_SERIAL_ASSERT KKASSERT fails (lockstatus != LK_EXCLUSIVE) -> panic mid-shutdown after disks synced. No attacker-controlled data; PR:H as scored. Rig trigger A reaches the identical dispatch via device_shutdown on the fake child for a controlled capture.
Evidence (decisive lines)
panic_reboot.txt (trigger B: assertion message naming panasonic_serial/hkey_sound_mute/verbatim line 374 plus the full backtrace acpi_panasonic_shutdown+0x23 <- bus_generic_shutdown+0x53 <- acpi_shutdown+0x9 <- bus_generic_shutdown+0x53); triggerA.txt (device_shutdown capture); run_fixed.log (trigger A: worker: device_shutdown returned (no assert fired); trigger B: clean reboot, grep -c panic over the whole serial log = 0, guest cycles back unattended)
PoC changes
No seed PoC existed; reused the DF-2386 rig and added worker cmd 9 (device_shutdown on the fake child -- the same kobj DEVICE_SHUTDOWN dispatch the reboot path performs) so the assert can be captured without consuming a full reboot cycle; the real reboot was then run end-to-end as trigger B on a separate boot.
Verified recommended fix
acpi_panasonic_shutdown: wrap the hkey_sound_mute call in ACPI_SERIAL_BEGIN(panasonic) / ACPI_SERIAL_END(panasonic), matching every other caller
Verdict
Confirmed on the verbatim driver in the DF-2386 kernel rig, through both real trigger paths. acpi_panasonic_shutdown calls hkey_sound_mute(sc->handle, HKEY_SET, &mute) with no ACPI_SERIAL_BEGIN(panasonic) anywhere in the function (acpi_panasonic.c:228-232) while every other caller path takes the serial (:248/:262, :487/:492, :509/:512); hkey_sound_mute opens with ACPI_SERIAL_ASSERT(panasonic) (:374), which expands to KKASSERT(lockstatus(&panasonic_serial, curthread) == LK_EXCLUSIVE) (acpivar.h:172) and panics on INVARIANTS kernels. Trigger A (device_shutdown(dev), the same subr_bus.c:2154-2162 DEVICE_SHUTDOWN dispatch the reboot path uses) panicked with the assertion naming hkey_sound_mute and line 374 of the verbatim file. Trigger B (root reboot end-to-end) captured the full chain: boot() -> acpi_shutdown -> bus_generic_shutdown -> acpi_panasonic_shutdown+0x23 -> hkey_sound_mute+0xb9 -> assertion panic at :374 after disks synced (the recursive-panic-prone moment the finding describes). Deterministic on every shutdown of an INVARIANTS kernel with this driver attached; production non-INVARIANTS kernels compile the assert out and keep only the unsynchronized SSET evaluation racing concurrent sysctl/notify holders. Root-triggered DoS at reboot, no memory corruption, not a privesc. fix.diff (ACPI_SERIAL_BEGIN/END around the mute) A/B validated: device_shutdown returns with no assert and a real reboot completes with zero panics in the serial log.
No comments yet.