Enforce net epoch in in6_selectsrc().
in6_selectsrc() may call fib6_lookup() in some cases, which requires epoch. Wrap in6_selectsrc* calls into epoch inside its users. Mark it as requiring epoch by adding NET_EPOCH_ASSERT(). MFC after: 1 weeek Differential Revision: https://reviews.freebsd.org/D28647
This commit is contained in:
@@ -1006,15 +1006,18 @@ nfscl_getmyip(struct nfsmount *nmp, struct in6_addr *paddr, int *isinet6p)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
if (nmp->nm_nam->sa_family == AF_INET6) {
|
if (nmp->nm_nam->sa_family == AF_INET6) {
|
||||||
|
struct epoch_tracker et;
|
||||||
struct sockaddr_in6 *sin6;
|
struct sockaddr_in6 *sin6;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sin6 = (struct sockaddr_in6 *)nmp->nm_nam;
|
sin6 = (struct sockaddr_in6 *)nmp->nm_nam;
|
||||||
|
|
||||||
|
NET_EPOCH_ENTER(et);
|
||||||
CURVNET_SET(CRED_TO_VNET(nmp->nm_sockreq.nr_cred));
|
CURVNET_SET(CRED_TO_VNET(nmp->nm_sockreq.nr_cred));
|
||||||
error = in6_selectsrc_addr(fibnum, &sin6->sin6_addr,
|
error = in6_selectsrc_addr(fibnum, &sin6->sin6_addr,
|
||||||
sin6->sin6_scope_id, NULL, paddr, NULL);
|
sin6->sin6_scope_id, NULL, paddr, NULL);
|
||||||
CURVNET_RESTORE();
|
CURVNET_RESTORE();
|
||||||
|
NET_EPOCH_EXIT(et);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
|
|||||||
{
|
{
|
||||||
struct ip6_hdr *oip6, *nip6;
|
struct ip6_hdr *oip6, *nip6;
|
||||||
struct icmp6_hdr *icmp6;
|
struct icmp6_hdr *icmp6;
|
||||||
|
struct epoch_tracker et;
|
||||||
u_int preplen;
|
u_int preplen;
|
||||||
int off;
|
int off;
|
||||||
int nxt;
|
int nxt;
|
||||||
@@ -379,7 +380,9 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
|
|||||||
icmp6->icmp6_pptr = htonl((u_int32_t)param);
|
icmp6->icmp6_pptr = htonl((u_int32_t)param);
|
||||||
|
|
||||||
ICMP6STAT_INC(icp6s_outhist[type]);
|
ICMP6STAT_INC(icp6s_outhist[type]);
|
||||||
|
NET_EPOCH_ENTER(et);
|
||||||
icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
|
icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
|
||||||
|
NET_EPOCH_EXIT(et);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -352,6 +352,7 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr *nam,
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
int scope_ambiguous = 0;
|
int scope_ambiguous = 0;
|
||||||
struct in6_addr in6a;
|
struct in6_addr in6a;
|
||||||
|
struct epoch_tracker et;
|
||||||
|
|
||||||
INP_WLOCK_ASSERT(inp);
|
INP_WLOCK_ASSERT(inp);
|
||||||
INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); /* XXXRW: why? */
|
INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); /* XXXRW: why? */
|
||||||
@@ -379,8 +380,10 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr *nam,
|
|||||||
if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
|
if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
NET_EPOCH_ENTER(et);
|
||||||
error = in6_selectsrc_socket(sin6, inp->in6p_outputopts,
|
error = in6_selectsrc_socket(sin6, inp->in6p_outputopts,
|
||||||
inp, inp->inp_cred, scope_ambiguous, &in6a, NULL);
|
inp, inp->inp_cred, scope_ambiguous, &in6a, NULL);
|
||||||
|
NET_EPOCH_EXIT(et);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ in6_selectsrc(uint32_t fibnum, struct sockaddr_in6 *dstsock,
|
|||||||
int error;
|
int error;
|
||||||
struct ip6_moptions *mopts;
|
struct ip6_moptions *mopts;
|
||||||
|
|
||||||
|
NET_EPOCH_ASSERT();
|
||||||
KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__));
|
KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__));
|
||||||
|
|
||||||
dst = dstsock->sin6_addr; /* make a copy for local operation */
|
dst = dstsock->sin6_addr; /* make a copy for local operation */
|
||||||
|
|||||||
@@ -413,6 +413,8 @@ nd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *saddr6,
|
|||||||
int maxlen;
|
int maxlen;
|
||||||
caddr_t mac;
|
caddr_t mac;
|
||||||
|
|
||||||
|
NET_EPOCH_ASSERT();
|
||||||
|
|
||||||
if (IN6_IS_ADDR_MULTICAST(taddr6))
|
if (IN6_IS_ADDR_MULTICAST(taddr6))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -947,6 +949,8 @@ nd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
|
|||||||
struct in6_addr daddr6, dst6, src6;
|
struct in6_addr daddr6, dst6, src6;
|
||||||
uint32_t scopeid;
|
uint32_t scopeid;
|
||||||
|
|
||||||
|
NET_EPOCH_ASSERT();
|
||||||
|
|
||||||
int icmp6len, maxlen, error;
|
int icmp6len, maxlen, error;
|
||||||
caddr_t mac = NULL;
|
caddr_t mac = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -478,8 +478,10 @@ rip6_output(struct mbuf *m, struct socket *so, ...)
|
|||||||
/*
|
/*
|
||||||
* Source address selection.
|
* Source address selection.
|
||||||
*/
|
*/
|
||||||
|
NET_EPOCH_ENTER(et);
|
||||||
error = in6_selectsrc_socket(dstsock, optp, inp, so->so_cred,
|
error = in6_selectsrc_socket(dstsock, optp, inp, so->so_cred,
|
||||||
scope_ambiguous, &in6a, &hlim);
|
scope_ambiguous, &in6a, &hlim);
|
||||||
|
NET_EPOCH_EXIT(et);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto bad;
|
goto bad;
|
||||||
@@ -795,6 +797,7 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
|||||||
struct inpcb *inp;
|
struct inpcb *inp;
|
||||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
|
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
|
||||||
struct in6_addr in6a;
|
struct in6_addr in6a;
|
||||||
|
struct epoch_tracker et;
|
||||||
int error = 0, scope_ambiguous = 0;
|
int error = 0, scope_ambiguous = 0;
|
||||||
|
|
||||||
inp = sotoinpcb(so);
|
inp = sotoinpcb(so);
|
||||||
@@ -823,8 +826,10 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
|||||||
INP_INFO_WLOCK(&V_ripcbinfo);
|
INP_INFO_WLOCK(&V_ripcbinfo);
|
||||||
INP_WLOCK(inp);
|
INP_WLOCK(inp);
|
||||||
/* Source address selection. XXX: need pcblookup? */
|
/* Source address selection. XXX: need pcblookup? */
|
||||||
|
NET_EPOCH_ENTER(et);
|
||||||
error = in6_selectsrc_socket(addr, inp->in6p_outputopts,
|
error = in6_selectsrc_socket(addr, inp->in6p_outputopts,
|
||||||
inp, so->so_cred, scope_ambiguous, &in6a, NULL);
|
inp, so->so_cred, scope_ambiguous, &in6a, NULL);
|
||||||
|
NET_EPOCH_EXIT(et);
|
||||||
if (error) {
|
if (error) {
|
||||||
INP_WUNLOCK(inp);
|
INP_WUNLOCK(inp);
|
||||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ send_output(struct mbuf *m, struct ifnet *ifp, int direction)
|
|||||||
struct ip6_hdr *ip6;
|
struct ip6_hdr *ip6;
|
||||||
struct sockaddr_in6 dst;
|
struct sockaddr_in6 dst;
|
||||||
struct icmp6_hdr *icmp6;
|
struct icmp6_hdr *icmp6;
|
||||||
|
struct epoch_tracker et;
|
||||||
int icmp6len;
|
int icmp6len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -150,7 +151,9 @@ send_output(struct mbuf *m, struct ifnet *ifp, int direction)
|
|||||||
*/
|
*/
|
||||||
switch (icmp6->icmp6_type) {
|
switch (icmp6->icmp6_type) {
|
||||||
case ND_NEIGHBOR_SOLICIT:
|
case ND_NEIGHBOR_SOLICIT:
|
||||||
|
NET_EPOCH_ENTER(et);
|
||||||
nd6_ns_input(m, sizeof(struct ip6_hdr), icmp6len);
|
nd6_ns_input(m, sizeof(struct ip6_hdr), icmp6len);
|
||||||
|
NET_EPOCH_EXIT(et);
|
||||||
break;
|
break;
|
||||||
case ND_NEIGHBOR_ADVERT:
|
case ND_NEIGHBOR_ADVERT:
|
||||||
nd6_na_input(m, sizeof(struct ip6_hdr), icmp6len);
|
nd6_na_input(m, sizeof(struct ip6_hdr), icmp6len);
|
||||||
|
|||||||
Reference in New Issue
Block a user