MFC 2290dfb40f
:
Enter the net epoch before calling ip6_setpktopts
ip6_setpktopts() can look up ifnets via ifnet_by_index(), which
is only safe in the net epoch. Ensure that callers are in the net
epoch before calling this function.
Sponsored by: Dell EMC Isilon
MFC after: 4 weeks
Reviewed by: donner, kp
Differential Revision: https://reviews.freebsd.org/D30630
(cherry picked from commit 2290dfb40f
)
This commit is contained in:
parent
e88dbe4f46
commit
bbce80f3ef
@ -2488,6 +2488,7 @@ ip6_pcbopts(struct ip6_pktopts **pktopt, struct mbuf *m,
|
||||
struct ip6_pktopts *opt = *pktopt;
|
||||
int error = 0;
|
||||
struct thread *td = sopt->sopt_td;
|
||||
struct epoch_tracker et;
|
||||
|
||||
/* turn off any old options. */
|
||||
if (opt) {
|
||||
@ -2515,12 +2516,15 @@ ip6_pcbopts(struct ip6_pktopts **pktopt, struct mbuf *m,
|
||||
}
|
||||
|
||||
/* set options specified by user. */
|
||||
NET_EPOCH_ENTER(et);
|
||||
if ((error = ip6_setpktopts(m, opt, NULL, (td != NULL) ?
|
||||
td->td_ucred : NULL, so->so_proto->pr_protocol)) != 0) {
|
||||
ip6_clearpktopts(opt, -1); /* XXX: discard all options */
|
||||
free(opt, M_IP6OPT);
|
||||
NET_EPOCH_EXIT(et);
|
||||
return (error);
|
||||
}
|
||||
NET_EPOCH_EXIT(et);
|
||||
*pktopt = opt;
|
||||
return (0);
|
||||
}
|
||||
@ -2816,6 +2820,12 @@ ip6_setpktopts(struct mbuf *control, struct ip6_pktopts *opt,
|
||||
if (control == NULL || opt == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* ip6_setpktopt can call ifnet_by_index(), so it's imperative that we are
|
||||
* in the net epoch here.
|
||||
*/
|
||||
NET_EPOCH_ASSERT();
|
||||
|
||||
ip6_initpktopts(opt);
|
||||
if (stickyopt) {
|
||||
int error;
|
||||
|
@ -419,9 +419,13 @@ rip6_output(struct mbuf *m, struct socket *so, ...)
|
||||
INP_WLOCK(inp);
|
||||
|
||||
if (control != NULL) {
|
||||
if ((error = ip6_setpktopts(control, &opt,
|
||||
NET_EPOCH_ENTER(et);
|
||||
error = ip6_setpktopts(control, &opt,
|
||||
inp->in6p_outputopts, so->so_cred,
|
||||
so->so_proto->pr_protocol)) != 0) {
|
||||
so->so_proto->pr_protocol);
|
||||
NET_EPOCH_EXIT(et);
|
||||
|
||||
if (error != 0) {
|
||||
goto bad;
|
||||
}
|
||||
optp = &opt;
|
||||
|
@ -810,21 +810,16 @@ udp6_output(struct socket *so, int flags_arg, struct mbuf *m,
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
NET_EPOCH_ENTER(et);
|
||||
if (control) {
|
||||
if ((error = ip6_setpktopts(control, &opt,
|
||||
inp->in6p_outputopts, td->td_ucred, nxt)) != 0) {
|
||||
INP_UNLOCK(inp);
|
||||
ip6_clearpktopts(&opt, -1);
|
||||
if (control)
|
||||
m_freem(control);
|
||||
m_freem(m);
|
||||
return (error);
|
||||
goto release;
|
||||
}
|
||||
optp = &opt;
|
||||
} else
|
||||
optp = inp->in6p_outputopts;
|
||||
|
||||
NET_EPOCH_ENTER(et);
|
||||
if (sin6) {
|
||||
/*
|
||||
* Since we saw no essential reason for calling in_pcbconnect,
|
||||
|
Loading…
Reference in New Issue
Block a user