v1.0.0-alpha.2.1 — defensive-hardening
Pre-releasev1.0.0-alpha.2.1 — defensive-hardening
Released: May 19, 2026
Tag: v1.0.0-alpha.2.1
Upstream base: crazii/USBDDOS at b1308fb + PR crazii#31 + PR crazii#32 carried as fork-side commits
Type of release
Defensive-hardening release. Two functional patch series targeting USB enumeration freezes and OHCI DMA-structure page-crossing risks. Both patch series are also open as PRs against upstream crazii/USBDDOS (PR crazii#31 and PR crazii#32 in this fork's release set) and are carried as fork-side commits in the alpha.2.1 binaries until they merge upstream.
This is NOT a housekeeping release. Alpha.2 was housekeeping. Alpha.2.1 is not. There are real code changes in:
USBDDOS/usb.c— descriptor parser hardeningUSBDDOS/HCD/ohci.c— no-page-crossing DMA allocationUSBDDOS/usballoc.c— pool arena no-page-crossingUSBDDOS/DPMI/dpmi_dj2.c— linear-address-space NCPB check fix
What's new
Gap I (PR crazii#31) — graceful-skip hardening for unsupported device classes
Four edits in USBDDOS/usb.c plus one new constant in USBDDOS/usb.h:
-
Improved no-driver-found log surfaces the full
bDeviceClass/bDeviceSubClass/bDeviceProtocoltriplet plus a human-readable class name (audio,wireless,miscellaneous(IAD),vendor, etc.):- Was:
No driver found at port: 0 for device (class 01), skip - Now:
No driver found at port: 0 for device (class 01/01/04 audio), skip
- Was:
-
Explicit Interface Association Descriptor recognition (
USB_DT_INTERFACE_ASSOCIATION = 0x0B) in the descriptor walker, with informational_LOGoffirstIf/count/funcClass. No semantic change — USBDDOS continues to bind class drivers at device level, not function level, and does NOT use IAD'sbFunctionClassfor driver lookup. -
bNumInterfaces > 32cap mirroring Linux'sUSB_QUIRK_HONOR_BNUMINTERFACESdefensive pattern. The cap value is persisted topConfigList[].bNumInterfacesso subsequent malloc and memset operate on the same size (regression guard against heap buffer overrun). -
Zero-length descriptor defensive break:
if (len == 0) break;in the walker loop. Without this, a malformed device emitting any descriptor withbLength = 0causes a hard infinite loop oni = i + len. Strong candidate fix for the tester's KT133A+NEC+mixed-class-hub freeze.
Gap H (PR crazii#32) — no-page-crossing enforcement for OHCI DMA structures
Three coordinated changes:
-
USBDDOS/HCD/ohci.c: apply theDPMI_DMAMalloc → DPMI_DMAMallocNCPBmacro override at the top of the file, mirroring the pattern EHCI has used since its bring-up (ehci.c:25-30). OHCI's HCData allocation is the highest-risk site: it embeds the 256-byte HCCA plus 8 static EDs (~548 bytes total) and a plainDPMI_DMAMalloccould place it straddling a 4KB page boundary, silently breaking DMA for either the HCCA or the static EDs. -
USBDDOS/HCD/ohci.c: add DEBUG-build defense-in-depth assertions at the HCCA register-write site verifying the produced allocation actually fits within a single physical page. -
USBDDOS/usballoc.c: switch pool-arena allocations (both the on-demandUSBALLOC_GetMemorypath and theUSBALLOC_Initpre-allocation path) fromDPMI_DMAMalloctoDPMI_DMAMallocNCPB. Variable-size paths stay on plainDMAMallocbecause transfer buffers may legitimately exceed a page (OHCI § 3.1.1.1 supports buffers spanning one page boundary via the TD'sCBP/BEmechanism).
Bug fixed in the same commit: DPMI_DMAMallocNCPB in dpmi_dj2.c (DJGPP build path) was checking page boundaries in C-pointer-relative space rather than linear-address space. Under HDPMI32 with a non-page-aligned XMS mapping base — observed XMS lbase 002e1c00 (offset 0xC00 within its page) on QEMU — C-pointer "pages" and linear "pages" live on different grids offset by (DPMI_DSBase & 0xFFF). An allocation that NCPB previously declared page-contained in C-pointer space could still straddle a linear page boundary, which is what the hardware sees for DMA. The fix translates via DPMI_DSBase before the boundary test.
The Watcom/Borland path (dpmi_bc.cpp:991) was already correct — it uses DPMI_PTR2L(ptr) to get the linear address before the check, so only the DJGPP build was affected. EHCI was latently exposed to the same bug since its bring-up but evidently has not been hit in practice because its DMA structures (QH 96B, QTD 32B, iTD 64B) are small enough that the probability of crossing a linear-page boundary is much lower than for OHCI's 548-byte HCData.
Recommended upgrade triggers
- Hit the unsupported-class enumeration freeze. Typical: USB audio, Bluetooth dongle, or wireless-USB device behind a hub alongside HID devices. Specifically reported on KT133A + NEC µPD720101 + 4-port hub with USB microphone (class 0x01), BT dongle (class 0xE0), and two composite HID devices.
- Suspect OHCI DMA corruption on a DJGPP build using HDPMI32. XMS heap linear base may not be page-aligned, exposing the latent NCPB bug fixed in this release.
- Running alpha.1 or alpha.2 without observed symptoms: upgrade is optional but recommended.
Real-hardware verification status
The alpha label is retained for this release.
Both patch series were verified in QEMU (OHCI + usb-audio enumeration, mixed-class kbd + audio scenario across two OHCI controllers) and via a native-Linux unit test exercising the descriptor parser against synthetic descriptors (5 cases: audio with CSINTERFACE chain, IAD composite, bNumInterfaces=200 cap, malformed zero-length descriptor, interface overrun — all pass).
Real-hardware report against the original tester's KT133A+NEC configuration is still pending. If you can test on real silicon and file a report, please open an issue at Netrunner01/USBDDOS/issues.
The "alpha" label means real-hardware verification on the silicon the patches target is still pending — it does NOT mean the code is unstable or broken. Promotion to beta or v1.0.0 still requires at least one independent real-hardware test report per patched gap.
Build provenance
All four binaries in usbddos-v1.0.0-alpha.2.1-bundle.zip were built from the release-branch tip at commit 810b58b on a Linux x86_64 sandbox with DJGPP gcc 12.2.0 and Open Watcom v2.0 beta. DJGPP binaries embed the build-ID string 810b58b, DJGPP. Watcom binaries are bit-stable across rebuilds at the same commit.
| Binary | Toolchain | Mode | Size |
|---|---|---|---|
USBDDOS.EXE |
Open Watcom v2 | release | 65,402 |
USBDDOS-DEBUG.EXE |
Open Watcom v2 | DEBUG | 95,348 |
USBDDOSP.EXE |
DJGPP 12.2.0 | release | 208,384 |
USBDDOSP-DEBUG.EXE |
DJGPP 12.2.0 | DEBUG | 368,295 |
All four builds compile clean with the project's existing -Werror -Wconversion -Wsign-compare -pedantic-errors flag set.
Notes
- No CWSDPMI / HDPMI32 host preference change recommended. The NCPB fix is in the DJGPP build path (
USBDDOSP.EXE). The Watcom build (USBDDOS.EXE) was never affected. - QEMU regression test coverage: 7-test ladder still passes 7/7, plus an 8th test case (OHCI + usb-audio with HDPMI32 capturing the graceful-skip log line) passes.
- After PRs crazii#31 and crazii#32 merge upstream, a future alpha.3 release will cut from that new upstream tip (mirroring the alpha.1 → alpha.2 cycle).
License
GPL-2.0. See COPYING inside the release bundle. Source for these binaries is at this tag.