From ef2e580e561a89579acefc3b83fc905425ffbd9e Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Sun, 13 Oct 2019 04:25:16 +0000 Subject: [PATCH] Don't cover in6_ifattach() with network epoch, as it may call into network drivers ioctls, that may sleep. PR: 241223 --- sys/netinet6/in6.c | 2 +- sys/netinet6/in6_ifattach.c | 14 +++++++++++--- sys/netinet6/nd6.c | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index c92ee171b78..256d5a0c34c 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1930,12 +1930,12 @@ in6_if_up(struct ifnet *ifp) arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz)); } } + NET_EPOCH_EXIT(et); /* * special cases, like 6to4, are handled in in6_ifattach */ in6_ifattach(ifp, NULL); - NET_EPOCH_EXIT(et); } int diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index fd46f4494a4..91ef544d8b2 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -423,6 +423,7 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) struct in6_ifaddr *ia; struct in6_aliasreq ifra; struct nd_prefixctl pr0; + struct epoch_tracker et; struct nd_prefix *pr; int error; @@ -437,7 +438,10 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); } else { - if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) { + NET_EPOCH_ENTER(et); + error = get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr); + NET_EPOCH_EXIT(et); + if (error != 0) { nd6log((LOG_ERR, "%s: no ifid available\n", if_name(ifp))); return (-1); @@ -472,7 +476,9 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) return (-1); } + NET_EPOCH_ENTER(et); ia = in6ifa_ifpforlinklocal(ifp, 0); + NET_EPOCH_EXIT(et); if (ia == NULL) { /* * Another thread removed the address that we just added. @@ -667,8 +673,6 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) { struct in6_ifaddr *ia; - NET_EPOCH_ASSERT(); - if (ifp->if_afdata[AF_INET6] == NULL) return; /* @@ -718,7 +722,11 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) */ if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) { + struct epoch_tracker et; + + NET_EPOCH_ENTER(et); ia = in6ifa_ifpforlinklocal(ifp, 0); + NET_EPOCH_EXIT(et); if (ia == NULL) in6_ifattach_linklocal(ifp, altifp); else diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index fae88877a2f..4d13d5b74ca 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1691,7 +1691,6 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) struct ifaddr *ifa; struct in6_ifaddr *ia; - NET_EPOCH_ENTER(et); if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && !(ND.flags & ND6_IFF_IFDISABLED)) { /* ifdisabled 1->0 transision */ @@ -1702,6 +1701,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) * do not clear ND6_IFF_IFDISABLED. * See RFC 4862, Section 5.4.5. */ + NET_EPOCH_ENTER(et); CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; @@ -1710,6 +1710,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) break; } + NET_EPOCH_EXIT(et); if (ifa != NULL) { /* LLA is duplicated. */ @@ -1730,6 +1731,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED; if (V_ip6_dad_count > 0 && (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0) { + NET_EPOCH_ENTER(et); CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != @@ -1738,6 +1740,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) ia = (struct in6_ifaddr *)ifa; ia->ia6_flags |= IN6_IFF_TENTATIVE; } + NET_EPOCH_EXIT(et); } } @@ -1756,6 +1759,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) * address is assigned, and IFF_UP, try to * assign one. */ + NET_EPOCH_ENTER(et); CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != @@ -1765,13 +1769,13 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) break; } + NET_EPOCH_EXIT(et); if (ifa != NULL) /* No LLA is configured. */ in6_ifattach(ifp, NULL); } } ND_IFINFO(ifp)->flags = ND.flags; - NET_EPOCH_EXIT(et); break; } #undef ND