pnp_set_config() panics on card-supplied misaligned memory base (MEMORY32_RANGE/FIXED descriptors have no 256-byte granularity clamp)
Summary
A MEMORY32_RANGE base=0xE0001001 align=1 flows unmodified through pnpparse (which clamps only the 16-bit MEMORY_RANGE variant) -> isa_find_memory honors align=1 -> pnp_set_config panic('bogus memory assignment'). pnprig-verified through the real isa_driver_added->isa_assign_resources flow; granularity-clamp + panic-to-kprintf fix validated (graceful 'can't assign resources').
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5444 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.2 KB | β raw | |
| VERDICT.md | β | 2.5 KB | β raw | |
| verdict.json | β | 5.1 KB | view raw | |
| manifest.json | β | 984 B | view raw | |
| panic.txt | β | 521 B | view raw | |
| serial_runB_full.log | β | 2.6 KB | view raw | |
| fix_run.log | β | 548 B | view raw | |
| env.txt | β | 382 B | view raw |
DF-5444 β pnp_set_config() panics on card-supplied misaligned memory base (sys/bus/isa/pnp.c:260-261)
What
pnp_set_config() (the ISA_SET_CONFIG_CALLBACK installed by
pnp_create_devices, pnp.c:456-457) executes
panic("pnp_set_config: bogus memory assignment") when the assigned memory
base has bits below 0x100 set. The base is card-controlled end-to-end:
pnp_parse_desc()PNP_TAG_MEMORY32_RANGE stores a fully arbitrary 32-bitir_startandir_alignfrom the card (pnpparse.c:295-300) β no 256-byte granularity clamp (unlike PNP_TAG_MEMORY_RANGE at pnpparse.c:266-269 which forces align β₯ 0x10000);isa_find_memory()(isa_common.c:128-148) starts its candidate loop at the card-suppliedir_startand steps byMAX(align,1)β with align=1 the first candidate is the misaligned base itself;- the config callback then panics (pnp.c:260-261).
Same reachability for PNP_TAG_MEMORY32_FIXED (pnpparse.c:323-328, align=1, fixed base).
Trigger model
Crafted ISA-PnP card (or emulated/counterfeit PnP device in a VM) declaring
a logical device with MEMORY32_RANGE base=0xE0001001 align=1 size=1.
Boot-time / driver-load-time kernel panic = DoS (DS_ATTACHED-gated identify
notwithstanding: the kldloadβisa_driver_added path runs the whole engine,
see DF-5392).
Rig
Same rig/ as DF-5443 (verbatim pnp.c engine + virtual card). Module
hack_dfb (script 2): card declares one logical device with the misaligned
MEMORY32_RANGE above and a valid END tag. pnp_create_devices (real code)
creates the child with the real pnp_set_config callback;
isa_driver_added's child loop (isa_common.c:835-862) then runs
isa_assign_resources β callback β panic.
Build / Run
(cd /usr/src/sys/bus/isa/hack_dfb && make obj && make depend && make) kldload /usr/obj/usr/src/sys/bus/isa/hack_dfb/rigdfb.ko
Expected
Baseline: panic: pnp_set_config: bogus memory assignment, trace
pnp_set_config <- isa_assign_resources <- isa_driver_added <- devclass_add_driver.
Fixed kernel (fix.diff: pnpparse.c clamps MEMORY32_* granularity to 0x100 and rounds bases to 256; pnp.c degrades gracefully instead of panicking): no panic, warning printed, kldload returns 0.
DF-5444 VERDICT β REPRODUCED (kernel panic; card-driven DoS)
Bottom line
panic("pnp_set_config: bogus memory assignment") (sys/bus/isa/pnp.c:261)
was triggered through the real kernel flow on the guest by a card
declaring MEMORY32_RANGE base=0xE0001001 align=1 size=1. The single-fix
kernel (fix.diff) turns the identical stream into a graceful resource
rejection.
Chain (all real code; rig only virtualizes the card's port behaviour)
- Card bytes β
pnp_parse_desc()PNP_TAG_MEMORY32_RANGE stores arbitrary 32-bitir_start/ir_alignβ no 256-byte granularity clamp (pnpparse.c:295-300), unlike PNP_TAG_MEMORY_RANGE which forces align β₯ 0x10000 (pnpparse.c:266-269). isa_driver_added()child loop (isa_common.c:835-862) βisa_assign_resources()βisa_find_memory()(isa_common.c:128-148): candidate loop starts at the card base and steps byMAX(align,1)β with align=1 the first candidate is the misaligned base; rman grants it (0xE0001001 is free on this guest).- Config callback = the real
pnp_set_config(installed at pnp.c:456-457) βstart & 0xffβ panic (pnp.c:260-261).
Same reachability via PNP_TAG_MEMORY32_FIXED (pnpparse.c:323-328: fixed arbitrary base, align=1).
Evidence
Baseline (kernel #0): panic.txt / serial_runB_full.log β
panic: pnp_set_config: bogus memory assignment pnp_set_config() at pnp_set_config+0x192 isa_assign_resources() at isa_assign_resources+0x9e7 isa_driver_added() at isa_driver_added+0x106 devclass_add_driver() ... module_register_init()
Fixed (kernel #1, fix.diff): fix_run.log β RUN_B_RC=0,
(null) can't assign resources (memory) (rounded base no longer fits the
1-byte window β config rejected β device disabled), guest healthy.
Fix
pnpparse.c: MEMORY32_RANGE/MEMORY32_FIXED granularity clamped to 0x100 with
bases rounded up; pnp.c: panic downgraded to kprintf + truncation (defense
in depth). Validated above; full diff in fix.diff (shared with the
DF-5443/DF-5445 packs; build log in DF-5443/fix_build.log).
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
fixedSingle-fix kernel (fix.diff, #1 Mon Oct 5 16:47:13): the exact baseline-panic card stream loads with RUN_B_RC=0; the rounded base no longer fits the card's 1-byte window so the config is gracefully rejected ('(null) can't assign resources (memory)'), the device is disabled, no panic, guest healthy. Baseline bad behavior GONE.
fix_run.log (RUN_B_RC=0, resource-rejection message, healthy uptime); fix_build.log (in DF-5443 pack; full kernel build of the fixed tree); fix.diff (git apply --check clean)
Confirmed kernel references
Detail
Exploit chain
crafted ISA-PnP card (or VM-emulated PnP device) -> MEMORY32_RANGE base 0xE0001001 align=1 -> pnp_parse_desc stores arbitrary 32-bit start/align (pnpparse.c:295-300) -> ISA_ADD_CONFIG -> isa_driver_added -> isa_assign_resources -> isa_find_memory first candidate = misaligned base, allocated (isa_common.c:130-147) -> id_config_cb = pnp_set_config -> panic('bogus memory assignment') (pnp.c:260-261) -> kernel panic at boot/driver-load = denial of service.
Evidence (decisive lines)
panic.txt + serial_runB_full.log (baseline: panic trace through isa_assign_resources/isa_driver_added); fix_run.log (patched kernel: RUN_B_RC=0, '(null) can't assign resources (memory)', uptime healthy); fix.diff (pnpparse.c granularity clamps + pnp.c panic->kprintf); rig/ (hack_dfb wrapper, script 2)
PoC changes
Same rig as DF-5443 (see its poc_changes). Script 2 serves a 27-byte resource stream: LOGICAL_DEVICE tag (len 5) + MEMORY32_RANGE (0x85, len 17, base/endbase 0xE0001001, align 1, size 1) + END. No kprintf in the card path beyond PNPRIG markers; the panic comes from the unmodified pnp.c text.
Verified recommended fix
Enforce 256-byte memory granularity in pnpparse.c MEMORY32_RANGE/MEMORY32_FIXED (align>=0x100, base rounded up), and replace pnp_set_config()'s panic with a kprintf + base truncation β full unified diff in fix.diff.
Verdict
REPRODUCED on DragonFly 6.5-DEVELOPMENT (baseline #0). Same rig family as DF-5443 (verbatim pnp.c engine + virtual card). The card declares one logical device whose MEMORY32_RANGE descriptor carries base=0xE0001001, align=1, size=1. The REAL kernel code path runs end-to-end: pnp_create_devices() creates the child with the real pnp_set_config callback (pnp.c:446-457); after identify returns, isa_driver_added()'s child loop (isa_common.c:835-862) calls isa_assign_resources() -> isa_find_memory() (isa_common.c:128-148) which starts its candidate loop AT the card-supplied base with MAX(align,1)=1 stepping, so the first candidate is the misaligned base itself and rman grants it; the config callback then hits 'if (start & 0xff) panic("pnp_set_config: bogus memory assignment")' at pnp.c:260-261. Observed: 'panic: pnp_set_config: bogus memory assignment' with trace pnp_set_config <- isa_assign_resources <- isa_driver_added <- devclass_add_driver <- module_register_init (the genuine kldload flow). Root cause is the missing 256-byte granularity clamp for MEMORY32_RANGE/MEMORY32_FIXED in pnpparse.c (295-300, 323-328) β unlike PNP_TAG_MEMORY_RANGE which forces align>=0x10000 (pnpparse.c:266-269) β combined with a panic() as the failure mode in pnp.c. FIX VALIDATED on rebuilt kernel #1 (fix.diff: pnpparse clamps MEMORY32_* alignment to 0x100 and rounds bases to 256; pnp.c downgrades the panic to kprintf + truncation): the identical card stream now loads with RUN_B_RC=0, graceful '(null) can't assign resources (memory)' (rounded base no longer fits the 1-byte window -> config rejected -> device disabled), guest healthy.
No comments yet.