β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4479

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4479 Β· 5 files
FileTypeDescriptionSize
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

fixed
baseline reproduced→ patch + rebuild →patched clean

fix.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))
↓ fix.diffper-fix-DF-4479

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.