Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140663823
D33263.id99451.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D33263.id99451.diff
View Options
Index: sys/dev/hyperv/netvsc/if_hn.c
===================================================================
--- sys/dev/hyperv/netvsc/if_hn.c
+++ sys/dev/hyperv/netvsc/if_hn.c
@@ -4736,11 +4736,13 @@
first = true;
for (i = 0; i < hn_vfmap_size; ++i) {
+ struct epoch_tracker et;
struct ifnet *ifp;
if (hn_vfmap[i] == NULL)
continue;
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(i);
if (ifp != NULL) {
if (first)
@@ -4749,6 +4751,7 @@
sbuf_printf(sb, " %s", ifp->if_xname);
first = false;
}
+ NET_EPOCH_EXIT(et);
}
rm_runlock(&hn_vfmap_lock, &pt);
@@ -4778,12 +4781,14 @@
first = true;
for (i = 0; i < hn_vfmap_size; ++i) {
+ struct epoch_tracker et;
struct ifnet *ifp, *hn_ifp;
hn_ifp = hn_vfmap[i];
if (hn_ifp == NULL)
continue;
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(i);
if (ifp != NULL) {
if (first) {
@@ -4795,6 +4800,7 @@
}
first = false;
}
+ NET_EPOCH_EXIT(et);
}
rm_runlock(&hn_vfmap_lock, &pt);
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -343,22 +343,22 @@
MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
struct ifnet *
-ifnet_byindex(u_short idx)
+ifnet_byindex(int idx)
{
- if (__predict_false(idx > V_if_index))
+ NET_EPOCH_ASSERT();
+
+ if (__predict_false(idx <= 0 || idx > V_if_index))
return (NULL);
return (ck_pr_load_ptr(&V_ifindex_table[idx]));
}
struct ifnet *
-ifnet_byindex_ref(u_short idx)
+ifnet_byindex_ref(int idx)
{
struct ifnet *ifp;
- NET_EPOCH_ASSERT();
-
ifp = ifnet_byindex(idx);
if (ifp == NULL || (ifp->if_flags & IFF_DYING))
return (NULL);
@@ -679,9 +679,7 @@
*/
CURVNET_SET_QUIET(ifp->if_vnet);
IFNET_WLOCK();
- KASSERT(ifp == ifnet_byindex(ifp->if_index),
- ("%s: freeing unallocated ifnet", ifp->if_xname));
-
+ MPASS(V_ifindex_table[ifp->if_index] == ifp);
ifindex_free(ifp->if_index);
IFNET_WUNLOCK();
@@ -831,9 +829,7 @@
struct sockaddr_dl *sdl;
struct ifaddr *ifa;
- if (ifp->if_index == 0 || ifp != ifnet_byindex(ifp->if_index))
- panic ("%s: BUG: if_attach called without if_alloc'd input()\n",
- ifp->if_xname);
+ MPASS(V_ifindex_table[ifp->if_index] == ifp);
#ifdef VIMAGE
ifp->if_vnet = curvnet;
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h
+++ sys/net/if_var.h
@@ -613,12 +613,12 @@
#define IFNET_RUNLOCK() sx_sunlock(&ifnet_sxlock)
/*
- * Look up an ifnet given its index; the _ref variant also acquires a
- * reference that must be freed using if_rele(). It is almost always a bug
- * to call ifnet_byindex() instead of ifnet_byindex_ref().
+ * Look up an ifnet given its index. The returned value protected from
+ * being freed by the network epoch. The _ref variant also acquires a
+ * reference that must be freed using if_rele().
*/
-struct ifnet *ifnet_byindex(u_short idx);
-struct ifnet *ifnet_byindex_ref(u_short idx);
+struct ifnet *ifnet_byindex(int);
+struct ifnet *ifnet_byindex_ref(int);
/*
* Given the index, ifaddr_byindex() returns the one and only
Index: sys/netinet/igmp.c
===================================================================
--- sys/netinet/igmp.c
+++ sys/netinet/igmp.c
@@ -482,6 +482,7 @@
static int
sysctl_igmp_ifinfo(SYSCTL_HANDLER_ARGS)
{
+ struct epoch_tracker et;
int *name;
int error;
u_int namelen;
@@ -504,14 +505,11 @@
IN_MULTI_LIST_LOCK();
IGMP_LOCK();
- if (name[0] <= 0 || name[0] > V_if_index) {
- error = ENOENT;
- goto out_locked;
- }
-
error = ENOENT;
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(name[0]);
+ NET_EPOCH_EXIT(et);
if (ifp == NULL)
goto out_locked;
Index: sys/netinet/in_mcast.c
===================================================================
--- sys/netinet/in_mcast.c
+++ sys/netinet/in_mcast.c
@@ -1376,6 +1376,7 @@
static int
inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
{
+ struct epoch_tracker et;
struct group_source_req gsr;
sockunion_t *gsa, *ssa;
struct ifnet *ifp;
@@ -1414,8 +1415,6 @@
ssa->sin.sin_addr = mreqs.imr_sourceaddr;
if (!in_nullhost(mreqs.imr_interface)) {
- struct epoch_tracker et;
-
NET_EPOCH_ENTER(et);
INADDR_TO_IFP(mreqs.imr_interface, ifp);
/* XXXGL: ifref? */
@@ -1445,10 +1444,11 @@
ssa->sin.sin_len != sizeof(struct sockaddr_in))
return (EINVAL);
- if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
- return (EADDRNOTAVAIL);
-
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(gsr.gsr_interface);
+ NET_EPOCH_EXIT(et);
+ if (ifp == NULL)
+ return (EADDRNOTAVAIL);
if (sopt->sopt_name == MCAST_BLOCK_SOURCE)
doblock = 1;
@@ -1624,6 +1624,7 @@
static int
inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
{
+ struct epoch_tracker et;
struct __msfilterreq msfr;
sockunion_t *gsa;
struct ifnet *ifp;
@@ -1649,10 +1650,9 @@
if (error)
return (error);
- if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
- return (EINVAL);
-
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(msfr.msfr_ifindex);
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifnet pointer left */
if (ifp == NULL)
return (EINVAL);
@@ -2026,11 +2026,11 @@
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
- if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
- return (EADDRNOTAVAIL);
NET_EPOCH_ENTER(et);
ifp = ifnet_byindex_ref(gsr.gsr_interface);
NET_EPOCH_EXIT(et);
+ if (ifp == NULL)
+ return (EADDRNOTAVAIL);
break;
default:
@@ -2243,6 +2243,7 @@
static int
inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
{
+ struct epoch_tracker et;
struct group_source_req gsr;
struct ip_mreq_source mreqs;
sockunion_t *gsa, *ssa;
@@ -2304,8 +2305,6 @@
* using an IPv4 address as a key is racy.
*/
if (!in_nullhost(mreqs.imr_interface)) {
- struct epoch_tracker et;
-
NET_EPOCH_ENTER(et);
INADDR_TO_IFP(mreqs.imr_interface, ifp);
/* XXXGL ifref? */
@@ -2340,11 +2339,9 @@
return (EINVAL);
}
- if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
- return (EADDRNOTAVAIL);
-
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(gsr.gsr_interface);
-
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */
if (ifp == NULL)
return (EADDRNOTAVAIL);
break;
@@ -2481,13 +2478,17 @@
if (error)
return (error);
- if (mreqn.imr_ifindex < 0 || V_if_index < mreqn.imr_ifindex)
+ if (mreqn.imr_ifindex < 0)
return (EINVAL);
if (mreqn.imr_ifindex == 0) {
ifp = NULL;
} else {
+ struct epoch_tracker et;
+
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(mreqn.imr_ifindex);
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */
if (ifp == NULL)
return (EADDRNOTAVAIL);
}
@@ -2536,6 +2537,7 @@
static int
inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
{
+ struct epoch_tracker et;
struct __msfilterreq msfr;
sockunion_t *gsa;
struct ifnet *ifp;
@@ -2566,10 +2568,9 @@
gsa->sin.sin_port = 0; /* ignore port */
- if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
- return (EADDRNOTAVAIL);
-
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(msfr.msfr_ifindex);
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */
if (ifp == NULL)
return (EADDRNOTAVAIL);
@@ -2881,13 +2882,6 @@
if (namelen != 2)
return (EINVAL);
- ifindex = name[0];
- if (ifindex <= 0 || ifindex > V_if_index) {
- CTR2(KTR_IGMPV3, "%s: ifindex %u out of range",
- __func__, ifindex);
- return (ENOENT);
- }
-
group.s_addr = name[1];
if (!IN_MULTICAST(ntohl(group.s_addr))) {
CTR2(KTR_IGMPV3, "%s: group 0x%08x is not multicast",
@@ -2895,6 +2889,7 @@
return (EINVAL);
}
+ ifindex = name[0];
NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(ifindex);
if (ifp == NULL) {
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -1100,15 +1100,16 @@
return (EINVAL);
/* Validate the interface index if specified. */
- if (pktinfo->ipi6_ifindex > V_if_index)
- return (ENXIO);
-
- ifp = NULL;
if (pktinfo->ipi6_ifindex) {
+ struct epoch_tracker et;
+
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(pktinfo->ipi6_ifindex);
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */
if (ifp == NULL)
return (ENXIO);
- }
+ } else
+ ifp = NULL;
if (ifp != NULL && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
ia.s_addr = pktinfo->ipi6_addr.s6_addr32[3];
if (in_ifhasaddr(ifp, ia) == 0)
Index: sys/netinet6/in6_mcast.c
===================================================================
--- sys/netinet6/in6_mcast.c
+++ sys/netinet6/in6_mcast.c
@@ -1402,6 +1402,7 @@
in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
{
struct group_source_req gsr;
+ struct epoch_tracker et;
sockunion_t *gsa, *ssa;
struct ifnet *ifp;
struct in6_mfilter *imf;
@@ -1439,10 +1440,16 @@
ssa->sin6.sin6_len != sizeof(struct sockaddr_in6))
return (EINVAL);
- if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
- return (EADDRNOTAVAIL);
-
+ /*
+ * XXXGL: this function should use ifnet_byindex_ref, or
+ * expand the epoch section all the way to where we put
+ * the reference.
+ */
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(gsr.gsr_interface);
+ NET_EPOCH_EXIT(et);
+ if (ifp == NULL)
+ return (EADDRNOTAVAIL);
if (sopt->sopt_name == MCAST_BLOCK_SOURCE)
doblock = 1;
@@ -1629,6 +1636,7 @@
static int
in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
{
+ struct epoch_tracker et;
struct __msfilterreq msfr;
sockunion_t *gsa;
struct ifnet *ifp;
@@ -1662,9 +1670,13 @@
if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr))
return (EINVAL);
- if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
- return (EADDRNOTAVAIL);
+ /*
+ * XXXGL: this function should use ifnet_byindex_ref, or expand the
+ * epoch section all the way to where the interface is referenced.
+ */
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(msfr.msfr_ifindex);
+ NET_EPOCH_EXIT(et);
if (ifp == NULL)
return (EADDRNOTAVAIL);
(void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
@@ -1858,12 +1870,16 @@
*
* FIXME: The KAME use of the unspecified address (::)
* to join *all* multicast groups is currently unsupported.
+ *
+ * XXXGL: this function multiple times uses ifnet_byindex() without
+ * proper protection - staying in epoch, or putting reference on ifnet.
*/
static int
in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
{
struct in6_multi_head inmh;
struct group_source_req gsr;
+ struct epoch_tracker et;
sockunion_t *gsa, *ssa;
struct ifnet *ifp;
struct in6_mfilter *imf;
@@ -1905,9 +1921,11 @@
if (mreq.ipv6mr_interface == 0) {
ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6);
} else {
- if (V_if_index < mreq.ipv6mr_interface)
- return (EADDRNOTAVAIL);
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(mreq.ipv6mr_interface);
+ NET_EPOCH_EXIT(et);
+ if (ifp == NULL)
+ return (EADDRNOTAVAIL);
}
CTR3(KTR_MLD, "%s: ipv6mr_interface = %d, ifp = %p",
__func__, mreq.ipv6mr_interface, ifp);
@@ -1946,10 +1964,11 @@
ssa->sin6.sin6_port = 0;
ssa->sin6.sin6_scope_id = 0;
}
-
- if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
- return (EADDRNOTAVAIL);
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(gsr.gsr_interface);
+ NET_EPOCH_EXIT(et);
+ if (ifp == NULL)
+ return (EADDRNOTAVAIL);
break;
default:
@@ -2168,6 +2187,7 @@
{
struct ipv6_mreq mreq;
struct group_source_req gsr;
+ struct epoch_tracker et;
sockunion_t *gsa, *ssa;
struct ifnet *ifp;
struct in6_mfilter *imf;
@@ -2266,9 +2286,9 @@
* XXX SCOPE6 lock potentially taken here.
*/
if (ifindex != 0) {
- if (V_if_index < ifindex)
- return (EADDRNOTAVAIL);
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(ifindex);
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */
if (ifp == NULL)
return (EADDRNOTAVAIL);
(void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
@@ -2293,7 +2313,9 @@
ip6_sprintf(ip6tbuf, &gsa->sin6.sin6_addr));
ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6);
} else {
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(ifindex);
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */
}
if (ifp == NULL)
return (EADDRNOTAVAIL);
@@ -2410,6 +2432,7 @@
static int
in6p_set_multicast_if(struct inpcb *inp, struct sockopt *sopt)
{
+ struct epoch_tracker et;
struct ifnet *ifp;
struct ip6_moptions *imo;
u_int ifindex;
@@ -2421,19 +2444,19 @@
error = sooptcopyin(sopt, &ifindex, sizeof(u_int), sizeof(u_int));
if (error)
return (error);
- if (V_if_index < ifindex)
- return (EINVAL);
+ NET_EPOCH_ENTER(et);
if (ifindex == 0)
ifp = NULL;
else {
ifp = ifnet_byindex(ifindex);
- if (ifp == NULL)
- return (EINVAL);
- if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
+ NET_EPOCH_EXIT(et);
return (EADDRNOTAVAIL);
+ }
}
imo = in6p_findmoptions(inp);
- imo->im6o_multicast_ifp = ifp;
+ imo->im6o_multicast_ifp = ifp; /* XXXGL: reference?! */
+ NET_EPOCH_EXIT(et);
INP_WUNLOCK(inp);
return (0);
@@ -2442,12 +2465,13 @@
/*
* Atomically set source filters on a socket for an IPv6 multicast group.
*
- * SMPng: NOTE: Potentially calls malloc(M_WAITOK) with Giant held.
+ * XXXGL: unsafely exits epoch with ifnet pointer
*/
static int
in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
{
struct __msfilterreq msfr;
+ struct epoch_tracker et;
sockunion_t *gsa;
struct ifnet *ifp;
struct in6_mfilter *imf;
@@ -2477,9 +2501,9 @@
gsa->sin6.sin6_port = 0; /* ignore port */
- if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex)
- return (EADDRNOTAVAIL);
+ NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(msfr.msfr_ifindex);
+ NET_EPOCH_EXIT(et);
if (ifp == NULL)
return (EADDRNOTAVAIL);
(void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
@@ -2758,13 +2782,6 @@
if (namelen != 5)
return (EINVAL);
- ifindex = name[0];
- if (ifindex <= 0 || ifindex > V_if_index) {
- CTR2(KTR_MLD, "%s: ifindex %u out of range",
- __func__, ifindex);
- return (ENOENT);
- }
-
memcpy(&mcaddr, &name[1], sizeof(struct in6_addr));
if (!IN6_IS_ADDR_MULTICAST(&mcaddr)) {
CTR2(KTR_MLD, "%s: group %s is not multicast",
@@ -2772,6 +2789,7 @@
return (EINVAL);
}
+ ifindex = name[0];
NET_EPOCH_ENTER(et);
ifp = ifnet_byindex(ifindex);
if (ifp == NULL) {
Index: sys/netinet6/ip6_mroute.c
===================================================================
--- sys/netinet6/ip6_mroute.c
+++ sys/netinet6/ip6_mroute.c
@@ -677,6 +677,7 @@
static int
add_m6if(struct mif6ctl *mifcp)
{
+ struct epoch_tracker et;
struct mif6 *mifp;
struct ifnet *ifp;
int error;
@@ -692,12 +693,14 @@
MIF6_UNLOCK();
return (EADDRINUSE); /* XXX: is it appropriate? */
}
- if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) {
+
+ NET_EPOCH_ENTER(et);
+ if ((ifp = ifnet_byindex(mifcp->mif6c_pifi)) == NULL) {
+ NET_EPOCH_EXIT(et);
MIF6_UNLOCK();
return (ENXIO);
}
-
- ifp = ifnet_byindex(mifcp->mif6c_pifi);
+ NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */
if (mifcp->mif6c_flags & MIFF_REGISTER) {
if (reg_mif_num == (mifi_t)-1) {
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -2819,8 +2819,8 @@
return (EINVAL);
/*
- * ip6_setpktopt can call ifnet_by_index(), so it's imperative that we are
- * in the net epoch here.
+ * ip6_setpktopt can call ifnet_byindex(), so it's imperative that we
+ * are in the network epoch here.
*/
NET_EPOCH_ASSERT();
@@ -2959,8 +2959,6 @@
if (IN6_IS_ADDR_MULTICAST(&pktinfo->ipi6_addr))
return (EINVAL);
/* validate the interface index if specified. */
- if (pktinfo->ipi6_ifindex > V_if_index)
- return (ENXIO);
if (pktinfo->ipi6_ifindex) {
ifp = ifnet_byindex(pktinfo->ipi6_ifindex);
if (ifp == NULL)
Index: sys/netinet6/mld6.c
===================================================================
--- sys/netinet6/mld6.c
+++ sys/netinet6/mld6.c
@@ -363,6 +363,7 @@
static int
sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS)
{
+ struct epoch_tracker et;
int *name;
int error;
u_int namelen;
@@ -385,14 +386,9 @@
IN6_MULTI_LOCK();
IN6_MULTI_LIST_LOCK();
MLD_LOCK();
-
- if (name[0] <= 0 || name[0] > V_if_index) {
- error = ENOENT;
- goto out_locked;
- }
+ NET_EPOCH_ENTER(et);
error = ENOENT;
-
ifp = ifnet_byindex(name[0]);
if (ifp == NULL)
goto out_locked;
@@ -415,6 +411,7 @@
}
out_locked:
+ NET_EPOCH_EXIT(et);
MLD_UNLOCK();
IN6_MULTI_LIST_UNLOCK();
IN6_MULTI_UNLOCK();
Index: sys/netinet6/nd6_rtr.c
===================================================================
--- sys/netinet6/nd6_rtr.c
+++ sys/netinet6/nd6_rtr.c
@@ -2425,18 +2425,21 @@
int
nd6_setdefaultiface(int ifindex)
{
- int error = 0;
-
- if (ifindex < 0 || V_if_index < ifindex)
- return (EINVAL);
- if (ifindex != 0 && !ifnet_byindex(ifindex))
- return (EINVAL);
if (V_nd6_defifindex != ifindex) {
V_nd6_defifindex = ifindex;
- if (V_nd6_defifindex > 0)
+ if (V_nd6_defifindex != 0) {
+ struct epoch_tracker et;
+
+ /*
+ * XXXGL: this function should use ifnet_byindex_ref!
+ */
+ NET_EPOCH_ENTER(et);
V_nd6_defifp = ifnet_byindex(V_nd6_defifindex);
- else
+ NET_EPOCH_EXIT(et);
+ if (V_nd6_defifp == NULL)
+ return (EINVAL);
+ } else
V_nd6_defifp = NULL;
/*
@@ -2447,7 +2450,7 @@
scope6_setdefault(V_nd6_defifp);
}
- return (error);
+ return (0);
}
bool
Index: sys/netinet6/scope6.c
===================================================================
--- sys/netinet6/scope6.c
+++ sys/netinet6/scope6.c
@@ -177,16 +177,22 @@
return (EINVAL);
}
- if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
- idlist->s6id_list[i] > V_if_index) {
- /*
- * XXX: theoretically, there should be no
- * relationship between link IDs and interface
- * IDs, but we check the consistency for
- * safety in later use.
- */
- IF_AFDATA_WUNLOCK(ifp);
- return (EINVAL);
+ if (i == IPV6_ADDR_SCOPE_LINKLOCAL) {
+ struct epoch_tracker et;
+
+ NET_EPOCH_ENTER(et);
+ if (!ifnet_byindex(idlist->s6id_list[i])) {
+ /*
+ * XXX: theoretically, there should be
+ * no relationship between link IDs and
+ * interface IDs, but we check the
+ * consistency for safety in later use.
+ */
+ NET_EPOCH_EXIT(et);
+ IF_AFDATA_WUNLOCK(ifp);
+ return (EINVAL);
+ }
+ NET_EPOCH_EXIT(et);
}
/*
@@ -325,14 +331,20 @@
if (zoneid != 0 &&
(IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr))) {
+ struct epoch_tracker et;
+
/*
* At this moment, we only check interface-local and
* link-local scope IDs, and use interface indices as the
* zone IDs assuming a one-to-one mapping between interfaces
* and links.
*/
- if (V_if_index < zoneid || ifnet_byindex(zoneid) == NULL)
+ NET_EPOCH_ENTER(et);
+ if (ifnet_byindex(zoneid) == NULL) {
+ NET_EPOCH_EXIT(et);
return (ENXIO);
+ }
+ NET_EPOCH_EXIT(et);
/* XXX assignment to 16bit from 32bit variable */
sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff);
@@ -358,14 +370,15 @@
*/
zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
if (zoneid) {
+ struct epoch_tracker et;
+
+ NET_EPOCH_ENTER(et);
/* sanity check */
- if (V_if_index < zoneid)
- return (ENXIO);
-#if 0
- /* XXX: Disabled due to possible deadlock. */
- if (!ifnet_byindex(zoneid))
+ if (!ifnet_byindex(zoneid)) {
+ NET_EPOCH_EXIT(et);
return (ENXIO);
-#endif
+ }
+ NET_EPOCH_EXIT(et);
if (sin6->sin6_scope_id != 0 &&
zoneid != sin6->sin6_scope_id) {
log(LOG_NOTICE,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 27, 2:39 PM (6 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27306937
Default Alt Text
D33263.id99451.diff (19 KB)
Attached To
Mode
D33263: ifnet_byindex() actually requires network epoch
Attached
Detach File
Event Timeline
Log In to Comment