changeset 11680:f7d6d87905e0

6923355 tcp leaves conn_ixa->ixa_cred unitialized causing confusion
author Erik Nordmark <Erik.Nordmark@Sun.COM>
date Wed, 17 Feb 2010 19:52:19 -0800
parents d52267d340fe
children fe992d6ccc26
files usr/src/uts/common/inet/ip/icmp.c usr/src/uts/common/inet/ip/ip.c usr/src/uts/common/inet/ip/ip_attr.c usr/src/uts/common/inet/ip/ipclassifier.c usr/src/uts/common/inet/tcp/tcp.c usr/src/uts/common/inet/udp/udp.c
diffstat 6 files changed, 81 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/icmp.c	Wed Feb 17 20:52:17 2010 -0500
+++ b/usr/src/uts/common/inet/ip/icmp.c	Wed Feb 17 19:52:19 2010 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1990 Mentat Inc. */
@@ -800,6 +800,15 @@
 		connp->conn_flowinfo = flowinfo;
 	}
 
+	/*
+	 * We update our cred/cpid based on the caller of connect
+	 */
+	if (connp->conn_cred != cr) {
+		crhold(cr);
+		crfree(connp->conn_cred);
+		connp->conn_cred = cr;
+	}
+	connp->conn_cpid = pid;
 	ixa->ixa_cred = cr;
 	ixa->ixa_cpid = pid;
 	if (is_system_labeled()) {
@@ -3050,6 +3059,8 @@
 	/* Get a copy of conn_xmit_ipp since the TX label might change it */
 	ipp = kmem_zalloc(sizeof (*ipp), KM_NOSLEEP);
 	if (ipp == NULL) {
+		ixa->ixa_cred = connp->conn_cred;	/* Restore */
+		ixa->ixa_cpid = connp->conn_cpid;
 		ixa_refrele(ixa);
 		BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
 		freemsg(mp);
@@ -3273,6 +3284,8 @@
 		break;
 	}
 done:
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	ip_pkt_free(ipp);
 	kmem_free(ipp, sizeof (*ipp));
@@ -3352,6 +3365,8 @@
 	/* Get a copy of conn_xmit_ipp since the options might change it */
 	ipp = kmem_zalloc(sizeof (*ipp), KM_NOSLEEP);
 	if (ipp == NULL) {
+		ixa->ixa_cred = connp->conn_cred;	/* Restore */
+		ixa->ixa_cpid = connp->conn_cpid;
 		ixa_refrele(ixa);
 		BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
 		freemsg(mp);
@@ -3582,6 +3597,8 @@
 		break;
 	}
 done:
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	ip_pkt_free(ipp);
 	kmem_free(ipp, sizeof (*ipp));
@@ -3633,6 +3650,8 @@
 	if (mp == NULL) {
 		ASSERT(error != 0);
 		mutex_exit(&connp->conn_lock);
+		ixa->ixa_cred = connp->conn_cred;	/* Restore */
+		ixa->ixa_cpid = connp->conn_cpid;
 		ixa_refrele(ixa);
 		BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
 		freemsg(mp);
@@ -3645,6 +3664,8 @@
 		if (mp == NULL) {
 			mutex_exit(&connp->conn_lock);
 			BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
+			ixa->ixa_cred = connp->conn_cred;	/* Restore */
+			ixa->ixa_cpid = connp->conn_cpid;
 			ixa_refrele(ixa);
 			return (EHOSTUNREACH);	/* IPsec policy failure */
 		}
@@ -3699,6 +3720,8 @@
 			/* FALLTHRU */
 		default:
 		failed:
+			ixa->ixa_cred = connp->conn_cred;	/* Restore */
+			ixa->ixa_cpid = connp->conn_cpid;
 			ixa_refrele(ixa);
 			BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
 			freemsg(mp);
@@ -3729,6 +3752,8 @@
 		error = ENETUNREACH;
 		break;
 	}
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	return (error);
 }
@@ -3772,6 +3797,8 @@
 	if (mp == NULL) {
 		ASSERT(error != 0);
 		mutex_exit(&connp->conn_lock);
+		ixa->ixa_cred = connp->conn_cred;	/* Restore */
+		ixa->ixa_cpid = connp->conn_cpid;
 		ixa_refrele(ixa);
 		BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
 		freemsg(mp);
@@ -3784,6 +3811,8 @@
 		if (mp == NULL) {
 			mutex_exit(&connp->conn_lock);
 			BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
+			ixa->ixa_cred = connp->conn_cred;	/* Restore */
+			ixa->ixa_cpid = connp->conn_cpid;
 			ixa_refrele(ixa);
 			return (EHOSTUNREACH);	/* IPsec policy failure */
 		}
@@ -3838,6 +3867,8 @@
 			/* FALLTHRU */
 		default:
 		failed:
+			ixa->ixa_cred = connp->conn_cred;	/* Restore */
+			ixa->ixa_cpid = connp->conn_cpid;
 			ixa_refrele(ixa);
 			BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
 			freemsg(mp);
@@ -3880,6 +3911,8 @@
 		mutex_exit(&connp->conn_lock);
 		break;
 	}
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	return (error);
 }
@@ -4595,12 +4628,15 @@
 		break;
 	}
 done:
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	return (error);
 
 ud_error:
-	if (ixa != NULL)
-		ixa_refrele(ixa);
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
+	ixa_refrele(ixa);
 
 	BUMP_MIB(&is->is_rawip_mib, rawipOutErrors);
 	freemsg(data_mp);
--- a/usr/src/uts/common/inet/ip/ip.c	Wed Feb 17 20:52:17 2010 -0500
+++ b/usr/src/uts/common/inet/ip/ip.c	Wed Feb 17 19:52:19 2010 -0800
@@ -6162,6 +6162,7 @@
 	 * connp->conn_cred is crfree()ed in ipcl_conn_destroy()
 	 */
 	connp->conn_cred = credp;
+	connp->conn_cpid = curproc->p_pid;
 	/* Cache things in ixa without an extra refhold */
 	connp->conn_ixa->ixa_cred = connp->conn_cred;
 	connp->conn_ixa->ixa_cpid = connp->conn_cpid;
--- a/usr/src/uts/common/inet/ip/ip_attr.c	Wed Feb 17 20:52:17 2010 -0500
+++ b/usr/src/uts/common/inet/ip/ip_attr.c	Wed Feb 17 19:52:19 2010 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1990 Mentat Inc. */
@@ -1073,15 +1073,15 @@
 	if (ixa->ixa_free_flags & IXA_FREE_TSL) {
 		ASSERT(ixa->ixa_tsl != NULL);
 		label_rele(ixa->ixa_tsl);
-		ixa->ixa_tsl = NULL;
 		ixa->ixa_free_flags &= ~IXA_FREE_TSL;
 	}
+	ixa->ixa_tsl = NULL;
 	if (ixa->ixa_free_flags & IXA_FREE_CRED) {
 		ASSERT(ixa->ixa_cred != NULL);
 		crfree(ixa->ixa_cred);
-		ixa->ixa_cred = NULL;
 		ixa->ixa_free_flags &= ~IXA_FREE_CRED;
 	}
+	ixa->ixa_cred = NULL;
 	ixa->ixa_src_preferences = 0;
 	ixa->ixa_ifindex = 0;
 	ixa->ixa_multicast_ifindex = 0;
--- a/usr/src/uts/common/inet/ip/ipclassifier.c	Wed Feb 17 20:52:17 2010 -0500
+++ b/usr/src/uts/common/inet/ip/ipclassifier.c	Wed Feb 17 19:52:19 2010 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -641,6 +641,7 @@
 	if (connp->conn_cred != NULL) {
 		crfree(connp->conn_cred);
 		connp->conn_cred = NULL;
+		/* ixa_cred done in ipcl_conn_cleanup below */
 	}
 
 	if (connp->conn_ht_iphc != NULL) {
--- a/usr/src/uts/common/inet/tcp/tcp.c	Wed Feb 17 20:52:17 2010 -0500
+++ b/usr/src/uts/common/inet/tcp/tcp.c	Wed Feb 17 19:52:19 2010 -0800
@@ -2412,6 +2412,7 @@
 	if (econnp->conn_cred != NULL)
 		crfree(econnp->conn_cred);
 	econnp->conn_cred = aconnp->conn_cred;
+	econnp->conn_ixa->ixa_cred = econnp->conn_cred;
 	aconnp->conn_cred = NULL;
 	econnp->conn_cpid = aconnp->conn_cpid;
 	ASSERT(econnp->conn_netstack == aconnp->conn_netstack);
@@ -6542,6 +6543,7 @@
 	 */
 	tcp_reinit_values(tcp);
 	ipcl_hash_remove(connp);
+	/* Note that ixa_cred gets cleared in ixa_cleanup */
 	ixa_cleanup(connp->conn_ixa);
 	tcp_ipsec_cleanup(tcp);
 
@@ -7882,6 +7884,10 @@
 	connp->conn_cpid = curproc->p_pid;
 	connp->conn_open_time = ddi_get_lbolt64();
 
+	/* Cache things in the ixa without any refhold */
+	connp->conn_ixa->ixa_cred = credp;
+	connp->conn_ixa->ixa_cpid = connp->conn_cpid;
+
 	connp->conn_zoneid = zoneid;
 	/* conn_allzones can not be set this early, hence no IPCL_ZONEID */
 	connp->conn_ixa->ixa_zoneid = zoneid;
--- a/usr/src/uts/common/inet/udp/udp.c	Wed Feb 17 20:52:17 2010 -0500
+++ b/usr/src/uts/common/inet/udp/udp.c	Wed Feb 17 19:52:19 2010 -0800
@@ -3128,6 +3128,8 @@
 	/* Get a copy of conn_xmit_ipp since the options might change it */
 	ipp = kmem_zalloc(sizeof (*ipp), KM_NOSLEEP);
 	if (ipp == NULL) {
+		ixa->ixa_cred = connp->conn_cred;	/* Restore */
+		ixa->ixa_cpid = connp->conn_cpid;
 		ixa_refrele(ixa);
 		BUMP_MIB(&us->us_udp_mib, udpOutErrors);
 		freemsg(mp);
@@ -3357,6 +3359,8 @@
 		break;
 	}
 done:
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	ip_pkt_free(ipp);
 	kmem_free(ipp, sizeof (*ipp));
@@ -3397,6 +3401,8 @@
 	if (mp == NULL) {
 		ASSERT(error != 0);
 		mutex_exit(&connp->conn_lock);
+		ixa->ixa_cred = connp->conn_cred;	/* Restore */
+		ixa->ixa_cpid = connp->conn_cpid;
 		ixa_refrele(ixa);
 		BUMP_MIB(&us->us_udp_mib, udpOutErrors);
 		freemsg(mp);
@@ -3452,6 +3458,8 @@
 			/* FALLTHRU */
 		default:
 		failed:
+			ixa->ixa_cred = connp->conn_cred;	/* Restore */
+			ixa->ixa_cpid = connp->conn_cpid;
 			ixa_refrele(ixa);
 			freemsg(mp);
 			BUMP_MIB(&us->us_udp_mib, udpOutErrors);
@@ -3483,6 +3491,8 @@
 		error = ENETUNREACH;
 		break;
 	}
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	return (error);
 }
@@ -3514,6 +3524,8 @@
 	if (mp == NULL) {
 		ASSERT(error != 0);
 		mutex_exit(&connp->conn_lock);
+		ixa->ixa_cred = connp->conn_cred;	/* Restore */
+		ixa->ixa_cpid = connp->conn_cpid;
 		ixa_refrele(ixa);
 		BUMP_MIB(&us->us_udp_mib, udpOutErrors);
 		freemsg(mp);
@@ -3569,6 +3581,8 @@
 			/* FALLTHRU */
 		default:
 		failed:
+			ixa->ixa_cred = connp->conn_cred;	/* Restore */
+			ixa->ixa_cpid = connp->conn_cpid;
 			ixa_refrele(ixa);
 			freemsg(mp);
 			BUMP_MIB(&us->us_udp_mib, udpOutErrors);
@@ -3612,6 +3626,8 @@
 		mutex_exit(&connp->conn_lock);
 		break;
 	}
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	return (error);
 }
@@ -4409,12 +4425,15 @@
 		mutex_exit(&connp->conn_lock);
 		break;
 	}
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
 	ixa_refrele(ixa);
 	return (error);
 
 ud_error:
-	if (ixa != NULL)
-		ixa_refrele(ixa);
+	ixa->ixa_cred = connp->conn_cred;	/* Restore */
+	ixa->ixa_cpid = connp->conn_cpid;
+	ixa_refrele(ixa);
 
 	freemsg(data_mp);
 	BUMP_MIB(&us->us_udp_mib, udpOutErrors);
@@ -6200,6 +6219,15 @@
 	}
 	mutex_exit(&udpf->uf_lock);
 
+	/*
+	 * We update our cred/cpid based on the caller of connect
+	 */
+	if (connp->conn_cred != cr) {
+		crhold(cr);
+		crfree(connp->conn_cred);
+		connp->conn_cred = cr;
+	}
+	connp->conn_cpid = pid;
 	ixa->ixa_cred = cr;
 	ixa->ixa_cpid = pid;
 	if (is_system_labeled()) {