summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2014-03-05 16:14:42 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2014-03-05 16:14:42 +0000
commit2d02bb4655a4bcc0b7f2e0b0e661270f13d0f8a3 (patch)
tree93668f0237e432973b0c0d568ce4c24afbe505ad
parenta16c14a26a4c72468482a0026ecaabafeb24fff9 (diff)
parenta1ca8b43681e3163e9f085ab65b8b6de1848d8ac (diff)
downloadillumos-joyent-2d02bb4655a4bcc0b7f2e0b0e661270f13d0f8a3.tar.gz
[illumos-gate merge]
commit a1ca8b43681e3163e9f085ab65b8b6de1848d8ac 4596 Callers of ip_srcid_find_id() need to be more careful commit 7298ed33f6dda314aee9fee22d0dccfb09cc0ef6 4314 mountd(1m): Options are not related to Solaris
-rw-r--r--usr/src/man/man1m/mountd.1m6
-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
6 files changed, 114 insertions, 45 deletions
diff --git a/usr/src/man/man1m/mountd.1m b/usr/src/man/man1m/mountd.1m
index 167ab98a27..655c2d060d 100644
--- a/usr/src/man/man1m/mountd.1m
+++ b/usr/src/man/man1m/mountd.1m
@@ -3,7 +3,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH MOUNTD 1M "Apr 27, 2005"
+.TH MOUNTD 1M "Mar 02, 2014"
.SH NAME
mountd \- server for NFS mount requests and NFS access checks
.SH SYNOPSIS
@@ -38,8 +38,8 @@ Only super user can run the \fBmountd\fR daemon.
.SH OPTIONS
.sp
.LP
-The options shown below are supported for NVSv2/v3 clients. They are not
-supported for Solaris NFSv4 clients.
+The options shown below are supported for NFSv2/v3 clients. They are not
+supported for NFSv4 clients.
.sp
.ne 2
.na
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);