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)
PoC verification
Evidence pack
findings/poc/DF-3403 Β· 2 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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
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_testableConfirmed 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.
No comments yet.