DF-4812 / run.log
DF-4812 run log (full untrimmed console output of the decisive runs)
=====================================================================
Guest: DragonFly dfbsd 6.5-DEVELOPMENT #0 (in-guest built kernel, X86_64_GENERIC)
Setup: guest booted with QEMU_EXTRA="-acpitable file=.../ssdt_tosh.aml"
(SSDT v02 AUDIT TOSHCI defines \TSH0 with _HID=TOS6200; GHCI returns a
3-element package instead of the 6 the driver requires; ENAB returns 0)
Driver attach:
# kldload acpi_toshiba
acpi_toshiba0: <Toshiba HCI Extras> on acpi0
# devinfo -v | grep -i tosh
acpi_toshiba0 pnpinfo _HID=TOS6200 _UID=0 at handle=\TSH0
Single-read behavior (NOTE: DF sysctl(8) silently swallows failed leaf reads โ
show_var() does `if (i || !len) { error = 1; goto done; }` with no message and
main() returns warncount=0, so the trigger leaves NO trace for the victim user;
each sysctl(8) invocation performs TWO handler calls: size-estimate + real):
$ sysctl hw.acpi.toshiba.force_fan
rc=0 (no output)
# dmesg | tail -2
toshiba: invalid package! <-- acpi_toshiba.c:438, the leak path
toshiba: invalid package!
---------------------------------------------------------------------
RUN 1 (BASELINE, unprivileged user "maxx", 20,000 reads of force_fan)
before : acpica 469 46.0K 0 390M 221K
command: $ i=0; while [ $i -lt 20000 ]; do \
sysctl hw.acpi.toshiba.force_fan >/dev/null 2>&1; i=$((i+1)); done
after : acpica 39.5K 3.71M 0 390M 572K
DELTA : +39,031 M_ACPICA objects, +3.66 MB leaked (~190 B / invocation,
~2 objects/invocation = 1 object per hci_call() โ matches the two
handler calls per sysctl(8) invocation)
---------------------------------------------------------------------
RUN 2 (BASELINE stress, unprivileged, 20,000 iters x 2 nodes = 40,000 reads)
before : acpica 39.5K 3.71M 0 390M 572K
command: $ i=0; while [ $i -lt 20000 ]; do \
sysctl hw.acpi.toshiba.force_fan >/dev/null 2>&1; \
sysctl hw.acpi.toshiba.lcd_brightness >/dev/null 2>&1; i=$((i+1)); done
after : acpica 118K 11.0M 0 390M 1.25M
DELTA : +78.5K objects, +7.3 MB โ linear, unbounded
total markers in msgbuf after runs: 40,283 x "toshiba: invalid package!"
(msgbuf is a wrap-around ring; 60,000 invocations x 2 calls each)
---------------------------------------------------------------------
FIX VALIDATION (same guest, same SSDT, same load)
# cd /usr/src && patch -p1 < /tmp/df4812/fix.diff
(hunk #1 succeeded at 434 โ adds AcpiOsFree(results.Pointer) before the
early `return (ENXIO)`)
# cd /usr/src/sys/dev/acpica/acpi_toshiba && make obj && make [see fix_build.log]
# kldunload acpi_toshiba
# kldload /usr/obj/usr/src/sys/dev/acpica/acpi_toshiba/acpi_toshiba.ko
post-swap baseline: acpica 118K 11.0M 0 390M 1.32M
(the 11 MB leaked by the baseline module is of course
not recovered retroactively โ it stays allocated)
RUN 3 (PATCHED, identical load: 20,000 iters x 2 nodes = 40,000 reads)
command: $ i=0; while [ $i -lt 20000 ]; do \
sysctl hw.acpi.toshiba.force_fan >/dev/null 2>&1; \
sysctl hw.acpi.toshiba.lcd_brightness >/dev/null 2>&1; i=$((i+1)); done
after : acpica 118K 11.0M 0 390M 2.00M
DELTA : 0 objects, 0 bytes โ FLAT.
Requests counter climbed 1.32M -> 2.00M (~680K more allocations
serviced), and dmesg still shows fresh "toshiba: invalid package!"
markers, proving the same code path executed and now frees.
---------------------------------------------------------------------
Conclusion: unauthenticated local, silent, unbounded kernel heap (M_ACPICA)
leak of ~190 bytes per sysctl(8) invocation on any machine whose Toshiba GHCI
implementation answers with a package of < 6 elements; one-line fix verified:
leak gone, behavior otherwise unchanged.