mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
mbuf: do not restore dying interfaces
When we remove an interface it is first removed from the interface list
V_ifnet (by if_unlink_ifnet()) and marked as IFF_DYING. We then wait for
any possible references to stop being used (i.e.
epoch_wait/epoch_drain_callbacks) before we tear it fully down.
However, the index in ifindex_table is not removed, so m_rcvif_restore()
can still find the (now dying) interface.
This results in panics, for example when dummynet restores the rcvif
pointer and passes a packet to ip6_input() we can panic because the
AF_INET6 domain has already been removed (so we end up dereferencing a
NULL pointer there).
Check that the interface is not dying before we restore it, which is
equivalent to checking its presence in V_ifnet, and thus ensures that
future accesses (while in NET_EPOCH) are safe.
Reviewed by: glebius
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D34076
This commit is contained in:
parent
1c91aedf25
commit
703e533da5
1 changed files with 7 additions and 2 deletions
|
|
@ -1650,11 +1650,16 @@ m_rcvif_serialize(struct mbuf *m)
|
|||
struct ifnet *
|
||||
m_rcvif_restore(struct mbuf *m)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
M_ASSERTPKTHDR(m);
|
||||
NET_EPOCH_ASSERT();
|
||||
|
||||
return ((m->m_pkthdr.rcvif = ifnet_byindexgen(m->m_pkthdr.rcvidx,
|
||||
m->m_pkthdr.rcvgen)));
|
||||
ifp = ifnet_byindexgen(m->m_pkthdr.rcvidx, m->m_pkthdr.rcvgen);
|
||||
if (ifp == NULL || (ifp->if_flags & IFF_DYING))
|
||||
return (NULL);
|
||||
|
||||
return (m->m_pkthdr.rcvif = ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue