# 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

1. **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 its
   `num_slots`, `enclosure_id`, `phy_bits`, `dpm_entry_num` (= BAD). The
   caller (`_mapping_get_dev_info:972-998`) then reserves `num_slots` (=0)
   entries and stores the found `start_index` into the half-wiped entry, so
   every later `_mapping_add_new_device:1165` slot computation
   (`start_index + slot - start_slot`, with `start_slot` also zeroed) and the
   DPM commit path operate on corrupted enclosure state.

2. **Off-by-one overlap test** (`:829-831`): an enclosure owns map-table
   slots `[start_index, start_index + num_slots)`; the skip test
   `map_idx > (enc_entry->start_index + enc_entry->num_slots)` treats
   `map_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`).

3. **Stale accumulator** (`:783-820`): `num_found` is not reset before the
   third (post-eviction) search loop at `:809`; it retains the tail count of
   the second loop, so `start_idx = (map_idx - num_found) + 1` (`:815`) can
   point *before* the actually-contiguous free run — entries still owned by
   other enclosures get marked `MPS_DEV_RESERVED` by 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).
