summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorDan McDonald <danmcd@omniti.com>2014-02-14 11:27:16 -0500
committerDan McDonald <danmcd@omniti.com>2014-03-05 10:54:10 -0500
commita1ca8b43681e3163e9f085ab65b8b6de1848d8ac (patch)
tree116b6fc2cff4ac6b6e952a344371b80a11b5af39 /usr/src
parent7298ed33f6dda314aee9fee22d0dccfb09cc0ef6 (diff)
downloadillumos-joyent-a1ca8b43681e3163e9f085ab65b8b6de1848d8ac.tar.gz
4596 Callers of ip_srcid_find_id() need to be more careful
Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Sebastien Roy <sebastien.roy@delphix.com> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/inet/ip.h4
-rw-r--r--usr/src/uts/common/inet/ip/icmp.c52
-rw-r--r--usr/src/uts/common/inet/ip/ip_srcid.c29
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c15
-rw-r--r--usr/src/uts/common/inet/udp/udp.c53
5 files changed, 111 insertions, 42 deletions
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index fcf70368c8..fde3dc3ad3 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -24,6 +24,7 @@
* Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
*/
#ifndef _INET_IP_H
@@ -3453,7 +3454,8 @@ extern void ire_untrace_ref(ire_t *);
extern int ip_srcid_insert(const in6_addr_t *, zoneid_t, ip_stack_t *);
extern int ip_srcid_remove(const in6_addr_t *, zoneid_t, ip_stack_t *);
-extern void ip_srcid_find_id(uint_t, in6_addr_t *, zoneid_t, netstack_t *);
+extern boolean_t ip_srcid_find_id(uint_t, in6_addr_t *, zoneid_t, boolean_t,
+ netstack_t *);
extern uint_t ip_srcid_find_addr(const in6_addr_t *, zoneid_t, netstack_t *);
extern uint8_t ipoptp_next(ipoptp_t *);
diff --git a/usr/src/uts/common/inet/ip/icmp.c b/usr/src/uts/common/inet/ip/icmp.c
index 9f6bc8b22f..8da126f7dc 100644
--- a/usr/src/uts/common/inet/ip/icmp.c
+++ b/usr/src/uts/common/inet/ip/icmp.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -768,8 +769,12 @@ rawip_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
scopeid = sin6->sin6_scope_id;
srcid = sin6->__sin6_src_id;
if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
+ /* Due to check above, we know sin6_addr is v6-only. */
+ if (!ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+ B_FALSE, connp->conn_netstack)) {
+ /* Mismatch - v6src would be v4mapped. */
+ return (EADDRNOTAVAIL);
+ }
}
break;
}
@@ -3337,7 +3342,6 @@ icmp_output_ancillary(conn_t *connp, sin_t *sin, sin6_t *sin6, mblk_t *mp,
in6_addr_t v6nexthop;
in_port_t dstport;
uint32_t flowinfo;
- uint_t srcid;
int is_absreq_failure = 0;
conn_opt_arg_t coas, *coa;
@@ -3440,6 +3444,9 @@ icmp_output_ancillary(conn_t *connp, sin_t *sin, sin6_t *sin6, mblk_t *mp,
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
ixa->ixa_flags |= IXAF_IS_IPV4;
} else if (sin6 != NULL) {
+ boolean_t v4mapped;
+ uint_t srcid;
+
v6dst = sin6->sin6_addr;
dstport = sin6->sin6_port;
flowinfo = sin6->sin6_flowinfo;
@@ -3450,14 +3457,20 @@ icmp_output_ancillary(conn_t *connp, sin_t *sin, sin6_t *sin6, mblk_t *mp,
} else {
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
}
- if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
- }
- if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+ v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+ if (v4mapped)
ixa->ixa_flags |= IXAF_IS_IPV4;
else
ixa->ixa_flags &= ~IXAF_IS_IPV4;
+ if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+ if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+ v4mapped, connp->conn_netstack)) {
+ /* Mismatched v4mapped/v6 specified by srcid. */
+ mutex_exit(&connp->conn_lock);
+ error = EADDRNOTAVAIL;
+ goto failed; /* Does freemsg() and mib. */
+ }
+ }
} else {
/* Connected case */
v6dst = connp->conn_faddr_v6;
@@ -4419,14 +4432,13 @@ icmp_output_newdst(conn_t *connp, mblk_t *data_mp, sin_t *sin, sin6_t *sin6,
IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
dstport = sin->sin_port;
flowinfo = 0;
+ /* Don't bother with ip_srcid_find_id(), but indicate anyway. */
srcid = 0;
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
- if (srcid != 0 && V4_PART_OF_V6(&v6src) == INADDR_ANY) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
- }
ixa->ixa_flags |= IXAF_IS_IPV4;
} else {
+ boolean_t v4mapped;
+
v6dst = sin6->sin6_addr;
dstport = sin6->sin6_port;
flowinfo = sin6->sin6_flowinfo;
@@ -4437,14 +4449,20 @@ icmp_output_newdst(conn_t *connp, mblk_t *data_mp, sin_t *sin, sin6_t *sin6,
} else {
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
}
- if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
- }
- if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+ v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+ if (v4mapped)
ixa->ixa_flags |= IXAF_IS_IPV4;
else
ixa->ixa_flags &= ~IXAF_IS_IPV4;
+ if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+ if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+ v4mapped, connp->conn_netstack)) {
+ /* Mismatched v4mapped/v6 specified by srcid. */
+ mutex_exit(&connp->conn_lock);
+ error = EADDRNOTAVAIL;
+ goto ud_error;
+ }
+ }
}
/* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
if (connp->conn_xmit_ipp.ipp_fields & IPPF_ADDR) {
diff --git a/usr/src/uts/common/inet/ip/ip_srcid.c b/usr/src/uts/common/inet/ip/ip_srcid.c
index f6507d6413..efb49f20e0 100644
--- a/usr/src/uts/common/inet/ip/ip_srcid.c
+++ b/usr/src/uts/common/inet/ip/ip_srcid.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
*/
/*
@@ -223,14 +225,22 @@ ip_srcid_find_addr(const in6_addr_t *addr, zoneid_t zoneid,
/*
* Map from a source id to an address.
* If the id is unknown return the unspecified address.
+ *
+ * For known IDs, check if the returned address is v4mapped or not, and
+ * return B_TRUE if it matches the desired v4mapped state or not. This
+ * prevents a broken app from requesting (via __sin6_src_id) a v4mapped
+ * address for a v6 destination, or vice versa.
+ *
+ * "addr" will not be set if we return B_FALSE.
*/
-void
+boolean_t
ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
- netstack_t *ns)
+ boolean_t v4mapped, netstack_t *ns)
{
srcid_map_t **smpp;
srcid_map_t *smp;
ip_stack_t *ipst = ns->netstack_ip;
+ boolean_t rc;
rw_enter(&ipst->ips_srcid_lock, RW_READER);
smpp = srcid_lookup_id(id, ipst);
@@ -239,11 +249,24 @@ ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
/* Not preset */
ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id));
*addr = ipv6_all_zeros;
+ rc = B_TRUE;
} else {
ASSERT(smp->sm_refcnt != 0);
- *addr = smp->sm_addr;
+ /*
+ * The caller tells us if it expects a v4mapped address.
+ * Use it, along with the property of "addr" to set the rc.
+ */
+ if (IN6_IS_ADDR_V4MAPPED(addr))
+ rc = v4mapped; /* We want a v4mapped address. */
+ else
+ rc = !v4mapped; /* We don't want a v4mapped address. */
+
+ if (rc)
+ *addr = smp->sm_addr;
+
}
rw_exit(&ipst->ips_srcid_lock);
+ return (rc);
}
/* Assign the next available ID */
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index 5ba1c603c0..7d48fd1c49 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -24,6 +24,7 @@
* Copyright (c) 2011, Joyent Inc. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -1583,8 +1584,11 @@ tcp_connect_ipv4(tcp_t *tcp, ipaddr_t *dstaddrp, in_port_t dstport,
/* Handle __sin6_src_id if socket not bound to an IP address */
if (srcid != 0 && connp->conn_laddr_v4 == INADDR_ANY) {
- ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
- IPCL_ZONEID(connp), tcps->tcps_netstack);
+ if (!ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
+ IPCL_ZONEID(connp), B_TRUE, tcps->tcps_netstack)) {
+ /* Mismatch - conn_laddr_v6 would be v6 address. */
+ return (EADDRNOTAVAIL);
+ }
connp->conn_saddr_v6 = connp->conn_laddr_v6;
}
@@ -1665,8 +1669,11 @@ tcp_connect_ipv6(tcp_t *tcp, in6_addr_t *dstaddrp, in_port_t dstport,
/* Handle __sin6_src_id if socket not bound to an IP address */
if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
- ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
- IPCL_ZONEID(connp), tcps->tcps_netstack);
+ if (!ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
+ IPCL_ZONEID(connp), B_FALSE, tcps->tcps_netstack)) {
+ /* Mismatch - conn_laddr_v6 would be v4-mapped. */
+ return (EADDRNOTAVAIL);
+ }
connp->conn_saddr_v6 = connp->conn_laddr_v6;
}
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c
index e6dfd3efe9..4a6e835b67 100644
--- a/usr/src/uts/common/inet/udp/udp.c
+++ b/usr/src/uts/common/inet/udp/udp.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
*/
/* Copyright (c) 1990 Mentat Inc. */
@@ -2714,6 +2715,8 @@ udp_output_ancillary(conn_t *connp, sin_t *sin, sin6_t *sin6, mblk_t *mp,
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
ixa->ixa_flags |= IXAF_IS_IPV4;
} else if (sin6 != NULL) {
+ boolean_t v4mapped;
+
v6dst = sin6->sin6_addr;
dstport = sin6->sin6_port;
flowinfo = sin6->sin6_flowinfo;
@@ -2724,14 +2727,20 @@ udp_output_ancillary(conn_t *connp, sin_t *sin, sin6_t *sin6, mblk_t *mp,
} else {
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
}
- if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
- }
- if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+ v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+ if (v4mapped)
ixa->ixa_flags |= IXAF_IS_IPV4;
else
ixa->ixa_flags &= ~IXAF_IS_IPV4;
+ if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+ if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+ v4mapped, connp->conn_netstack)) {
+ /* Mismatch - v4mapped/v6 specified by srcid. */
+ mutex_exit(&connp->conn_lock);
+ error = EADDRNOTAVAIL;
+ goto failed; /* Does freemsg() and mib. */
+ }
+ }
} else {
/* Connected case */
v6dst = connp->conn_faddr_v6;
@@ -3722,14 +3731,13 @@ udp_output_newdst(conn_t *connp, mblk_t *data_mp, sin_t *sin, sin6_t *sin6,
IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
dstport = sin->sin_port;
flowinfo = 0;
+ /* Don't bother with ip_srcid_find_id(), but indicate anyway. */
srcid = 0;
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
- if (srcid != 0 && V4_PART_OF_V6(&v6src) == INADDR_ANY) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
- }
ixa->ixa_flags |= IXAF_IS_IPV4;
} else {
+ boolean_t v4mapped;
+
v6dst = sin6->sin6_addr;
dstport = sin6->sin6_port;
flowinfo = sin6->sin6_flowinfo;
@@ -3740,14 +3748,20 @@ udp_output_newdst(conn_t *connp, mblk_t *data_mp, sin_t *sin, sin6_t *sin6,
} else {
ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
}
- if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
- }
- if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+ v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+ if (v4mapped)
ixa->ixa_flags |= IXAF_IS_IPV4;
else
ixa->ixa_flags &= ~IXAF_IS_IPV4;
+ if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+ if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+ v4mapped, connp->conn_netstack)) {
+ /* Mismatched v4mapped/v6 specified by srcid. */
+ mutex_exit(&connp->conn_lock);
+ error = EADDRNOTAVAIL;
+ goto ud_error;
+ }
+ }
}
/* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
if (connp->conn_xmit_ipp.ipp_fields & IPPF_ADDR) {
@@ -5526,6 +5540,7 @@ udp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
uint_t scopeid = 0;
uint_t srcid = 0;
in6_addr_t v6src = connp->conn_saddr_v6;
+ boolean_t v4mapped;
udp = connp->conn_udp;
us = udp->udp_us;
@@ -5554,11 +5569,15 @@ udp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
v6dst = sin6->sin6_addr;
dstport = sin6->sin6_port;
srcid = sin6->__sin6_src_id;
+ v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
- ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
- connp->conn_netstack);
+ if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+ v4mapped, connp->conn_netstack)) {
+ /* Mismatch v4mapped/v6 specified by srcid. */
+ return (EADDRNOTAVAIL);
+ }
}
- if (IN6_IS_ADDR_V4MAPPED(&v6dst)) {
+ if (v4mapped) {
if (connp->conn_ipv6_v6only)
return (EADDRNOTAVAIL);