# DF-2467 verdict -- TOCTOU in i_create_session: slot published outside the lock

status: reproduced   reproduced: 1   impact: corruption
confidence: certain   attempts: 2   runtime_sec: 900

The verbatim i_create_session (iscsi.c:609-656) searches the lowest unused session slot under sc->lock but executes sc->sessions[n] = sp at :639 AFTER lockmgr(LK_RELEASE) at :635. A deterministic in-window interleave (thread A parked by the interposed lockmgr_release right after the unlock - semantically identical to preemption at that instruction) let a second ISCSISETSES caller run to completion: both were handed sid=0, make_dev(iscsi unit=0) was called twice, sessions[] ended with 1 reachable entry while the TAILQ and nsess counted 2 - the overwritten session is orphaned/leaked with a duplicate dev minor, and a make_dev failure on the duplicate leaves sp->dev NULL for the ism_stop destroy_dev arm. Root-only (control node 0600 root:wheel, iscsi.c:762). Fix (publish the slot under the lock) validated A/B on the same rig: B gets sid=1, sessions[]/TAILQ/nsess consistent.

## Evidence (decisive lines)
DF2467[stalled-race]: sessions[] used=1 TAILQ entries=2 nsess=2 dup_minors=1
DF2467: sessions[0] = sp sid=0 OCCUPIED
DF2467: sessions on TAILQ but unreachable via sessions[] (orphaned/leaked): 1
DF2467[stalled-race]: RESULT=RACE OBSERVED (duplicate slot/minor, inconsistent sessions[]/isc_sess/nsess bookkeeping)
log: make_dev(iscsi%d unit=0) make_dev(iscsi%d unit=0)
DF2467: A was told sid=0, B was told sid=0 (SAME SLOT handed to both)
--- fixed source A/B ---
DF2467[stalled-race]: sessions[] used=2 TAILQ entries=2 nsess=2 dup_minors=0
DF2467[stalled-race]: RESULT=clean (slot assignment serialized with the search)
DF2467: A was told sid=0, B was told sid=1




## Exploit chain / privesc assessment
steps: root ioctl ISCSISETSES x2 racing - deterministic interleave on verbatim function; impact is bookkeeping corruption, orphaned sessions and duplicate minors; privesc ceiling: none beyond the filed root-only confusion/leak (no unpriv path - /dev/iscsi is 0600).

## Fix + A/B
fix.diff moves the slot publish under the lock; A/B on the same rig shows distinct sids and consistent bookkeeping.


## 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.
