Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160505120
D12586.id33731.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D12586.id33731.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D12586: improve inp locking in getsockopt, setsockopt, and related functions
Attached
Detach File
Event Timeline
Log In to Comment