⬢ DragonFlyBSD Kernel Audit
DF-5445 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5445",
  "status": "reproduced",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "REPRODUCED on DragonFly 6.5-DEVELOPMENT (baseline #0), both faces. Face 1 (no-END stream): a card that keeps resource-data-ready asserted and never sends tag 0x78 keeps pnp_read_resources() (pnp.c:546-574) looping and pnp_read_bytes() growing the kmalloc buffer in 1 KiB steps with NO total-length cap \u2014 kldload NEVER returned (local timeout RC=124 after 50 s), the buffer reached a single 5.57 MB allocation at t+50 s and 12.41 MB at t+125 s and was still growing, a parallel vmstat ssh starved (RC=124), and the guest never recovered (reset required): kernel wedge + unbounded kernel-memory exhaustion. Face 2 (logical-device spray): 6000 PNP_TAG_LOGICAL_DEVICE tags (36 KB card stream) create 6000 bus children, each with an 8640-byte configs[] kmalloc inside pnp_parse_resources() plus ivars and a never-freed 24-byte csnldn \u2014 measured M_DEVBUF growth 208K->6.11MB (+5.9MB permanent, 211->11.9K chunks) for the 36 KB stream (~164x amplification); ldn is an unbounded int although the LDN register is 8-bit, so the face is unbounded. FIX VALIDATED on rebuilt kernel #1 (fix.diff: PNP_MAX_RESOURCE_DATA=64 KiB cap in pnp_read_resources + 256-LDN cap in pnp_create_devices): the exact wedge stream now completes in 4.26 s with pnp_read_resources: too much resource data and kldload RC=0 (guest healthy); the LD spray stops at isa0: too many logical devices with devbuf delta +258K (vs +5.9MB baseline).",
  "exploit_chain": "crafted ISA-PnP card -> endless ready-or-data byte service, no END tag -> pnp_read_resources infinite loop -> pnp_read_bytes unbounded kmalloc growth (1 KiB steps) -> kernel-memory exhaustion + permanently busy kldload/boot thread (wedge). Alternate face: endless LOGICAL_DEVICE tags -> per-tag device + ivars + csnldn (leaked) + 8640-byte configs[] allocation -> unbounded permanent kernel memory from a ~6-bytes-per-device card stream.",
  "evidence": "run_endless.log (SSH_RC=124, verbatim kmalloc growth samples 5566464..5570560 at t+50s and 12407808..12409856 at t+125s, starved second command, reset required); run_ldspray.log (baseline: devbuf 208K->6.11MB, 211->11.9K chunks, found=1, 6.57s load); fix_run_endless.log (patched: 4.26 s, RC=0, 7x too much resource data); fix_run_ldspray.log (patched: isa0: too many logical devices, devbuf +258K); rig/ (hack_dfc endless wrapper, hack_dfd spray wrapper)",
  "kernel_refs": [
    "sys/bus/isa/pnp.c:536-581",
    "sys/bus/isa/pnp.c:546-574",
    "sys/bus/isa/pnp.c:493-526",
    "sys/bus/isa/pnp.c:428-460",
    "sys/bus/isa/pnp.c:453-458",
    "sys/bus/isa/pnpparse.c:425-426"
  ],
  "poc_changes": "Same rig as DF-5443 (see its poc_changes). Script 3 synthesizes an endless 0x09/0x00 small-tag stream; script 4 emits 6000 finite LD tags + END.",
  "attempts": 2,
  "guest_uname": "baseline: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 / fixed: #1: Mon Oct 5 16:47:13 UTC 2026 (fix-validated kernel)",
  "runtime_sec": 1500,
  "guest_dirty": 0,
  "build_cmd": "(cd /usr/src/sys/bus/isa/hack_dfc && make obj && make depend && make); likewise hack_dfd",
  "run_cmd": "timeout 50 kldload .../rigdfc.ko   # baseline: RC=124 wedge; fixed: 4.3 s RC=0 ; kldload .../rigdfd.ko",
  "code_hash": "e4db996c97f7a4791e143a54d555297b7493f7759a96af75f02e72d484daba75",
  "notes": "Low severity: card-data DoS at boot/driver-load (no unprivileged-user path), but strictly unbounded by construction (no length or LDN cap anywhere in the engine) and demonstrated live. The csnldn kmalloc (pnp.c:453) is additionally leaked per logical device even in normal operation. The 64 KiB cap chosen in fix.diff is ~16x the largest real-world PnP card resource data; maintainers may tune.",
  "recommended_fix": "Cap total ingested resource bytes per card (PNP_MAX_RESOURCE_DATA=64 KiB) in pnp_read_resources() and cap logical devices at 256 (LDN register width) in pnp_create_devices() \u2014 full unified diff in fix.diff.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "Single-fix kernel (fix.diff, #1 Mon Oct 5 16:47:13): the exact wedge stream completes in 4.26 s with pnp_read_resources: too much resource data (RC=0, guest healthy, no unbounded growth); the LD spray stops at 256 devices with isa0: too many logical devices and devbuf delta +258K vs +5.9MB baseline. Baseline bad behavior GONE on both faces.",
  "fix_evidence": "fix_run_endless.log, fix_run_ldspray.log; fix_build.log + fix.diff (in DF-5443 pack)",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Mon Oct 5 16:47:13 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64"
}