net: Enter a net epoch around protocol if_up/down notifications

When traversing a list of interface addresses, we need to be in a net
epoch section, and protocol ctlinput routines need a stable reference to
the address.

Reported by:	syzbot+3219af764ead146a3a4e@syzkaller.appspotmail.com
Reviewed by:	kp, melifaro
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D31889
This commit is contained in:
Mark Johnston 2021-09-10 09:07:40 -04:00
parent 7955efd574
commit b1e6a792d6
2 changed files with 8 additions and 0 deletions

View File

@ -516,6 +516,8 @@ pfctlinput(int cmd, struct sockaddr *sa)
struct domain *dp;
struct protosw *pr;
NET_EPOCH_ASSERT();
for (dp = domains; dp; dp = dp->dom_next)
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_ctlinput)

View File

@ -2195,14 +2195,17 @@ static void
if_unroute(struct ifnet *ifp, int flag, int fam)
{
struct ifaddr *ifa;
struct epoch_tracker et;
KASSERT(flag == IFF_UP, ("if_unroute: flag != IFF_UP"));
ifp->if_flags &= ~flag;
getmicrotime(&ifp->if_lastchange);
NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
NET_EPOCH_EXIT(et);
ifp->if_qflush(ifp);
if (ifp->if_carp)
@ -2218,14 +2221,17 @@ static void
if_route(struct ifnet *ifp, int flag, int fam)
{
struct ifaddr *ifa;
struct epoch_tracker et;
KASSERT(flag == IFF_UP, ("if_route: flag != IFF_UP"));
ifp->if_flags |= flag;
getmicrotime(&ifp->if_lastchange);
NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
pfctlinput(PRC_IFUP, ifa->ifa_addr);
NET_EPOCH_EXIT(et);
if (ifp->if_carp)
(*carp_linkstate_p)(ifp);
rt_ifmsg(ifp);