infiniband: Widen NET_EPOCH coverage
From static code analysis, some device drivers (cxgbe, mlx4, mthca, and qlnx) do not enter net epoch before lagg_input_infiniband(). If IPoIB interface is a member of lagg(4) interface, and after returning from lagg_input_infiniband() the receiving interface of mbuf is set to lagg(4) interface, then when concurrently destroying the lagg(4) interface, there is a small window that the interface gets destroyed and becomes invalid before infiniband_input() re-enter net epoch, thus leading use-after-free. Widen NET_EPOCH coverage to prevent use-after-free. Thanks hselasky@ for testing with mlx5 devices. Reviewed by: hselasky Tested by: hselasky MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D39275
This commit is contained in:
@@ -417,6 +417,7 @@ infiniband_input(struct ifnet *ifp, struct mbuf *m)
|
|||||||
int isr;
|
int isr;
|
||||||
|
|
||||||
CURVNET_SET_QUIET(ifp->if_vnet);
|
CURVNET_SET_QUIET(ifp->if_vnet);
|
||||||
|
NET_EPOCH_ENTER(et);
|
||||||
|
|
||||||
if ((ifp->if_flags & IFF_UP) == 0) {
|
if ((ifp->if_flags & IFF_UP) == 0) {
|
||||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||||
@@ -504,10 +505,9 @@ infiniband_input(struct ifnet *ifp, struct mbuf *m)
|
|||||||
mac_ifnet_create_mbuf(ifp, m);
|
mac_ifnet_create_mbuf(ifp, m);
|
||||||
#endif
|
#endif
|
||||||
/* Allow monitor mode to claim this frame, after stats are updated. */
|
/* Allow monitor mode to claim this frame, after stats are updated. */
|
||||||
NET_EPOCH_ENTER(et);
|
|
||||||
netisr_dispatch(isr, m);
|
netisr_dispatch(isr, m);
|
||||||
NET_EPOCH_EXIT(et);
|
|
||||||
done:
|
done:
|
||||||
|
NET_EPOCH_EXIT(et);
|
||||||
CURVNET_RESTORE();
|
CURVNET_RESTORE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-4
@@ -2192,16 +2192,14 @@ lagg_input_ethernet(struct ifnet *ifp, struct mbuf *m)
|
|||||||
static struct mbuf *
|
static struct mbuf *
|
||||||
lagg_input_infiniband(struct ifnet *ifp, struct mbuf *m)
|
lagg_input_infiniband(struct ifnet *ifp, struct mbuf *m)
|
||||||
{
|
{
|
||||||
struct epoch_tracker et;
|
|
||||||
struct lagg_port *lp = ifp->if_lagg;
|
struct lagg_port *lp = ifp->if_lagg;
|
||||||
struct lagg_softc *sc = lp->lp_softc;
|
struct lagg_softc *sc = lp->lp_softc;
|
||||||
struct ifnet *scifp = sc->sc_ifp;
|
struct ifnet *scifp = sc->sc_ifp;
|
||||||
|
|
||||||
NET_EPOCH_ENTER(et);
|
NET_EPOCH_ASSERT();
|
||||||
if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
|
if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
|
||||||
lp->lp_detaching != 0 ||
|
lp->lp_detaching != 0 ||
|
||||||
sc->sc_proto == LAGG_PROTO_NONE) {
|
sc->sc_proto == LAGG_PROTO_NONE) {
|
||||||
NET_EPOCH_EXIT(et);
|
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@@ -2214,7 +2212,6 @@ lagg_input_infiniband(struct ifnet *ifp, struct mbuf *m)
|
|||||||
m = NULL;
|
m = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NET_EPOCH_EXIT(et);
|
|
||||||
return (m);
|
return (m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user