amr_cam_attach overflows amr_cam_sim[] if controller reports more than AMR_MAX_CHANNELS channels
| Field | Value |
|---|---|
| ID | DF-1842 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:H |
| CWE | CWE-787 Out-of-bounds Write |
| File | sys/dev/raid/amr/amr_cam.c |
| Lines | 170-173, 210-214 |
| Area | dev/raid (MegaRAID CAM attach) |
| Confidence | likely |
| Discovered | 2026-07-20 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
amr_cam_attach loops for (chn = 0; chn < sc->amr_maxchan; chn++) writing
sc->amr_cam_sim[chn], but the array is declared
struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS] with AMR_MAX_CHANNELS == 8
(amrreg.h:85, amrvar.h:237). amr_maxchan is taken verbatim from
controller-reported ap->ap_nschan (amr.c:955) or
ae->ae_adapter.aa_channels (amr.c:990), both u_int8_t with no clamp. A
controller reporting more than 8 channels (firmware bug, malicious PCI device,
or compromised controller firmware) makes the loop write past the end of
amr_cam_sim into the adjacent softc fields (amr_cam_devq, amr_cam_ccbq,
amr_dev_t, amr_list_lock internals), corrupting the softc. amr_cam_detach
has the same shape (line 210) and will read past the array in the same
condition.
Root cause
amr_cam.c:170:
for (chn = 0; chn < sc->amr_maxchan; chn++) {
...
if ((sc->amr_cam_sim[chn] = cam_sim_alloc(amr_cam_action,
amr_cam.c:210 reads it back in the same shape during detach.
amrvar.h:237 declares struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS]; with
AMR_MAX_CHANNELS = 8 (amrreg.h:85).
amr.c:955 does sc->amr_maxchan = ap->ap_nschan; and amr.c:990 does
sc->amr_maxchan = ae->ae_adapter.aa_channels; β both copy a controller-supplied
u_int8_t directly into the field used as the loop bound with no imin/imax
clamp, unlike sc->amr_maxio which is clamped at amr.c:1005
(sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD);).
Threat model & preconditions
- Attacker position: local kernel memory corruption at device attach time (and readback at detach time). Not remotely reachable.
- Privileges gained or impact: panic, lock-state corruption, or arbitrary
pointer overwrite depending on the reported channel count. The overflow
corrupts fields immediately after
amr_cam_siminstruct amr_softc(amr_cam_devq,amr_cam_ccbq,amr_dev_t,amr_list_lock). - Required config or capabilities: a malicious/buggy PCI MegaRAID controller present at boot or hot-plug, or compromise of the controller firmware.
- Reachability: PCI bus enumeration of a controller that mis-reports its channel count.
Proof of concept
Reproducing on real AMI MegaRAID hardware requires a controller that mis-reports
its channel count, which is uncommon. To prove impact deterministically, stub
amr_query_controller (or use qemu with a custom fake prodinfo response that
sets ap_nschan to e.g. 16) and boot the resulting kernel:
- Patch amr.c:955 to
sc->amr_maxchan = 16;(development-only injection that simulates a lying controller). - Build a kernel, boot under kvm.
- Observe either (a) an immediate panic in
amr_cam_attachduringconfig_intrhook/bus_generic_attachwhen the loop writes pastamr_cam_sim[]intoamr_cam_devqand dereferences the corrupted pointer later, or (b) corruption ofamr_list_lockinternals leading to a lockmgr assertion/panic on first I/O.
Build & run
# Development-only kernel patch to simulate a lying controller: # sys/dev/raid/amr/amr.c:955 -> sc->amr_maxchan = 16; # Build kernel, boot under kvm with a faked MegaRAID PCI device.
Expected output
panic in cam_sim_alloc or lockmgr with a corrupted softc OR KKASSERT failure in amr_cam_action:406
The PoC value is demonstrating that the loop bound is unclamped; on production hardware with a well-behaved controller it will not trigger.
Impact
Low-severity because of the hardware-trust precondition. A malicious/compromised PCI MegaRAID controller can corrupt kernel memory at attach. Defense-in-depth: controller-reported counts must not be trusted as loop bounds without clamping.
Recommended fix
Clamp amr_maxchan to AMR_MAX_CHANNELS where it is read from the controller.
--- a/sys/dev/raid/amr/amr.c
+++ b/sys/dev/raid/amr/amr.c
@@ -952,7 +952,8 @@ amr_query_controller(struct amr_softc *sc)
return(1);
}
sc->amr_maxdrives = 40;
- sc->amr_maxchan = ap->ap_nschan;
+ sc->amr_maxchan = imin(ap->ap_nschan, AMR_MAX_CHANNELS);
sc->amr_maxio = ap->ap_maxio;
@@ -987,7 +988,8 @@ amr_query_controller(struct amr_softc *sc)
}
sc->amr_maxdrives = 8;
- sc->amr_maxchan = ae->ae_adapter.aa_channels;
+ sc->amr_maxchan = imin(ae->ae_adapter.aa_channels, AMR_MAX_CHANNELS);
sc->amr_maxio = ae->ae_adapter.aa_maxio;
Optionally also add a KKASSERT / KASSERT in amr_cam_attach that
sc->amr_maxchan <= AMR_MAX_CHANNELS before the loop, so the failure mode is a
controlled panic instead of silent heap corruption if some other path mutates
the field later.
References
- Sibling clamp on
amr_maxio: amr.c:1005 (sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD);). - Array bound: amrreg.h:85, amrvar.h:237.
Timeline
- 2026-07-20 Discovered during automated audit.
- 2026-07-20 Reported to DragonFlyBSD security contact (pending).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1842 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able fix for the cited bug | 379 B | view raw |
| VERDICT.md | verdict | source-confirmation analysis | 1.0 KB | β raw |
| build.sh | build-script | N/A (source-only) | 65 B | view raw |
| run.sh | run-script | N/A (source-only) | 89 B | view raw |
DF-1842 VERDICT
Verdict: REPRODUCED (source-confirmed)
Impact: Low (driver-level NULL deref / OOB / leak / DoS β hardware-gated)
Mechanism: amr_cam_attach L170 for(chn=0;chn
Citation: sys/dev/raid/amr/amr_cam.c:170-214
Fix: Applied fix.diff β compiles in batch kernel build (rc=0, -Werror).
Verification method: Source-only line-by-line trace of cited path:line. Low-severity driver bug; PoC trigger requires specific hardware or root context. Confirmed the cited vulnerable pattern exists in source.
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.
Fix verification
fixedfix.diff compiled in batch kernel build rc=0 -Werror
fix.diff compiled in batch kernel build rc=0 -Werror
Confirmed kernel references
β
Detail
Exploit chain
none (Low severity)
Evidence (decisive lines)
Source-confirmed: amr_maxchan from controller overflows amr_cam_sim[8] (amr_cam.c:170-173)
Verified recommended fix
Source-confirmed: amr_maxchan from controller overflows amr_cam_sim[8] (amr_cam.c:170-173)
Verdict
Source-confirmed: amr_maxchan from controller overflows amr_cam_sim[8] (amr_cam.c:170-173)
No comments yet.