diff options
author | Mark Johnston <markj@FreeBSD.org> | 2021-09-10 13:07:40 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2021-09-10 13:07:40 +0000 |
commit | b1e6a792d68e9c59740d5e925405d8d4343d099b (patch) | |
tree | 247ecc7fe63c747833aaefa3b2c0b0bf244bee68 /sys/net | |
parent | 7955efd574b98601a95da45d6d8e7f452631fddd (diff) | |
download | src-b1e6a792d68e9c59740d5e925405d8d4343d099b.tar.gz src-b1e6a792d68e9c59740d5e925405d8d4343d099b.zip |
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
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 8d2a66471836..83a0b07805ee 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -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); |