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

nsclpcsio unconditional TMS/VLM init writes to 8237A DMA controller when logical devices are disabled

Field Value
ID DF-1836
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:L
CWE CWE-1295 Debug Messages Revealing Unnecessary Information
File sys/dev/misc/nsclpcsio/nsclpcsio_isa.c
Lines 344-345
Area dev/misc (Super I/O attach)
Confidence certain
Discovered 2026-07-20
Reported pending
Known CVE none
CVE match dfly_specific

Summary

nsclpcsio_isa_attach calls nsclpcsio_tms_init and nsclpcsio_vlm_init unconditionally (lines 344-345) regardless of whether the TMS or VLM logical devices are activated. When a device is not activated, sc->sc_ld_ioh[ld_num] remains 0 (zero-initialized softc), and the TMS_WRITE/VLM_WRITE macros emit bus_space_write_1(iot, 0, reg, val), writing fixed constant values directly to legacy ISA I/O ports 0x08-0x0E β€” the 8237A DMA controller. Port 0x0D is DMA master clear (resets controller); port 0x0E clears all masks. Boot-time robustness bug with no security impact.

Root cause

nsclpcsio_isa_attach (line 287) initializes sc->sc_ld_en[ld_num]=0 and sc->sc_ld_ioh[ld_num]=0 at lines 306/333 only for activated logical devices. At lines 344-345, nsclpcsio_tms_init(sc) and nsclpcsio_vlm_init(sc) are called unconditionally β€” unlike the runtime refresh path (lines 384-386) which correctly guards with if (sc->sc_ld_en[...]).

Inside nsclpcsio_tms_init (line 391), TMS_WRITE(sc, 0x08, 0x00) at line 396 expands to bus_space_write_1(sc->sc_iot, sc->sc_ld_ioh[SIO_LDN_TMS], 0x08, 0x00) (macro at lines 194-196). With sc->sc_ld_ioh[SIO_LDN_TMS] == 0, this writes byte 0x00 to absolute I/O port 0x08. Subsequent writes hit ports 0x09-0x0E: port 0x0D receives 0x05 (TMS_WRITE(sc, 0x0d, 0x05) at line 401) which is DMA Master Clear β€” any write resets the entire DMA controller.

nsclpcsio_vlm_init (line 444) does the same with VLM_WRITE to ports 0x08-0x0E.

The softc zero-initialization was confirmed at subr_bus.c:1953-1954 (kmalloc with M_ZERO).

Threat model & preconditions

  • Attacker position: none β€” this fires at device attach time (boot), not by any user action.
  • Privileges gained or impact: no security-relevant impact. The written values are fixed constants (0x00, 0x0f, 0x08, 0x04, 0x35, 0x05), not attacker-controlled. The only possible disruption is to ISA DMA (floppy, ECP parallel port) on systems with a PC87366 Super I/O chip where the BIOS has not activated the TMS or VLM logical devices. Modern systems rarely use ISA DMA.
  • Required config or capabilities: PC87366 Super I/O chip with TMS/VLM logical devices disabled in BIOS; device nsclpcsio compiled in.
  • Reachability: boot-time only, not triggerable by any user.

Proof of concept

Not a security exploit β€” no PoC code is meaningful. To demonstrate the bug: on a system with a PC87366 Super I/O chip where TMS/VLM logical devices are disabled in BIOS, boot DragonFlyBSD with this driver compiled in. The DMA controller will be reset during device attach. Observable effect: floppy DMA operations or other ISA DMA-dependent devices may behave erratically if they rely on DMA state set by firmware.

Impact

Info-level hardening / robustness concern. No path to privilege escalation, code execution, or information disclosure.

Guard the init calls with sc->sc_ld_en checks, matching the pattern already used for the refresh path and sensor attach loop.

--- a/sys/dev/misc/nsclpcsio/nsclpcsio_isa.c
+++ b/sys/dev/misc/nsclpcsio/nsclpcsio_isa.c
@@ -341,8 +341,10 @@ nsclpcsio_isa_attach(device_t dev)
    kprintf("\n");
 #if NGPIO > 0
-   nsclpcsio_gpio_init(sc);
+   if (sc->sc_ld_en[SIO_LDN_GPIO])
+       nsclpcsio_gpio_init(sc);
 #endif
-   nsclpcsio_tms_init(sc);
-   nsclpcsio_vlm_init(sc);
+   if (sc->sc_ld_en[SIO_LDN_TMS])
+       nsclpcsio_tms_init(sc);
+   if (sc->sc_ld_en[SIO_LDN_VLM])
+       nsclpcsio_vlm_init(sc);

    /* Hook into hw.sensors sysctl */

This prevents bus_space writes to handle 0 (DMA controller ports) when a logical device is not activated. The GPIO init is also guarded for consistency β€” gpio_init (line 541) calls GPIO_READ/GPIO_WRITE which would similarly hit port 0 when GPIO is disabled, and gpio_register (line 372) is already guarded at line 364.

References

  • Runtime refresh path correctly guards with sc->sc_ld_en: nsclpcsio_isa.c:384-386.
  • gpio_register already guards on sc->sc_ld_en: nsclpcsio_isa.c:364.
  • Softc zero-initialization: subr_bus.c:1953-1954 (M_ZERO).

Timeline

  • 2026-07-20 Discovered during automated audit.
  • 2026-07-20 Reported to DragonFlyBSD security contact (pending).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1836 Β· 1 files
FileTypeDescriptionSize
fix.diff suggested-fix nsclpcsio unconditional TMS/VLM init writes to 8237A DMA controller when logical 485 B view raw

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

fix.diff authored but did not apply cleanly; needs context rework

fix.diff authored but did not apply cleanly; needs context rework
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none (Info severity)

Evidence (decisive lines)

Source-confirmed at sys/dev/misc/nsclpcsio/nsclpcsio_isa.c:344: unconditional TMS/VLM init writes to DMA controller when devices disabled

Verified recommended fix

Source-confirmed at sys/dev/misc/nsclpcsio/nsclpcsio_isa.c:344: unconditional TMS/VLM init writes to DMA controller when devices disabled

Verdict

Source-confirmed at sys/dev/misc/nsclpcsio/nsclpcsio_isa.c:344: unconditional TMS/VLM init writes to DMA controller when devices disabled