On Sun, Sep 04, 2016 at 05:43:20PM +0200, Martin Pieuchot wrote: > Thanks to awolk@ hacking on USB wireless we found a lot of new races in > the network stack. > > Passing and ``ifp'' pointer to a task is *not* safe. If the task > sleeps, then another thread my start executing if_detach() freeing the > memory associated to ``ifp''. And task do sleep, that's why we use > them in the first place. > > So we should always pass and ifp index like I did with the > if_input_process() task. Diff attached fix awolk@'s first panic. > > ok? >
OK claudio@ > Index: net/if.c > =================================================================== > RCS file: /cvs/src/sys/net/if.c,v > retrieving revision 1.441 > diff -u -p -r1.441 if.c > --- net/if.c 4 Sep 2016 10:32:01 -0000 1.441 > +++ net/if.c 4 Sep 2016 11:03:37 -0000 > @@ -400,6 +400,8 @@ if_map_dtor(void *null, void *m) > void > if_attachsetup(struct ifnet *ifp) > { > + unsigned long ifidx; > + > TAILQ_INIT(&ifp->if_groups); > > if_addgroup(ifp, IFG_ALL); > @@ -409,18 +411,19 @@ if_attachsetup(struct ifnet *ifp) > pfi_attach_ifnet(ifp); > #endif > > - task_set(ifp->if_watchdogtask, if_watchdog_task, ifp); > timeout_set(ifp->if_slowtimo, if_slowtimo, ifp); > if_slowtimo(ifp); > > - task_set(ifp->if_linkstatetask, if_linkstate, ifp); > - > if_idxmap_insert(ifp); > KASSERT(if_get(0) == NULL); > > + ifidx = ifp->if_index; > + > mq_init(&ifp->if_inputqueue, 8192, IPL_NET); > - task_set(ifp->if_inputtask, if_input_process, > - (void *)(unsigned long)ifp->if_index); > + task_set(ifp->if_inputtask, if_input_process, (void *)ifidx); > + task_set(ifp->if_watchdogtask, if_watchdog_task, (void *)ifidx); > + task_set(ifp->if_linkstatetask, if_linkstate, (void *)ifidx); > + > > /* Announce the interface. */ > rt_ifannouncemsg(ifp, IFAN_ARRIVAL); > @@ -1482,11 +1485,16 @@ if_up(struct ifnet *ifp) > * a link-state transition. > */ > void > -if_linkstate(void *xifp) > +if_linkstate(void *xifidx) > { > - struct ifnet *ifp = xifp; > + unsigned int ifidx = (unsigned long)xifidx; > + struct ifnet *ifp; > int s; > > + ifp = if_get(ifidx); > + if (ifp == NULL) > + return; > + > s = splsoftnet(); > rt_ifmsg(ifp); > #ifndef SMALL_KERNEL > @@ -1494,6 +1502,8 @@ if_linkstate(void *xifp) > #endif > dohooks(ifp->if_linkstatehooks, 0); > splx(s); > + > + if_put(ifp); > } > > /* > @@ -1525,15 +1535,22 @@ if_slowtimo(void *arg) > } > > void > -if_watchdog_task(void *arg) > +if_watchdog_task(void *xifidx) > { > - struct ifnet *ifp = arg; > + unsigned int ifidx = (unsigned long)xifidx; > + struct ifnet *ifp; > int s; > > + ifp = if_get(ifidx); > + if (ifp == NULL) > + return; > + > s = splnet(); > if (ifp->if_watchdog) > (*ifp->if_watchdog)(ifp); > splx(s); > + > + if_put(ifp); > } > > /* -- :wq Claudio