# DF-4084 — sis_stop() uses non-blocking callout_stop while sis_tick re-arms:
# timer resurrects after stop; on detach, sis_tick runs against freed
# softc/miibus/resources (use-after-free) — DF-3715 callout-discipline family

File: sys/dev/netif/sis/if_sis.c (pass 2 — first pass over this file)
Class: callout/lifetime race (privileged detach → UAF)

## Root cause (path:line)

- if_sis.c:1123: `callout_init(&sc->sis_timer);` (plain init)
- if_sis.c:1477-1500: sis_tick callback:
  - 1484 `lwkt_serialize_enter(ifp->if_serializer);` … work …
  - 1498 `callout_reset(&sc->sis_timer, hz, sis_tick, sc);` … 1499 exit.
- if_sis.c:2033: sis_stop(): `callout_stop(&sc->sis_timer);`
- sys/kern/kern_timeout.c:1086-1088 (API contract):
  "callout_stop … does not interlock against a callout that is in-progress."

Sequence: sis_tick fires on CPU1 and blocks acquiring if_serializer, which a
thread doing sis_stop (ifconfig down via sis_ioctl:1974-1980, watchdog via
sis_watchdog:2013, or sis_detach:1203-1208) holds. callout_stop returns
without stopping the in-progress callback. The stopper releases the
serializer; sis_tick then completes and — at line 1498 — callout_reset
re-arms the timer *after stop*. The callout is resurrected.

Consequences:

1. ifconfig down / sis_init cycle: timer keeps ticking against a stopped
   chip (mii_tick on a halted PHY) — incorrect but mostly benign.
2. **sis_detach (devctl detach / kldunload if_sis)**: after sis_stop, detach
   tears down bus_teardown_intr (1207), ether_ifdetach (1210),
   device_delete_child(miibus) (1213), releases sis_irq/sis_res (1216-1219)
   and sis_dma_free (1221); the softc is freed when the driver detaches.
   The resurrected/late sis_tick then executes: enters the freed ifnet's
   serializer, `device_get_softc(sc->sis_miibus)` on the deleted child,
   CSR reads on released resources → use-after-free → panic or worse.

Contrast with the correct pattern used by oce in the same commit family:
`callout_terminate(&sc->timer)` (sys/dev/netif/oce/oce_if.c:331), which
cancels and waits.

## Fix

In sis_stop (or sis_detach, before releasing resources):

	callout_terminate(&sc->sis_timer);   /* instead of callout_stop */

(callout_terminate, kern_timeout.c:1104-1121, synchronously cancels and
prevents resurrection.)

## Verification status

UNTESTED — hardware-gated: the sis_tick path needs the SiS/DP83815 NIC
(mii_tick on sc->sis_miibus); QEMU has no model (guest pciconf shows no
0x1039/0x100b devices). The callout_stop contract violation is source-certain.
