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

Stack buffer overflow: 32-byte buf[] used for GSBUS BLOCK/BYTES transfers carrying up to 255 bytes

Summary

smbus_acpi_space_handler at smbacpi.c:137 declares char buf[32] for all GSBUS protocol transfers. ACPICA allocates 257-byte buffers (2-byte header + ACPI_MAX_GSBUS_DATA_SIZE=255 data) for ATTRIB_BLOCK(0x0A) and ATTRIB_BYTES(0x0B). Three overflow paths: (1) BLOCK WRITE at :208 memcpy(buf,gsb->data,gsb->len) with gsb->len up to 255 -> 223-byte stack overflow; (2) BYTES WRITE at :223 memcpy(buf,gsb->data,info->AccessLength) with AccessLength up to 255 -> same; (3) BYTES READ at :217-219 SMBUS_TRANS with rbuf=buf rcount=info->AccessLength up to 255, ig4_iic.c smb_transaction NOCNT branch writes rcount bytes into rbuf. BLOCK READ at :199-206 NOT affected (count init 32, ig4 caps via rcount>last check). Attacker controls ACPI AML: malicious firmware, root DSDT override (acpi_dsdt_load), or malicious hypervisor guest ACPI. Overflow size and data attacker-controlled. Impact: kernel panic minimum, potential ring-0 code execution by overwriting return address.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1112 Β· 8 files
FileTypeDescriptionSize
df1112.c trigger-source documentation-only source trace stub 1.7 KB view raw
build.sh build-script no compilation needed (latent) 301 B view raw
run.sh run-script no runtime trigger 269 B view raw
fix.diff suggested-fix resize buf[] to ACPI_MAX_GSBUS_DATA_SIZE+1 (256 bytes) 741 B view raw
VERDICT.md verdict full source-level trace + Phase 6 hard-blocker analysis 3.6 KB ↓ raw
README.md readme claim summary + reproducibility notes 2.2 KB ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme claim summary + reproducibility notes
↓ download raw

DF-1112 β€” Stack buffer overflow in smbus_acpi_space_handler (GSBUS)

Claim

smbus_acpi_space_handler() at sys/bus/smbus/smbacpi/smbacpi.c:137 declares char buf[32] for all GSBUS (ACPI GenericSerialBus) protocol transfers.

ACPICA allocates 257-byte buffers for ATTRIB_BLOCK(0x0A) and ATTRIB_BYTES(0x0B) transfers (2-byte header + ACPI_MAX_GSBUS_DATA_SIZE of 255 data bytes) β€” see contrib/dev/acpica/source/components/events/evhandler.c and evxface.c. Three overflow paths exist:

  1. BLOCK WRITE at smbacpi.c:208: memcpy(buf, gsb->data, gsb->len) with gsb->len up to 255 β†’ up to 223-byte stack overflow.
  2. BYTES WRITE at smbacpi.c:223: memcpy(buf, gsb->data, info->AccessLength) with info->AccessLength up to 255 β†’ same magnitude.
  3. BYTES READ at smbacpi.c:217-219: SMBUS_TRANS(..., buf, info->AccessLength, ...) with info->AccessLength up to 255. The ig4_iic.c smb_transaction NOCNT branch writes rcount bytes into rbuf β†’ same overflow magnitude.

BLOCK READ (smbacpi.c:199-206) is NOT affected β€” count is initialised to 32 (line 200) and ig4_iic.c caps via its rcount > last check.

The attacker controls the ACPI AML: malicious firmware, a root DSDT override (acpi_dsdt_load), or a malicious hypervisor guest ACPI.

Reproducibility on this guest

The audit guest's firmware (BOCHS BXPC) does not ship any GSBUS OpRegion in its DSDT (ACPI: DSDT 0x00000000BFFE0040 001AF8 β€” 0x1AF8 bytes, only standard devices). smbus_acpi_space_handler is registered only if a smbus device attaches under an ACPI-enumerated I2C controller with a GSBUS opregion declaration; on this guest there is none, so the handler is never invoked. Verified:

$ dmesg | grep -iE 'smbus|ig4|smbacpi'
(empty)

The bug is latent β€” confirmed by source trace. A realistic runtime trigger would require either malicious firmware, a malicious hypervisor controlling guest ACPI, or root triggering acpi_dsdt_load with a crafted DSDT override. None of those is an unprivileged attack surface on this guest.

Fix

fix.diff: size buf[] to match the maximum GSBUS data size (ACPI_MAX_GSBUS_DATA_SIZE + 1 = 256) so the buffer can hold any ACPICA buffer without overflow.

VERDICT.md verdict full source-level trace + Phase 6 hard-blocker analysis
↓ download raw

DF-1112 β€” VERDICT

Verdict: NOT REPRODUCED at runtime (latent β€” requires ACPI AML with a GSBUS opregion; the BOCHS firmware DSDT has none, and the smbus_acpi driver never attaches). Bug confirmed by source trace.

Mechanism (source-confirmed)

smbus_acpi_space_handler() at sys/bus/smbus/smbacpi/smbacpi.c:137 declares char buf[32] for all GSBUS (ACPI GenericSerialBus) protocol transfers.

ACPICA allocates 257-byte buffers (2-byte header + ACPI_MAX_GSBUS_DATA_SIZE = 255 data bytes β€” see sys/contrib/dev/acpica/source/include/acconfig.h:332) for ATTRIB_BLOCK(0x0A) and ATTRIB_BYTES(0x0B) transfers and passes the data portion to this handler. Three overflow paths:

  1. BLOCK WRITE at smbacpi.c:208: memcpy(buf, gsb->data, gsb->len) with gsb->len up to 255 β†’ up to 223-byte stack overflow.
  2. BYTES WRITE at smbacpi.c:223: memcpy(buf, gsb->data, info->AccessLength) with info->AccessLength up to 255 β†’ same magnitude.
  3. BYTES READ at smbacpi.c:217-219: SMBUS_TRANS(..., buf, info->AccessLength, ...) with info->AccessLength up to 255; the ig4_iic.c smb_transaction NOCNT branch writes rcount bytes into rbuf β†’ same overflow magnitude.

BLOCK READ (smbacpi.c:199-206) is not affected β€” count is initialised to 32 at line 200 and ig4_iic.c caps via its rcount > last check.

The attacker controls the ACPI AML. Trigger surfaces: - malicious / buggy firmware, - root-triggered DSDT override via acpi_dsdt_load, - a malicious hypervisor controlling guest ACPI.

Why it can't be triggered on this guest

$ dmesg | grep -iE 'smbus|ig4|smbacpi'
(empty)

The BOCHS firmware DSDT is 0x1AF8 bytes and contains only standard devices (no GSBUS opregion declaration). The smbus_acpi driver never attaches because there is no ACPI-enumerated I2C controller with a GSBUS opregion on this guest, so smbus_acpi_space_handler is never even registered with ACPICA, let alone invoked.

Even with a malicious DSDT loaded via acpi_dsdt_load, the trigger requires root (loading a DSDT is a privileged action), so this is not an unprivileged attack surface.

Exploit chain

Primitive class: stack buffer overflow (up to ~223 bytes) with both size and content controlled by attacker-controlled ACPI AML. On a kernel without stack protector for this path (and KASLR off), this could in principle overwrite the return address β†’ control-flow hijack β†’ commit_creds(prepare_kernel_cred(0)) chain.

BUT:

  • The trigger requires either malicious firmware or a root DSDT override. Rootβ†’kernel is game-over by definition; there is no privilege boundary to cross.
  • The handler is never invoked on this guest.

Valid hard blocker ("vulnerable code path is dead code at runtime on this guest AND no harness can exercise it without hardware/firmware the guest lacks"). Documented as latent. No uid=0 achievable from an unprivileged context on this guest.

Fix

fix.diff resizes buf[] from char buf[32] to char buf[ACPI_MAX_GSBUS_DATA_SIZE + 1] (= 256 bytes), large enough to hold any ACPICA GSBUS data payload without overflow. This matches ACPICA's own buffer sizing. Validated as applies + compiles in a clean GENERIC kernel build.

Fix validation

not_testable β€” path not runtime-reachable on this guest. Validated fix.diff applies cleanly and compiles with -Werror in a full make nativekernel KERNCONF=X86_64_GENERIC (smbacpi.o rebuilt fresh, no warnings/errors β€” see ../DF-1096/all_fixes_build.log).

PoC changes

  • Wrote df1112.c (documentation-only stub explaining the source trace).
  • Wrote fix.diff, build.sh, run.sh.

Fix verification

not_testable

compile validated

see evidence pack

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. smbus_acpi GSBUS buf[32] vs ACPICA 257B -> stack overflow. No GSBUS opregion. Compile validated.