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

slstart dereferences tp->t_slsc and the softc before acquiring any token (races slclose/SLIOCSUNIT)

Summary

slstart reads tp->t_slsc and dereferences sc->sc_if.if_snd BEFORE lwkt_gettoken(&tp->t_token). slclose NULLs tp->t_slsc and SLIOCSUNIT swaps softc contents under tty_token+t_token, so an SMP race with tty close yields a NULL-deref or a softc mid-swap (garbage ifq) -> panic. Distinct site from DF-0576 (callout handlers reading sc_ttyp pre-token); this is the TX entry. LEGACY bucket; not reproduced. Fix: derive sc/ifsq after acquiring t_token, bail if NULL.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3403 Β· 2 files
FileTypeDescriptionSize
README.md β€” 1.6 KB ↓ raw
verdict.json β€” 1.3 KB view raw

DF-3403 β€” if_sl: slstart dereferences tp->t_slsc (and the softc) before taking any token

What

sys/net/sl/if_sl.c:529-532:

slstart(struct tty *tp)
{
        struct sl_softc *sc = (struct sl_softc *)tp->t_slsc;
        struct ifaltq_subque *ifsq = ifq_get_subq_default(&sc->sc_if.if_snd);
        ...
        lwkt_gettoken(&tp->t_token);        /* :539 β€” too late */

tp->t_slsc is read and sc is dereferenced before t_token (or tty_token) is acquired. slclose (:302-338) nulls tp->t_slsc (:326) and sc->sc_ttyp (:325) under tty_token+t_token, and sltioctl's SLIOCSUNIT swaps softc contents under the same tokens (:359-392). A slstart invocation racing the close on another CPU reads t_slsc == NULL (NULL deref at &sc->sc_if.if_snd β†’ immediate panic) or a softc mid-swap (garbage ifq pointer β†’ wild deref).

Downstream, :546 (*tp->t_oproc)(tp) and the sc == NULL check at :560 (after the token) partially paper over this, but the :531-532 prologue is outside any protection. Distinct from DF-0576, which covers the callout handlers (sl_keepalive:1016, sl_outfill:1043) reading sc->sc_ttyp before the token β€” this is the main TX entry reading t_slsc/softc before the token.

Impact

Root must have configured SLIP; the race window is the close/detach of the tty versus a driver-driven l_start call. PANIC (NULL/wild dereference) on SMP. Low / likely. LEGACY bucket. Phase V skipped (legacy race, per batch instructions).

Fix

Move the sc/ifsq derivation below lwkt_gettoken(&tp->t_token) and bail out if sc == NULL before touching sc->sc_if.

Fix verification

not_testable
per-fix-DF-3403

Confirmed kernel references

Detail

Evidence (decisive lines)

['findings/poc/DF-3403/README.md']

PoC changes

n/a (Phase V skipped for this Low finding per batch contract)

Verified recommended fix

Derive sc/ifsq after acquiring t_token and bail if sc == NULL

Verdict

slstart (if_sl.c:531-532) reads tp->t_slsc and dereferences sc->sc_if.if_snd to derive ifsq BEFORE lwkt_gettoken(&tp->t_token) at :539. slclose nulls tp->t_slsc (:326) and sltioctl SLIOCSUNIT swaps softc contents (:359-392) under tty_token+t_token, so an SMP race with tty close/detach yields NULL-deref (sc==NULL -> &sc->sc_if) or a softc mid-swap (garbage ifq) -> panic. Distinct site from DF-0576 (callout handlers reading sc_ttyp pre-token); this is the TX entry reading t_slsc pre-token. LEGACY bucket, root-gated setup, tiny window; Phase V skipped.