# DF-2762 - Verification Verdict

**Status:** reproduced
**Impact:** none (hardening)
**Confidence:** certain

## Mechanism
sys_setgroups calls cratom_proc(p) FIRST - which publishes the fresh COW credential to the process - and only THEN copyins the new group list into that live credential. During the copyin window other threads observe a credential with the OLD count but progressively NEW group bytes; a faulting copyin returns an error while the published credential has already been (partially) mutated.

## Verdict
REPRODUCED as root on the stock guest: a mutator thread alternating setgroups(setA)/setgroups(setB) plus an observer thread produced 115 observations of MIXED group sets out of 6.9M getgroups reads (samples: {1000,1001,1002,1003,5004,5005,5006,5007} - old prefix, new suffix), proving the credential is exposed mid-mutation exactly as claimed. The EFAULT variant (copyin straddling a guard page) returned EFAULT without an observable partial mutation in this run - DFly copyin for the 32-byte window completed or faulted before publication became visible to the same thread, so that sub-claim stays code-certain; the mixed-set window itself is runtime-proven.

## Threat / reachability
Root-gated credential-consistency race: authorization checks (group_member) running concurrently with setgroups can evaluate against a mixed old/new group set.

## Privilege escalation assessment
n/a (self-inflicted window; setgroups is root-gated)

## Fix
copyin into a stack staging buffer BEFORE cratom, then memcpy+publish under the exclusive window.

## Kernel references
- `sys/kern/kern_prot.c:682`
- `sys/kern/kern_prot.c:689`
- `sys/kern/kern_prot.c:692`

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

Note: an earlier draft of this fix.diff failed the first combined build (see _batch41/README.md); the shipped diff is the corrected, compile-clean version.
