setstate(object_initialized) reports EBUSY 'Can't set state' for transitions it performed: 1046 compares against sd_initializing (the source state) instead of the requested/actual result
Summary
After set_sd_state succeeds and forceup promotes the SD to sd_up inside the same ioctl, setstate checks sd->state != sd_initializing - the state it came FROM - unsatisfiable on success, so the ioctl always answers EBUSY while dmesg shows the transition succeeded. Demonstrated deterministically (reply.error=16 with actual state 13). Recovery automation cannot distinguish success from refusal. Mirror-image dead code at :250 documented. Judge-by-result fix, validated.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4479 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| vinum_setstate_logic.c | poc | setstate + VINUM_SDCONFIG readback | 5.4 KB | view raw |
| run.log | run-log | baseline output | 1.0 KB | view raw |
| fix.diff | suggested-fix | use transition result | 719 B | view raw |
| fix_run.log | run-log | patched output | 803 B | view raw |
| env.txt | env | guest/kernel info | 314 B | view raw |
Fix verification
fixedfix.diff switches the check to the transition result; patched kernel reports error=0 with the sd actually in sd_initialized (readback state=6).
fix_run.log (reply.error=0 ... state=6(sd_initialized))
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log (baseline: reply.error=16 + 'Can't set state' with actual state transitions logged); fix_run.log (patched: reply.error=0, state=6 sd_initialized)
PoC changes
authored fresh; VINUM_SDCONFIG ioctl number brute-forced to size 208 (struct sd on amd64) and state parsed at offset 64; enum order confirmed from vinumstate.h (unallocated,uninit,referenced,init,empty,initializing,initialized,obsolete,stale,crashed,down,reviving,reborn,up)
Verified recommended fix
Judge success by the set_sd_state return value instead of comparing sd->state against the source state (see fix.diff)
Verdict
Deterministic logic bug: VINUM_SETSTATE(object_initialized, sd) reports EBUSY 'Can't set state' for transitions the kernel actually performs, because vinumstate.c:1046 compares sd->state against sd_initializing (the state it came FROM) after requesting sd_initialized. Demonstrated with state readback (VINUM_SDCONFIG): reply.error=16 while dmesg shows 's0 is initialized by force' and the readback state is sd_up (update_plex_state->forceup promoted it within the same ioctl). Impact ceiling is administrative-tooling confusion and masked recovery automation, not memory safety; classed Low.
No comments yet.