Page MenuHomeFreeBSD

D12586.id33731.diff
No OneTemporary

D12586.id33731.diff

Index: sys/netinet/ip_output.c
===================================================================
--- sys/netinet/ip_output.c
+++ sys/netinet/ip_output.c
@@ -1076,17 +1076,23 @@
switch (sopt->sopt_name) {
case IP_TOS:
+ INP_WLOCK(inp);
inp->inp_ip_tos = optval;
+ INP_WUNLOCK(inp);
break;
case IP_TTL:
+ INP_WLOCK(inp);
inp->inp_ip_ttl = optval;
+ INP_WUNLOCK(inp);
break;
case IP_MINTTL:
- if (optval >= 0 && optval <= MAXTTL)
+ if (optval >= 0 && optval <= MAXTTL) {
+ INP_WLOCK(inp);
inp->inp_ip_minttl = optval;
- else
+ INP_WUNLOCK(inp);
+ } else
error = EINVAL;
break;
@@ -1099,12 +1105,15 @@
INP_WUNLOCK(inp); \
} while (0)
-#define OPTSET2(bit, val) do { \
- INP_WLOCK(inp); \
+#define OPTSET2_N(bit, val) do { \
if (val) \
inp->inp_flags2 |= bit; \
else \
inp->inp_flags2 &= ~bit; \
+} while (0)
+#define OPTSET2(bit, val) do { \
+ INP_WLOCK(inp); \
+ OPTSET2_N(bit, val); \
INP_WUNLOCK(inp); \
} while (0)
@@ -1154,8 +1163,10 @@
case IP_RSS_LISTEN_BUCKET:
if ((optval >= 0) &&
(optval < rss_getnumbuckets())) {
+ INP_WLOCK(inp);
inp->inp_rss_listen_bucket = optval;
- OPTSET2(INP_RSS_BUCKET_SET, 1);
+ OPTSET2_N(INP_RSS_BUCKET_SET, 1);
+ INP_WUNLOCK(inp);
} else {
error = EINVAL;
}
@@ -1242,6 +1253,7 @@
switch (sopt->sopt_name) {
case IP_OPTIONS:
case IP_RETOPTS:
+ INP_RLOCK(inp);
if (inp->inp_options)
error = sooptcopyout(sopt,
mtod(inp->inp_options,
@@ -1249,6 +1261,7 @@
inp->inp_options->m_len);
else
sopt->sopt_valsize = 0;
+ INP_RUNLOCK(inp);
break;
case IP_TOS:
@@ -1315,12 +1328,14 @@
break;
case IP_PORTRANGE:
+ INP_RLOCK(inp);
if (inp->inp_flags & INP_HIGHPORT)
optval = IP_PORTRANGE_HIGH;
else if (inp->inp_flags & INP_LOWPORT)
optval = IP_PORTRANGE_LOW;
else
optval = 0;
+ INP_RUNLOCK(inp);
break;
case IP_ONESBCAST:
@@ -1346,6 +1361,7 @@
break;
#ifdef RSS
case IP_RSSBUCKETID:
+ INP_RLOCK(inp);
retval = rss_hash2bucket(inp->inp_flowid,
inp->inp_flowtype,
&rss_bucket);
@@ -1353,6 +1369,7 @@
optval = rss_bucket;
else
error = EINVAL;
+ INP_RUNLOCK(inp);
break;
case IP_RECVRSSBUCKETID:
optval = OPTBIT2(INP_RECVRSSBUCKETID);
Index: sys/netinet/raw_ip.c
===================================================================
--- sys/netinet/raw_ip.c
+++ sys/netinet/raw_ip.c
@@ -569,7 +569,9 @@
if (sopt->sopt_level != IPPROTO_IP) {
if ((sopt->sopt_level == SOL_SOCKET) &&
(sopt->sopt_name == SO_SETFIB)) {
+ INP_WLOCK(inp);
inp->inp_inc.inc_fibnum = so->so_fibnum;
+ INP_WUNLOCK(inp);
return (0);
}
return (EINVAL);
@@ -637,10 +639,12 @@
sizeof optval);
if (error)
break;
+ INP_WLOCK(inp);
if (optval)
inp->inp_flags |= INP_HDRINCL;
else
inp->inp_flags &= ~INP_HDRINCL;
+ INP_WUNLOCK(inp);
break;
case IP_FW3: /* generic ipfw v.3 functions */
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -133,7 +133,7 @@
struct ucred *, int);
static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *,
struct socket *, struct sockopt *);
-static int ip6_getpcbopt(struct ip6_pktopts *, int, struct sockopt *);
+static int ip6_getpcbopt(struct inpcb *, int, struct sockopt *);
static int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *,
struct ucred *, int, int, int);
@@ -1496,8 +1496,10 @@
error = soopt_mcopyin(sopt, m); /* XXX */
if (error != 0)
break;
+ INP_WLOCK(in6p);
error = ip6_pcbopts(&in6p->in6p_outputopts,
m, so, sopt);
+ INP_WUNLOCK(in6p);
m_freem(m); /* XXX */
break;
}
@@ -1567,19 +1569,25 @@
error = EINVAL;
else {
/* -1 = kernel default */
+ INP_WLOCK(in6p);
in6p->in6p_hops = optval;
if ((in6p->inp_vflag &
INP_IPV4) != 0)
in6p->inp_ip_ttl = optval;
+ INP_WUNLOCK(in6p);
}
break;
-#define OPTSET(bit) \
+#define OPTSET_N(bit) \
do { \
- INP_WLOCK(in6p); \
if (optval) \
in6p->inp_flags |= (bit); \
else \
in6p->inp_flags &= ~(bit); \
+} while (/*CONSTCOND*/ 0)
+#define OPTSET(bit) \
+do { \
+ INP_WLOCK(in6p); \
+ OPTSET_N(bit); \
INP_WUNLOCK(in6p); \
} while (/*CONSTCOND*/ 0)
#define OPTSET2292(bit) \
@@ -1594,23 +1602,34 @@
} while (/*CONSTCOND*/ 0)
#define OPTBIT(bit) (in6p->inp_flags & (bit) ? 1 : 0)
-#define OPTSET2(bit, val) do { \
- INP_WLOCK(in6p); \
+#define OPTSET2_N(bit, val) do { \
if (val) \
in6p->inp_flags2 |= bit; \
else \
in6p->inp_flags2 &= ~bit; \
+} while (0)
+#define OPTSET2(bit, val) do { \
+ INP_WLOCK(in6p); \
+ OPTSET2_N(bit, val); \
INP_WUNLOCK(in6p); \
} while (0)
#define OPTBIT2(bit) (in6p->inp_flags2 & (bit) ? 1 : 0)
+#define OPTSET2292_EXCLUSIVE(bit) \
+do { \
+ INP_WLOCK(in6p); \
+ if (OPTBIT(IN6P_RFC2292)) { \
+ error = EINVAL; \
+ } else { \
+ if (optval) \
+ in6p->inp_flags |= (bit); \
+ else \
+ in6p->inp_flags &= ~(bit); \
+ } \
+ INP_WUNLOCK(in6p); \
+} while (/*CONSTCOND*/ 0)
case IPV6_RECVPKTINFO:
- /* cannot mix with RFC2292 */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
- OPTSET(IN6P_PKTINFO);
+ OPTSET2292_EXCLUSIVE(IN6P_PKTINFO);
break;
case IPV6_HOPLIMIT:
@@ -1622,57 +1641,34 @@
error = EINVAL;
break;
}
+ INP_WLOCK(in6p);
optp = &in6p->in6p_outputopts;
error = ip6_pcbopt(IPV6_HOPLIMIT,
(u_char *)&optval, sizeof(optval),
optp, (td != NULL) ? td->td_ucred :
NULL, uproto);
+ INP_WUNLOCK(in6p);
break;
}
case IPV6_RECVHOPLIMIT:
- /* cannot mix with RFC2292 */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
- OPTSET(IN6P_HOPLIMIT);
+ OPTSET2292_EXCLUSIVE(IN6P_HOPLIMIT);
break;
case IPV6_RECVHOPOPTS:
- /* cannot mix with RFC2292 */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
- OPTSET(IN6P_HOPOPTS);
+ OPTSET2292_EXCLUSIVE(IN6P_HOPOPTS);
break;
case IPV6_RECVDSTOPTS:
- /* cannot mix with RFC2292 */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
- OPTSET(IN6P_DSTOPTS);
+ OPTSET2292_EXCLUSIVE(IN6P_DSTOPTS);
break;
case IPV6_RECVRTHDRDSTOPTS:
- /* cannot mix with RFC2292 */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
- OPTSET(IN6P_RTHDRDSTOPTS);
+ OPTSET2292_EXCLUSIVE(IN6P_RTHDRDSTOPTS);
break;
case IPV6_RECVRTHDR:
- /* cannot mix with RFC2292 */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
- OPTSET(IN6P_RTHDR);
+ OPTSET2292_EXCLUSIVE(IN6P_RTHDR);
break;
case IPV6_RECVPATHMTU:
@@ -1702,24 +1698,24 @@
* available only prior to bind(2).
* see ipng mailing list, Jun 22 2001.
*/
+ INP_WLOCK(in6p);
if (in6p->inp_lport ||
!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
error = EINVAL;
+ INP_WUNLOCK(in6p);
break;
}
- OPTSET(IN6P_IPV6_V6ONLY);
+ OPTSET_N(IN6P_IPV6_V6ONLY);
+ /* optclear vflag */
if (optval)
in6p->inp_vflag &= ~INP_IPV4;
else
in6p->inp_vflag |= INP_IPV4;
+ INP_WUNLOCK(in6p);
break;
case IPV6_RECVTCLASS:
/* cannot mix with RFC2292 XXX */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
- OPTSET(IN6P_TCLASS);
+ OPTSET2292_EXCLUSIVE(IN6P_TCLASS);
break;
case IPV6_AUTOFLOWLABEL:
OPTSET(IN6P_AUTOFLOWLABEL);
@@ -1739,8 +1735,10 @@
case IPV6_RSS_LISTEN_BUCKET:
if ((optval >= 0) &&
(optval < rss_getnumbuckets())) {
+ INP_WLOCK(in6p);
in6p->inp_rss_listen_bucket = optval;
- OPTSET2(INP_RSS_BUCKET_SET, 1);
+ OPTSET2_N(INP_RSS_BUCKET_SET, 1);
+ INP_WUNLOCK(in6p);
} else {
error = EINVAL;
}
@@ -1763,11 +1761,13 @@
break;
{
struct ip6_pktopts **optp;
+ INP_WLOCK(in6p);
optp = &in6p->in6p_outputopts;
error = ip6_pcbopt(optname,
(u_char *)&optval, sizeof(optval),
optp, (td != NULL) ? td->td_ucred :
NULL, uproto);
+ INP_WUNLOCK(in6p);
break;
}
@@ -1832,12 +1832,6 @@
int optlen;
struct ip6_pktopts **optp;
- /* cannot mix with RFC2292 */
- if (OPTBIT(IN6P_RFC2292)) {
- error = EINVAL;
- break;
- }
-
/*
* We only ensure valsize is not too large
* here. Further validation will be done
@@ -1847,12 +1841,21 @@
sizeof(optbuf_storage), 0);
if (error)
break;
+
+ INP_WLOCK(in6p);
+ /* cannot mix with RFC2292 */
+ if (OPTBIT(IN6P_RFC2292)) {
+ error = EINVAL;
+ INP_WUNLOCK(in6p);
+ break;
+ }
optlen = sopt->sopt_valsize;
optbuf = optbuf_storage;
optp = &in6p->in6p_outputopts;
error = ip6_pcbopt(optname, optbuf, optlen,
optp, (td != NULL) ? td->td_ucred : NULL,
uproto);
+ INP_WUNLOCK(in6p);
break;
}
#undef OPTSET
@@ -1999,6 +2002,7 @@
case IPV6_PORTRANGE:
{
int flags;
+ INP_RLOCK(in6p);
flags = in6p->inp_flags;
if (flags & INP_HIGHPORT)
optval = IPV6_PORTRANGE_HIGH;
@@ -2006,6 +2010,7 @@
optval = IPV6_PORTRANGE_LOW;
else
optval = 0;
+ INP_RUNLOCK(in6p);
break;
}
case IPV6_RECVTCLASS:
@@ -2037,6 +2042,7 @@
break;
#ifdef RSS
case IPV6_RSSBUCKETID:
+ INP_RLOCK(in6p);
retval =
rss_hash2bucket(in6p->inp_flowid,
in6p->inp_flowtype,
@@ -2045,6 +2051,7 @@
optval = rss_bucket;
else
error = EINVAL;
+ INP_RUNLOCK(in6p);
break;
case IPV6_RECVRSSBUCKETID:
@@ -2067,6 +2074,7 @@
{
u_long pmtu = 0;
struct ip6_mtuinfo mtuinfo;
+ struct in6_addr addr;
if (!(so->so_state & SS_ISCONNECTED))
return (ENOTCONN);
@@ -2074,9 +2082,15 @@
* XXX: we dot not consider the case of source
* routing, or optional information to specify
* the outgoing interface.
+ * Copy faddr out of in6p to avoid holding lock
+ * on inp during route lookup.
*/
+ INP_RLOCK(in6p);
+ bzero(&addr, sizeof(addr));
+ bcopy(&in6p->in6p_faddr, &addr, sizeof(addr));
+ INP_RUNLOCK(in6p);
error = ip6_getpmtu_ctl(so->so_fibnum,
- &in6p->in6p_faddr, &pmtu);
+ &addr, &pmtu);
if (error)
break;
if (pmtu > IPV6_MAXPACKET)
@@ -2126,8 +2140,7 @@
case IPV6_DONTFRAG:
case IPV6_USE_MIN_MTU:
case IPV6_PREFER_TEMPADDR:
- error = ip6_getpcbopt(in6p->in6p_outputopts,
- optname, sopt);
+ error = ip6_getpcbopt(in6p, optname, sopt);
break;
case IPV6_MULTICAST_IF:
@@ -2199,15 +2212,19 @@
IPPROTO_ICMPV6) {
if (optval != icmp6off)
error = EINVAL;
- } else
+ } else {
+ INP_WLOCK(in6p);
in6p->in6p_cksum = optval;
+ INP_WUNLOCK(in6p);
+ }
break;
case SOPT_GET:
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
optval = icmp6off;
- else
+ else {
optval = in6p->in6p_cksum;
+ }
error = sooptcopyout(sopt, &optval, sizeof(optval));
break;
@@ -2238,6 +2255,8 @@
int error = 0;
struct thread *td = sopt->sopt_td;
+ INP_WLOCK_ASSERT(sotoinpcb(so));
+
/* turn off any old options. */
if (opt) {
#ifdef DIAGNOSTIC
@@ -2303,7 +2322,7 @@
}
static int
-ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct sockopt *sopt)
+ip6_getpcbopt(struct inpcb *in6p, int optname, struct sockopt *sopt)
{
void *optdata = NULL;
int optdatalen = 0;
@@ -2313,6 +2332,10 @@
int deftclass = 0, on;
int defminmtu = IP6PO_MINMTU_MCASTONLY;
int defpreftemp = IP6PO_TEMPADDR_SYSTEM;
+ struct ip6_pktopts *pktopt;
+
+ INP_RLOCK(in6p);
+ pktopt = in6p->in6p_outputopts;
switch (optname) {
case IPV6_PKTINFO:
@@ -2394,8 +2417,10 @@
#ifdef DIAGNOSTIC
panic("ip6_getpcbopt: unexpected option\n");
#endif
+ INP_RUNLOCK(in6p);
return (ENOPROTOOPT);
}
+ INP_RUNLOCK(in6p);
error = sooptcopyout(sopt, optdata, optdatalen);
@@ -3082,6 +3107,8 @@
{
int len;
+ INP_WLOCK_ASSERT(in6p);
+
if (!in6p->in6p_outputopts)
return 0;
Index: sys/netipsec/ipsec_pcb.c
===================================================================
--- sys/netipsec/ipsec_pcb.c
+++ sys/netipsec/ipsec_pcb.c
@@ -276,6 +276,8 @@
struct secpolicy **spp, *newsp;
int error, flags;
+ INP_WLOCK_ASSERT(inp);
+
xpl = (struct sadb_x_policy *)request;
/* Select direction. */
switch (xpl->sadb_x_policy_dir) {
@@ -283,6 +285,7 @@
case IPSEC_DIR_OUTBOUND:
break;
default:
+ INP_WUNLOCK(inp);
ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
xpl->sadb_x_policy_dir));
return (EINVAL);
@@ -300,8 +303,10 @@
return (EACCES);
/* Allocate new SP entry. */
newsp = key_msg2sp(xpl, len, &error);
- if (newsp == NULL)
+ if (newsp == NULL) {
+ INP_WUNLOCK(inp);
return (error);
+ }
newsp->state = IPSEC_SPSTATE_PCB;
newsp->spidx.ul_proto = IPSEC_ULPROTO_ANY;
#ifdef INET
@@ -329,10 +334,10 @@
break;
default:
/* Other security policy types aren't allowed for PCB */
+ INP_WUNLOCK(inp);
return (EINVAL);
}
- INP_WLOCK(inp);
if (xpl->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
spp = &inp->inp_sp->sp_in;
flags = INP_INBOUND_POLICY;
@@ -365,7 +370,7 @@
xpl = (struct sadb_x_policy *)request;
- INP_RLOCK(inp);
+ INP_RLOCK_ASSERT(inp);
flags = inp->inp_sp->flags;
/* Select direction. */
switch (xpl->sadb_x_policy_dir) {
@@ -421,9 +426,6 @@
size_t optlen;
int error;
- if (inp->inp_sp == NULL)
- return (ENOPROTOOPT);
-
/* Limit maximum request size to PAGE_SIZE */
optlen = sopt->sopt_valsize;
if (optlen < sizeof(struct sadb_x_policy) || optlen > PAGE_SIZE)
@@ -439,12 +441,34 @@
*/
error = sooptcopyin(sopt, optdata, optlen, optlen);
if (error == 0) {
- if (sopt->sopt_dir == SOPT_SET)
+ if (sopt->sopt_dir == SOPT_SET) {
+ INP_WLOCK(inp);
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_WUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ if (inp->inp_sp == NULL) {
+ INP_WUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
+
error = ipsec_set_pcbpolicy(inp,
sopt->sopt_td ? sopt->sopt_td->td_ucred: NULL,
optdata, optlen);
- else {
+ /* ipsec_set_pcbpolicy unlocks */
+ INP_WUNLOCK(inp);
+ } else {
+ INP_RLOCK(inp);
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_RUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ if (inp->inp_sp == NULL) {
+ INP_RUNLOCK(inp);
+ return (ENOPROTOOPT);
+ }
error = ipsec_get_pcbpolicy(inp, optdata, &optlen);
+ /* ipsec_get_pcbpolicy unlocks */
if (error == 0)
error = sooptcopyout(sopt, optdata, optlen);
}
Index: sys/netipsec/xform_tcp.c
===================================================================
--- sys/netipsec/xform_tcp.c
+++ sys/netipsec/xform_tcp.c
@@ -78,21 +78,31 @@
struct tcpcb *tp;
int error, optval;
- INP_WLOCK_ASSERT(inp);
if (sopt->sopt_name != TCP_MD5SIG) {
- INP_WUNLOCK(inp);
return (ENOPROTOOPT);
}
- tp = intotcpcb(inp);
if (sopt->sopt_dir == SOPT_GET) {
+ INP_RLOCK(inp);
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_RUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ tp = intotcpcb(inp);
optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
- /* On success return with released INP_WLOCK */
+ /* On success return with released INP_RLOCK */
return (sooptcopyout(sopt, &optval, sizeof(optval)));
}
+ INP_WLOCK(inp);
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_WUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ tp = intotcpcb(inp);
+
INP_WUNLOCK(inp);
error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
@@ -109,8 +119,9 @@
tp->t_flags |= TF_SIGNATURE;
else
tp->t_flags &= ~TF_SIGNATURE;
+ INP_WUNLOCK(inp);
- /* On success return with acquired INP_WLOCK */
+ /* On success return with released INP_WLOCK */
return (error);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Jun 26, 4:50 AM (13 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34342125
Default Alt Text
D12586.id33731.diff (16 KB)

Event Timeline