_mapping_find_enc_map_space clears the WRONG enclosure entry (et_entry instead of enc_entry), off-by-one overlap test, stale num_found (mps twin of DF-3917)
Summary
During enclosure-table defragmentation: (1) the eviction path clears et_entry - the NEW enclosure being added - instead of enc_entry, the evicted overlapping one; (2) the overlap skip test treats the first slot PAST the enclosure as inside, clearing a map entry owned by the next enclosure; (3) skip_search is reset on the wrong entry and num_found is not reset before the third search loop, so start_idx undershoots the free run and the caller's reservation loop steals still-owned slots. All writes remain within the tables; the corrupted num_slots/start_slot then feed the known DF-1375 slot arithmetic. Identical defects in mpr_mapping.c (DF-3917 twin). 4-hunk fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4088 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 3.1 KB | β raw | |
| VERDICT.md | β | 2.6 KB | β raw | |
| env.txt | β | 1.4 KB | view raw | |
| fix.diff | β | 1.1 KB | view raw | |
| manifest.json | β | 620 B | view raw | |
| verdict.json | β | 2.4 KB | view raw |
DF-4088 β _mapping_find_enc_map_space clears the WRONG enclosure entry (et_entry vs enc_entry), off-by-one overlap test, stale num_found
File: sys/dev/raid/mps/mps_mapping.c:743-868
Class: CWE-697 wrong variable + off-by-one + stale accumulator (mps twin
of mpr sibling finding DF-3917; the mpr file mpr_mapping.c:1075-1121
carries the identical three defects line-for-line)
Severity: Low β pass 2 (GLM 5.3), bucket base:dev
Confidence: certain
The bugs
-
Wrong variable in the eviction clear (
:845-847):c if (map_idx == (enc_entry->start_index + enc_entry->num_slots - 1)) _mapping_clear_enc_entry(et_entry); /* should be enc_entry */Inside the loop that evicts the overlapping old enclosure (enc_entry), the code clears the new enclosure being added (et_entry): zeroes itsnum_slots,enclosure_id,phy_bits,dpm_entry_num(= BAD). The caller (_mapping_get_dev_info:972-998) then reservesnum_slots(=0) entries and stores the foundstart_indexinto the half-wiped entry, so every later_mapping_add_new_device:1165slot computation (start_index + slot - start_slot, withstart_slotalso zeroed) and the DPM commit path operate on corrupted enclosure state. -
Off-by-one overlap test (
:829-831): an enclosure owns map-table slots[start_index, start_index + num_slots); the skip testmap_idx > (enc_entry->start_index + enc_entry->num_slots)treatsmap_idx == start+num_slots(the first slot past the enclosure) as inside, so eviction clears one map entry belonging to the next enclosure (_mapping_clear_map_entry(mt_entry)at:843). -
Stale accumulator (
:783-820):num_foundis not reset before the third (post-eviction) search loop at:809; it retains the tail count of the second loop, sostart_idx = (map_idx - num_found) + 1(:815) can point before the actually-contiguous free run β entries still owned by other enclosures get markedMPS_DEV_RESERVEDby the caller's reservation loop (:993-998), silently stealing slots.
Impact
Mapping-table state corruption on the enclosure-defragmentation path
(reachable whenever table pressure forces eviction of a missing enclosure):
devices mapped into wrong/stolen slots, enclosures with zeroed metadata,
removal bookkeeping (removal_table) entries for the wrong handles, DPM
entries committed with wrong DeviceIndex/slot data. All writes stay within
the tables (indices bounded by end_of_table <= max_devices in this
function), so the direct impact is correctness/persistence, not OOB β it
feeds the already-filed DF-1375 slot arithmetic with corrupted
start_slot/num_slots, which is what keeps it security-relevant.
Hardware-gated for in-kernel reproduction (env.txt).
Fix
fix.diff β (a) > β >= in the overlap skip test; (b) clear enc_entry
(not et_entry) at the last-slot eviction point; (c) reset enc_entry's
(not et_entry's) skip_search flag at :862; (d) num_found = 0 before
the third search loop. Compile-validated with the batch (-Werror,
mps.ko linked β fix_build.log in DF-4085's pack).
DF-4088 VERDICT
Status: untested β hardware-gated (no mps HBA on the audit guest,
env.txt); Low-severity mapping-state-corruption class, PoC skipped per
batch precedent (mpr twin DF-3917 was likewise source-only).
Confidence: certain (all three defects verified line-by-line against
sys/dev/raid/mps/mps_mapping.c and cross-checked to be identical in
sys/dev/raid/mpr/mpr_mapping.c:1075-1121).
- Wrong-variable clear:
mps_mapping.c:847_mapping_clear_enc_entry(et_entry)inside theenc_entryeviction loop (loop head:826-828, eviction bookkeeping:833-844)._mapping_clear_enc_entryzeroesnum_slots,start_slot,enclosure_id,phy_bits,dpm_entry_num(:83-97) of the enclosure being added, while the evicted enclosure's entry is left with livestart_indexbut its map entries cleared β divergence on both sides. The caller assignset_entry->start_index = map_idxafterwards (:974), masking one symptom. - Off-by-one:
:829-831ownership is[start, start+num_slots)but the skip test allowsmap_idx == start+num_slotsβ one map entry past the enclosure gets_mapping_clear_map_entry()'d (:838-844) β that entry belongs to whatever enclosure follows. - Stale accumulator:
num_foundsurvives from the:783-794loop into the:809-820loop (found_space = 0reset at:808but notnum_found), sostart_idx = map_idx - num_found + 1(:815) undershoots the free run and the caller's reservation loop (:993-998) marks still-owned entriesMPS_DEV_RESERVED. - Blast radius: all indices generated here remain
< end_of_table β€ max_devices(:762-767), so no OOB inside this function; the corruptednum_slots/start_slotthen flow into_mapping_add_new_device:1165(whose missing bounds are the already-filed DF-1375) and into_mapping_commit_enc_entryβ persistence and mapping-correctness impact, Low severity on its own. - Fix:
fix.diff(4 hunks, all inside_mapping_find_enc_map_space). Compile-validated: applied to the guest/usr/srcwith the rest of the batch's mps fixes;makeinsys/dev/raid/mpswith-Werrorlinkedmps.ko(BUILD_EXIT=0;fix_build.login the DF-4085 pack)./usr/srcrestored pristine; guest reset with clean-source snapshot.
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
not_testableApplied to the guest /usr/src together with this batch's other mps fixes (DF-4085..DF-4090); make in sys/dev/raid/mps compiled all sources with -Werror and linked mps.ko (BUILD_EXIT=0). Runtime fix validation not testable: the path requires an mps(4) HBA delivering firmware data, absent on this guest.
findings/poc/DF-4088/fix.diff, findings/poc/DF-4085/fix_build.log
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (line-by-line + mpr:1075-1121 cross-check), fix.diff (4 hunks), fix_build.log in DF-4085 pack
PoC changes
n/a (untested)
Verified recommended fix
Clear enc_entry (not et_entry) at the eviction point, use >= in the overlap skip test, reset enc_entry->skip_search, and zero num_found before the post-eviction search loop.
Verdict
Low - PoC skipped per contract (hardware-gated logic class, mpr twin DF-3917 precedent). Source-certain triple defect in _mapping_find_enc_map_space: (1) :847 clears the NEW enclosure (et_entry) instead of the evicted overlapping one (enc_entry) during table defragmentation; (2) :829-831 overlap test is off by one (map_idx > start+num_slots lets the first slot PAST the enclosure be evicted/cleared); (3) :862 resets et_entry->skip_search where enc_entry's flag was set at :802, and num_found is stale (not reset at :808) so the third search loop's start_idx undershoots the free run. Net: enclosure metadata zeroed, map slots stolen from neighbor enclosures, corrupted num_slots/start_slot feed the known DF-1375 slot arithmetic. All writes stay within the tables. Fix authored; module compile-validated with the batch.
No comments yet.