git: 703e533da5e2 - main - mbuf: do not restore dying interfaces
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 28 Jan 2022 23:09:38 UTC
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=703e533da5e2e4743d38bbf4605fec041bc69976 commit 703e533da5e2e4743d38bbf4605fec041bc69976 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2022-01-27 21:01:09 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2022-01-28 22:09:08 +0000 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 --- sys/kern/kern_mbuf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index 5c69f663c0e2..23050e991418 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -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(); + + 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 = ifnet_byindexgen(m->m_pkthdr.rcvidx, - m->m_pkthdr.rcvgen))); + return (m->m_pkthdr.rcvif = ifp); } /*