PSARC 2007/670 db_credp update
6619593 Simplify and strengthen db_credp handling
6619596 Add getpeerucred() support to SCTP SOCK_STREAM
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
index 43b6805..d3036a7 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
@@ -32,7 +32,7 @@
  * $Id: smb_trantcp.c,v 1.39 2005/03/02 01:27:44 lindak Exp $
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -109,7 +109,7 @@
 
 	mlen = (sizeof (struct T_optmgmt_req) +
 	    sizeof (struct opthdr) + sizeof (int));
-	if (!(mp = allocb_wait(mlen, BPRI_LO, STR_NOSIG, &error)))
+	if (!(mp = allocb_cred_wait(mlen, STR_NOSIG, &error, CRED(), NOPID)))
 		return (error);
 
 	mp->b_datap->db_type = M_PROTO;
@@ -347,7 +347,7 @@
 	int error, fmode, mlen;
 
 	mlen = sizeof (struct T_discon_req);
-	if (!(mp = allocb_wait(mlen, BPRI_LO, STR_NOSIG, &error)))
+	if (!(mp = allocb_cred_wait(mlen, STR_NOSIG, &error, CRED(), NOPID)))
 		return (error);
 
 	mp->b_datap->db_type = M_PROTO;
diff --git a/usr/src/uts/common/fs/sockfs/sockcommon.h b/usr/src/uts/common/fs/sockfs/sockcommon.h
index c4dbecb..ef903bb 100644
--- a/usr/src/uts/common/fs/sockfs/sockcommon.h
+++ b/usr/src/uts/common/fs/sockfs/sockcommon.h
@@ -20,15 +20,13 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef	_SOCKCOMMON_H_
 #define	_SOCKCOMMON_H_
 
-#pragma ident	"@(#)sockcommon.h	1.1	07/06/14 SMI"
-
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -185,7 +183,8 @@
     rval_t *, int);
 extern void	so_enqueue_msg(struct sonode *, mblk_t *, size_t);
 
-extern mblk_t	*socopyinuio(uio_t *, ssize_t, size_t, ssize_t, size_t, int *);
+extern mblk_t	*socopyinuio(uio_t *, ssize_t, size_t, ssize_t, size_t, int *,
+    cred_t *);
 extern mblk_t 	*socopyoutuio(mblk_t *, struct uio *, ssize_t, int *);
 
 extern boolean_t somsghasdata(mblk_t *);
diff --git a/usr/src/uts/common/fs/sockfs/sockcommon_sops.c b/usr/src/uts/common/fs/sockfs/sockcommon_sops.c
index fb24093..5fd346b 100644
--- a/usr/src/uts/common/fs/sockfs/sockcommon_sops.c
+++ b/usr/src/uts/common/fs/sockfs/sockcommon_sops.c
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)sockcommon_sops.c	1.1	07/06/14 SMI"
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -273,7 +271,7 @@
 		bind_req.ADDR_length = namelen;
 		bind_req.ADDR_offset = (t_scalar_t)sizeof (bind_req);
 		mp = soallocproto2(&bind_req, sizeof (bind_req),
-		    name, namelen, 0, _ALLOC_SLEEP);
+		    name, namelen, 0, _ALLOC_SLEEP, cr);
 
 		type = kssl_check_proxy(mp, so, &ent);
 		freemsg(mp);
@@ -472,7 +470,8 @@
 			    so->so_proto_props.sopp_maxpsz,
 			    so->so_proto_props.sopp_wroff,
 			    so->so_proto_props.sopp_maxblk,
-			    so->so_proto_props.sopp_tail, &error)) == NULL) {
+			    so->so_proto_props.sopp_tail, &error,
+			    cr)) == NULL) {
 				break;
 			}
 			ASSERT(uiop->uio_resid >= 0);
diff --git a/usr/src/uts/common/fs/sockfs/sockcommon_subr.c b/usr/src/uts/common/fs/sockfs/sockcommon_subr.c
index 8988286..c8ff2be 100644
--- a/usr/src/uts/common/fs/sockfs/sockcommon_subr.c
+++ b/usr/src/uts/common/fs/sockfs/sockcommon_subr.c
@@ -468,7 +468,7 @@
 /* Copy userdata into a new mblk_t */
 mblk_t *
 socopyinuio(uio_t *uiop, ssize_t iosize, size_t wroff, ssize_t maxblk,
-    size_t tail_len, int *errorp)
+    size_t tail_len, int *errorp, cred_t *cr)
 {
 	mblk_t	*head = NULL, **tail = &head;
 
@@ -496,8 +496,12 @@
 
 		blocksize = MIN(iosize, maxblk);
 		ASSERT(blocksize >= 0);
-		if ((mp = allocb(wroff + blocksize + tail_len,
-		    BPRI_MED)) == NULL) {
+		if (is_system_labeled())
+			mp = allocb_cred(wroff + blocksize + tail_len,
+			    cr, curproc->p_pid);
+		else
+			mp = allocb(wroff + blocksize + tail_len, BPRI_MED);
+		if (mp == NULL) {
 			*errorp = ENOMEM;
 			return (head);
 		}
diff --git a/usr/src/uts/common/fs/sockfs/sockstr.c b/usr/src/uts/common/fs/sockfs/sockstr.c
index 71c8d4c..b05b60e 100644
--- a/usr/src/uts/common/fs/sockfs/sockstr.c
+++ b/usr/src/uts/common/fs/sockfs/sockstr.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -194,13 +194,25 @@
 				mblk_t	*newmp;
 				size_t	length;
 				cred_t	*cr;
+				pid_t	cpid;
+				int error;	/* Dummy - error not returned */
 
 				/*
 				 * Copy the message block because it is used
 				 * elsewhere, too.
+				 * Can't use copyb since we want to wait
+				 * yet allow for EINTR.
 				 */
-				length = MBLKL(mp);
-				newmp = soallocproto(length, _ALLOC_INTR);
+				/* Round up size for reuse */
+				length = MAX(MBLKL(mp), 64);
+				cr = msg_getcred(mp, &cpid);
+				if (cr != NULL) {
+					newmp = allocb_cred_wait(length, 0,
+					    &error, cr, cpid);
+				} else {
+					newmp = allocb_wait(length, 0, 0,
+					    &error);
+				}
 				if (newmp == NULL) {
 					error = EINTR;
 					goto exit;
@@ -208,10 +220,6 @@
 				bcopy(mp->b_rptr, newmp->b_wptr, length);
 				newmp->b_wptr += length;
 				newmp->b_next = mp->b_next;
-				cr = DB_CRED(mp);
-				if (cr != NULL)
-					mblk_setcred(newmp, cr);
-				DB_CPID(newmp) = DB_CPID(mp);
 
 				/*
 				 * Link the new message block into the queue
@@ -395,7 +403,7 @@
 	sotpi_info_t *sti = SOTOTPI(so);
 
 	/* Preallocate an unbind_req message */
-	mp = soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP);
+	mp = soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP, CRED());
 	mutex_enter(&so->so_lock);
 	sti->sti_unbind_mp = mp;
 #ifdef DEBUG
@@ -634,7 +642,7 @@
 	tir.PRIM_type = T_INFO_REQ;
 	mp = soallocproto1(&tir, sizeof (tir),
 	    sizeof (struct T_info_req) + sizeof (struct T_info_ack),
-	    _ALLOC_INTR);
+	    _ALLOC_INTR, CRED());
 	if (mp == NULL) {
 		eprintsoline(so, ENOBUFS);
 		return (ENOBUFS);
@@ -697,7 +705,7 @@
 	tcr.CAP_bits1 = cap_bits1;
 	mp = soallocproto1(&tcr, sizeof (tcr),
 	    sizeof (struct T_capability_req) + sizeof (struct T_capability_ack),
-	    _ALLOC_INTR);
+	    _ALLOC_INTR, CRED());
 	if (mp == NULL) {
 		eprintsoline(so, ENOBUFS);
 		return (ENOBUFS);
@@ -2264,8 +2272,7 @@
 
 		if (so->so_peercred != NULL)
 			crfree(so->so_peercred);
-		so->so_peercred = DB_CRED(mp);
-		so->so_cpid = DB_CPID(mp);
+		so->so_peercred = msg_getcred(mp, &so->so_cpid);
 		if (so->so_peercred != NULL)
 			crhold(so->so_peercred);
 
diff --git a/usr/src/uts/common/fs/sockfs/socksubr.c b/usr/src/uts/common/fs/sockfs/socksubr.c
index b82adb1..eee61f7 100644
--- a/usr/src/uts/common/fs/sockfs/socksubr.c
+++ b/usr/src/uts/common/fs/sockfs/socksubr.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1357,23 +1357,38 @@
  *	_ALLOC_SLEEP	sleep forever. Don't return NULL.
  */
 mblk_t *
-soallocproto(size_t size, int sleepflg)
+soallocproto(size_t size, int sleepflg, cred_t *cr)
 {
 	mblk_t	*mp;
 
 	/* Round up size for reuse */
 	size = MAX(size, 64);
-	mp = allocb(size, BPRI_MED);
+	if (cr != NULL)
+		mp = allocb_cred(size, cr, curproc->p_pid);
+	else
+		mp = allocb(size, BPRI_MED);
+
 	if (mp == NULL) {
 		int error;	/* Dummy - error not returned to caller */
 
 		switch (sleepflg) {
 		case _ALLOC_SLEEP:
-			mp = allocb_wait(size, BPRI_MED, STR_NOSIG, &error);
+			if (cr != NULL) {
+				mp = allocb_cred_wait(size, STR_NOSIG, &error,
+				    cr, curproc->p_pid);
+			} else {
+				mp = allocb_wait(size, BPRI_MED, STR_NOSIG,
+				    &error);
+			}
 			ASSERT(mp);
 			break;
 		case _ALLOC_INTR:
-			mp = allocb_wait(size, BPRI_MED, 0, &error);
+			if (cr != NULL) {
+				mp = allocb_cred_wait(size, 0, &error, cr,
+				    curproc->p_pid);
+			} else {
+				mp = allocb_wait(size, BPRI_MED, 0, &error);
+			}
 			if (mp == NULL) {
 				/* Caught signal while sleeping for memory */
 				eprintline(ENOBUFS);
@@ -1398,7 +1413,8 @@
  * This results in a bzero'ed chunk being placed the message.
  */
 mblk_t *
-soallocproto1(const void *buf, ssize_t len, ssize_t size, int sleepflg)
+soallocproto1(const void *buf, ssize_t len, ssize_t size, int sleepflg,
+    cred_t *cr)
 {
 	mblk_t	*mp;
 
@@ -1408,7 +1424,7 @@
 	ASSERT(size >= len);
 	/* Round up size for reuse */
 	size = MAX(size, 64);
-	mp = soallocproto(size, sleepflg);
+	mp = soallocproto(size, sleepflg, cr);
 	if (mp == NULL)
 		return (NULL);
 	mp->b_datap->db_type = M_PROTO;
@@ -1453,7 +1469,7 @@
  */
 mblk_t *
 soallocproto2(const void *buf1, ssize_t len1, const void *buf2, ssize_t len2,
-    ssize_t size, int sleepflg)
+    ssize_t size, int sleepflg, cred_t *cr)
 {
 	mblk_t *mp;
 
@@ -1461,7 +1477,7 @@
 		size = len1 + len2;
 	ASSERT(size >= len1 + len2);
 
-	mp = soallocproto1(buf1, len1, size, sleepflg);
+	mp = soallocproto1(buf1, len1, size, sleepflg, cr);
 	if (mp)
 		soappendmsg(mp, buf2, len2);
 	return (mp);
@@ -1475,7 +1491,7 @@
  */
 mblk_t *
 soallocproto3(const void *buf1, ssize_t len1, const void *buf2, ssize_t len2,
-    const void *buf3, ssize_t len3, ssize_t size, int sleepflg)
+    const void *buf3, ssize_t len3, ssize_t size, int sleepflg, cred_t *cr)
 {
 	mblk_t *mp;
 
@@ -1483,7 +1499,7 @@
 		size = len1 + len2 +len3;
 	ASSERT(size >= len1 + len2 + len3);
 
-	mp = soallocproto1(buf1, len1, size, sleepflg);
+	mp = soallocproto1(buf1, len1, size, sleepflg, cr);
 	if (mp != NULL) {
 		soappendmsg(mp, buf2, len2);
 		soappendmsg(mp, buf3, len3);
diff --git a/usr/src/uts/common/fs/sockfs/socksyscalls.c b/usr/src/uts/common/fs/sockfs/socksyscalls.c
index 4d0929f..b708469 100644
--- a/usr/src/uts/common/fs/sockfs/socksyscalls.c
+++ b/usr/src/uts/common/fs/sockfs/socksyscalls.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1945,7 +1945,13 @@
 		    SOTOTPI(so)->sti_kssl_ctx != NULL)
 			iosize = (int)MIN(iosize, maxblk);
 
-		if ((mp = allocb(iosize + extra, BPRI_MED)) == NULL) {
+		if (is_system_labeled()) {
+			mp = allocb_cred(iosize + extra, CRED(),
+			    curproc->p_pid);
+		} else {
+			mp = allocb(iosize + extra, BPRI_MED);
+		}
+		if (mp == NULL) {
 			error = EAGAIN;
 			break;
 		}
@@ -2400,7 +2406,13 @@
 		    SOTOTPI(so)->sti_kssl_ctx != NULL)
 			iosize = (int)MIN(iosize, maxblk);
 
-		if ((mp = allocb(iosize + extra, BPRI_MED)) == NULL) {
+		if (is_system_labeled()) {
+			mp = allocb_cred(iosize + extra, CRED(),
+			    curproc->p_pid);
+		} else {
+			mp = allocb(iosize + extra, BPRI_MED);
+		}
+		if (mp == NULL) {
 			error = EAGAIN;
 			break;
 		}
diff --git a/usr/src/uts/common/fs/sockfs/socktpi.c b/usr/src/uts/common/fs/sockfs/socktpi.c
index 6da1594..d801c1e 100644
--- a/usr/src/uts/common/fs/sockfs/socktpi.c
+++ b/usr/src/uts/common/fs/sockfs/socktpi.c
@@ -682,7 +682,8 @@
 		dprintso(so, 1, ("sobind: allocating unbind_req\n"));
 		/* NOTE: holding so_lock while sleeping */
 		sti->sti_unbind_mp =
-		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP);
+		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP,
+		    cr);
 	}
 
 	if (flags & _SOBIND_REBIND) {
@@ -1094,7 +1095,7 @@
 	bind_req.CONIND_number = backlog;
 	/* NOTE: holding so_lock while sleeping */
 	mp = soallocproto2(&bind_req, sizeof (bind_req),
-	    addr, addrlen, 0, _ALLOC_SLEEP);
+	    addr, addrlen, 0, _ALLOC_SLEEP, cr);
 	sti->sti_laddr_valid = 0;
 
 	/* Done using sti_laddr_sa - can drop the lock */
@@ -1478,7 +1479,7 @@
 
 	unbind_req.PRIM_type = T_UNBIND_REQ;
 	mp = soallocproto1(&unbind_req, sizeof (unbind_req),
-	    0, _ALLOC_SLEEP);
+	    0, _ALLOC_SLEEP, CRED());
 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
 	mutex_enter(&so->so_lock);
@@ -1663,7 +1664,7 @@
 	discon_req.PRIM_type = T_DISCON_REQ;
 	discon_req.SEQ_number = seqno;
 	mp = soallocproto1(&discon_req, sizeof (discon_req),
-	    0, _ALLOC_SLEEP);
+	    0, _ALLOC_SLEEP, CRED());
 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
 	mutex_enter(&so->so_lock);
@@ -1781,7 +1782,7 @@
 				 */
 				sti->sti_direct = 0;
 				(void) strioctl(SOTOV(so), _SIOCSOCKFALLBACK,
-				    0, 0, K_TO_K, CRED(), &rval);
+				    0, 0, K_TO_K, cr, &rval);
 			}
 			opt = NULL;
 			optlen = 0;
@@ -1881,19 +1882,25 @@
 	bcopy(src, nsti->sti_faddr_sa, srclen);
 	nsti->sti_faddr_valid = 1;
 
+	/*
+	 * Record so_peercred and so_cpid from a cred in the T_CONN_IND.
+	 * Send down a T_CONN_RES without a cred.
+	 */
 	if ((DB_REF(mp) > 1) || MBLKSIZE(mp) <
 	    (sizeof (struct T_conn_res) + sizeof (intptr_t))) {
-		cred_t *cr;
+		cred_t	*cr;
+		pid_t	cpid;
 
-		if ((cr = DB_CRED(mp)) != NULL) {
+		cr = msg_getcred(mp, &cpid);
+		if (cr != NULL) {
 			crhold(cr);
 			nso->so_peercred = cr;
-			nso->so_cpid = DB_CPID(mp);
+			nso->so_cpid = cpid;
 		}
 		freemsg(mp);
 
 		mp = soallocproto1(NULL, sizeof (struct T_conn_res) +
-		    sizeof (intptr_t), 0, _ALLOC_INTR);
+		    sizeof (intptr_t), 0, _ALLOC_INTR, NULL);
 		if (mp == NULL) {
 			/*
 			 * Accept can not fail with ENOBUFS.
@@ -1905,9 +1912,12 @@
 		}
 		conn_res = (struct T_conn_res *)mp->b_rptr;
 	} else {
-		nso->so_peercred = DB_CRED(mp);
-		nso->so_cpid = DB_CPID(mp);
-		DB_CRED(mp) = NULL;
+		/*
+		 * For efficency reasons we use msg_extractcred; no crhold
+		 * needed since db_credp is cleared (i.e., we move the cred
+		 * from the message to so_peercred.
+		 */
+		nso->so_peercred = msg_extractcred(mp, &nso->so_cpid);
 
 		mp->b_rptr = DB_BASE(mp);
 		conn_res = (struct T_conn_res *)mp->b_rptr;
@@ -1955,7 +1965,7 @@
 	nsti->sti_faddr_noxlate = sti->sti_faddr_noxlate;
 
 	if (nso->so_pgrp != 0) {
-		if ((error = so_set_events(nso, nvp, CRED())) != 0) {
+		if ((error = so_set_events(nso, nvp, cr)) != 0) {
 			eprintsoline(nso, error);
 			error = 0;
 			nso->so_pgrp = 0;
@@ -2059,7 +2069,7 @@
 				 */
 				mutex_exit(&nso->so_lock);
 				(void) VOP_CLOSE(nvp, 0, 1, (offset_t)0,
-				    CRED(), NULL);
+				    cr, NULL);
 				VN_RELE(nvp);
 				goto again;
 			}
@@ -2079,7 +2089,7 @@
 			int	rval;
 
 			if ((error = strioctl(SOTOV(nso), _SIOCSOCKFALLBACK,
-			    0, 0, K_TO_K, CRED(), &rval)) != 0) {
+			    0, 0, K_TO_K, cr, &rval)) != 0) {
 				mutex_enter(&so->so_lock);
 				so_lock_single(so);
 				eprintsoline(so, error);
@@ -2207,7 +2217,7 @@
 pr_disc_vp_unl:
 	eprintsoline(so, error);
 disconnect_vp_unlocked:
-	(void) VOP_CLOSE(nvp, 0, 1, 0, CRED(), NULL);
+	(void) VOP_CLOSE(nvp, 0, 1, 0, cr, NULL);
 	VN_RELE(nvp);
 disconnect_unlocked:
 	(void) sodisconnect(so, SEQ_number, 0);
@@ -2219,7 +2229,7 @@
 	(void) sodisconnect(so, SEQ_number, _SODISCONNECT_LOCK_HELD);
 	so_unlock_single(so, SOLOCKED);
 	mutex_exit(&so->so_lock);
-	(void) VOP_CLOSE(nvp, 0, 1, 0, CRED(), NULL);
+	(void) VOP_CLOSE(nvp, 0, 1, 0, cr, NULL);
 	VN_RELE(nvp);
 	return (error);
 
@@ -2268,7 +2278,8 @@
 	 * exceed sti_faddr_maxlen).
 	 */
 	mp = soallocproto(sizeof (struct T_conn_req) +
-	    2 * sti->sti_faddr_maxlen + sizeof (struct T_opthdr), _ALLOC_INTR);
+	    2 * sti->sti_faddr_maxlen + sizeof (struct T_opthdr), _ALLOC_INTR,
+	    cr);
 	if (mp == NULL) {
 		/*
 		 * Connect can not fail with ENOBUFS. A signal was
@@ -2296,7 +2307,7 @@
 		dprintso(so, 1, ("sotpi_connect: allocating unbind_req\n"));
 		/* NOTE: holding so_lock while sleeping */
 		sti->sti_unbind_mp =
-		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_INTR);
+		    soallocproto(sizeof (struct T_unbind_req), _ALLOC_INTR, cr);
 		if (sti->sti_unbind_mp == NULL) {
 			error = EINTR;
 			goto done;
@@ -2820,7 +2831,7 @@
 
 		mutex_exit(&so->so_lock);
 		mp = soallocproto1(&ordrel_req, sizeof (ordrel_req),
-		    0, _ALLOC_SLEEP);
+		    0, _ALLOC_SLEEP, cr);
 		/*
 		 * Send down the T_ORDREL_REQ even if there is flow control.
 		 * This prevents shutdown from blocking.
@@ -2897,7 +2908,7 @@
 
 		/* NOTE: holding so_lock while sleeping */
 		mp = soallocproto2(&tdr, sizeof (tdr),
-		    &toh, sizeof (toh), 0, _ALLOC_SLEEP);
+		    &toh, sizeof (toh), 0, _ALLOC_SLEEP, CRED());
 	} else {
 		struct T_unitdata_req	tudr;
 		void			*addr;
@@ -2963,7 +2974,7 @@
 			size = tudr.OPT_offset + tudr.OPT_length;
 			/* NOTE: holding so_lock while sleeping */
 			mp = soallocproto2(&tudr, sizeof (tudr),
-			    addr, addrlen, size, _ALLOC_SLEEP);
+			    addr, addrlen, size, _ALLOC_SLEEP, CRED());
 			mp->b_wptr += (_TPI_ALIGN_TOPT(addrlen) - addrlen);
 			soappendmsg(mp, &toh, sizeof (toh));
 		} else {
@@ -2986,7 +2997,7 @@
 
 			/* NOTE: holding so_lock while sleeping */
 			mp = soallocproto2(&tudr, sizeof (tudr),
-			    addr, addrlen, size, _ALLOC_SLEEP);
+			    addr, addrlen, size, _ALLOC_SLEEP, CRED());
 			mp->b_wptr += _TPI_ALIGN_TOPT(addrlen) - addrlen;
 			soappendmsg(mp, &toh, sizeof (toh));
 			soappendmsg(mp, &toh2, sizeof (toh2));
@@ -3830,7 +3841,7 @@
 			return (error);
 		mp = fdbuf_allocmsg(size, fdbuf);
 	} else {
-		mp = soallocproto(size, _ALLOC_INTR);
+		mp = soallocproto(size, _ALLOC_INTR, CRED());
 		if (mp == NULL) {
 			/*
 			 * Caught a signal waiting for memory.
@@ -3963,7 +3974,7 @@
 				return (error);
 			mp = fdbuf_allocmsg(size, fdbuf);
 		} else {
-			mp = soallocproto(size, _ALLOC_INTR);
+			mp = soallocproto(size, _ALLOC_INTR, CRED());
 			if (mp == NULL) {
 				/*
 				 * Caught a signal waiting for memory.
@@ -4108,7 +4119,7 @@
 		tudr.OPT_offset = 0;
 
 		mp = soallocproto2(&tudr, sizeof (tudr),
-		    addr, addrlen, 0, _ALLOC_INTR);
+		    addr, addrlen, 0, _ALLOC_INTR, CRED());
 		if (mp == NULL) {
 			/*
 			 * Caught a signal waiting for memory.
@@ -4137,7 +4148,7 @@
 
 		size = tudr.OPT_offset + tudr.OPT_length;
 		mp = soallocproto2(&tudr, sizeof (tudr),
-		    addr, addrlen, size, _ALLOC_INTR);
+		    addr, addrlen, size, _ALLOC_INTR, CRED());
 		if (mp == NULL) {
 			/*
 			 * Caught a signal waiting for memory.
@@ -4211,7 +4222,7 @@
 		}
 		dprintso(so, 1, ("sosend_svc: sending 0x%x %d, %ld bytes\n",
 		    prim, tdr.MORE_flag, iosize));
-		mp = soallocproto1(&tdr, sizeof (tdr), 0, _ALLOC_INTR);
+		mp = soallocproto1(&tdr, sizeof (tdr), 0, _ALLOC_INTR, CRED());
 		if (mp == NULL) {
 			/*
 			 * Caught a signal waiting for memory.
@@ -4711,7 +4722,7 @@
 		tudr.OPT_offset = 0;
 
 		mp = soallocproto2(&tudr, sizeof (tudr), addr, addrlen, 0,
-		    _ALLOC_INTR);
+		    _ALLOC_INTR, CRED());
 		if (mp == NULL) {
 			/*
 			 * Caught a signal waiting for memory.
@@ -5426,7 +5437,7 @@
 	oh.len = maxlen;
 
 	mp = soallocproto3(&optmgmt_req, sizeof (optmgmt_req),
-	    &oh, sizeof (oh), NULL, maxlen, 0, _ALLOC_SLEEP);
+	    &oh, sizeof (oh), NULL, maxlen, 0, _ALLOC_SLEEP, cr);
 	/* Let option management work in the presence of data flow control */
 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
@@ -5733,7 +5744,7 @@
 	oh.len = optlen;
 
 	mp = soallocproto3(&optmgmt_req, sizeof (optmgmt_req),
-	    &oh, sizeof (oh), optval, optlen, 0, _ALLOC_SLEEP);
+	    &oh, sizeof (oh), optval, optlen, 0, _ALLOC_SLEEP, cr);
 	/* Let option management work in the presence of data flow control */
 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
 	    MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
@@ -6297,7 +6308,7 @@
 			mutex_exit(&so->so_lock);
 
 			error = strioctl(vp, _SIOCSOCKFALLBACK, 0, 0, K_TO_K,
-			    CRED(), rvalp);
+			    cr, rvalp);
 
 			mutex_enter(&so->so_lock);
 			if (error == 0)
diff --git a/usr/src/uts/common/fs/sockfs/socktpi_impl.h b/usr/src/uts/common/fs/sockfs/socktpi_impl.h
index aa0b04b..6a515be 100644
--- a/usr/src/uts/common/fs/sockfs/socktpi_impl.h
+++ b/usr/src/uts/common/fs/sockfs/socktpi_impl.h
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -71,13 +71,13 @@
 extern void	so_drain_discon_ind(struct sonode *);
 extern void	so_flush_discon_ind(struct sonode *);
 
-extern mblk_t	*soallocproto(size_t, int);
-extern mblk_t	*soallocproto1(const void *, ssize_t, ssize_t, int);
+extern mblk_t	*soallocproto(size_t, int, cred_t *);
+extern mblk_t	*soallocproto1(const void *, ssize_t, ssize_t, int, cred_t *);
 extern void	soappendmsg(mblk_t *, const void *, ssize_t);
 extern mblk_t	*soallocproto2(const void *, ssize_t, const void *, ssize_t,
-			ssize_t, int);
+			ssize_t, int, cred_t *);
 extern mblk_t	*soallocproto3(const void *, ssize_t, const void *, ssize_t,
-			const void *, ssize_t, ssize_t, int);
+			const void *, ssize_t, ssize_t, int, cred_t *);
 
 extern int	so_set_asyncsigs(vnode_t *, pid_t, int, int, cred_t *);
 extern int	so_flip_async(struct sonode *, vnode_t *, int, cred_t *);
diff --git a/usr/src/uts/common/inet/arp/arp.c b/usr/src/uts/common/inet/arp/arp.c
index 06c499c..f2bfb50 100644
--- a/usr/src/uts/common/inet/arp/arp.c
+++ b/usr/src/uts/common/inet/arp/arp.c
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/stropts.h>
+#include <sys/strsubr.h>
 #include <sys/errno.h>
 #include <sys/strlog.h>
 #include <sys/dlpi.h>
@@ -1259,6 +1260,11 @@
 		mp = mp->b_cont;
 		if (!mp)
 			return (ENOENT);
+	} else {
+		cr = msg_getcred(mp, NULL);
+		/* For initial messages beteen IP and ARP, cr can be NULL */
+		if (cr == NULL)
+			cr = ((ar_t *)q->q_ptr)->ar_credp;
 	}
 	len = MBLKL(mp);
 	if (len < sizeof (uint32_t) || !OK_32PTR(mp->b_rptr))
@@ -1282,9 +1288,6 @@
 	if (arct->arct_priv_req != OP_NP) {
 		int error;
 
-		if (cr == NULL)
-			cr = DB_CREDDEF(mp_orig, ((ar_t *)q->q_ptr)->ar_credp);
-
 		if ((error = secpolicy_ip(cr, arct->arct_priv_req,
 		    B_FALSE)) != 0)
 			return (error);
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index 4159528..ff82081 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -294,11 +294,6 @@
 	CONN_DEC_REF(connp);					\
 }
 
-/* Get the credential of an IP queue of unknown type */
-#define	GET_QUEUE_CRED(wq)						\
-	((wq)->q_next ? (((ill_t *)(wq)->q_ptr)->ill_credp) \
-	    : ((Q_TO_CONN((wq)))->conn_cred))
-
 /*
  * Flags for the various ip_fanout_* routines.
  */
@@ -3224,6 +3219,7 @@
 extern void	icmp_unreachable(queue_t *, mblk_t *, uint8_t, zoneid_t,
     ip_stack_t *);
 extern mblk_t	*ip_add_info(mblk_t *, ill_t *, uint_t, zoneid_t, ip_stack_t *);
+cred_t		*ip_best_cred(mblk_t *, conn_t *);
 extern mblk_t	*ip_bind_v4(queue_t *, mblk_t *, conn_t *);
 extern	boolean_t ip_bind_ipsec_policy_set(conn_t *, mblk_t *);
 extern	int	ip_bind_laddr_v4(conn_t *, mblk_t **, uint8_t, ipaddr_t,
@@ -3231,9 +3227,10 @@
 extern	int	ip_proto_bind_laddr_v4(conn_t *, mblk_t **, uint8_t, ipaddr_t,
     uint16_t, boolean_t);
 extern	int	ip_proto_bind_connected_v4(conn_t *, mblk_t **,
-    uint8_t, ipaddr_t *, uint16_t, ipaddr_t, uint16_t, boolean_t, boolean_t);
+    uint8_t, ipaddr_t *, uint16_t, ipaddr_t, uint16_t, boolean_t, boolean_t,
+    cred_t *);
 extern	int	ip_bind_connected_v4(conn_t *, mblk_t **, uint8_t, ipaddr_t *,
-    uint16_t, ipaddr_t, uint16_t, boolean_t, boolean_t);
+    uint16_t, ipaddr_t, uint16_t, boolean_t, boolean_t, cred_t *);
 extern uint_t	ip_cksum(mblk_t *, int, uint32_t);
 extern int	ip_close(queue_t *, int);
 extern uint16_t	ip_csum_hdr(ipha_t *);
diff --git a/usr/src/uts/common/inet/ip/icmp.c b/usr/src/uts/common/inet/ip/icmp.c
index b381983..e26254a 100644
--- a/usr/src/uts/common/inet/ip/icmp.c
+++ b/usr/src/uts/common/inet/ip/icmp.c
@@ -141,6 +141,7 @@
 		    cred_t *cr);
 static void	icmp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err);
 static void	icmp_tpi_unbind(queue_t *q, mblk_t *mp);
+static int	icmp_update_label(icmp_t *icmp, mblk_t *mp, ipaddr_t dst);
 static void	icmp_wput(queue_t *q, mblk_t *mp);
 static void	icmp_wput_fallback(queue_t *q, mblk_t *mp);
 static int	raw_ip_send_data_v6(queue_t *q, conn_t *connp, mblk_t *mp,
@@ -248,7 +249,7 @@
 
 static int rawip_do_bind(conn_t *connp, struct sockaddr *sa, socklen_t len);
 static int rawip_do_connect(conn_t *connp, const struct sockaddr *sa,
-    socklen_t len);
+    socklen_t len, cred_t *cr);
 static void rawip_post_ip_bind_connect(icmp_t *icmp, mblk_t *ire_mp, int error);
 
 /*
@@ -270,6 +271,21 @@
 	icmp_t		*icmp;
 	conn_t	*connp = Q_TO_CONN(q);
 	mblk_t *mp1;
+	cred_t *cr;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		icmp_err_ack(q, mp, TSYSERR, EINVAL);
+		return;
+	}
 
 	icmp = connp->conn_icmp;
 	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) {
@@ -579,6 +595,21 @@
 	struct sockaddr *sa;
 	socklen_t len;
 	int error;
+	cred_t *cr;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		icmp_err_ack(q, mp, TSYSERR, EINVAL);
+		return;
+	}
 
 	icmp = connp->conn_icmp;
 	tcr = (struct T_conn_req *)mp->b_rptr;
@@ -615,7 +646,7 @@
 		return;
 	}
 
-	error = rawip_do_connect(connp, sa, len);
+	error = rawip_do_connect(connp, sa, len, cr);
 	if (error != 0) {
 		if (error < 0) {
 			icmp_err_ack(q, mp, -error, 0);
@@ -659,7 +690,8 @@
 }
 
 static int
-rawip_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len)
+rawip_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
+    cred_t *cr)
 {
 	icmp_t	*icmp;
 	sin_t	*sin;
@@ -779,12 +811,12 @@
 		error = ip_proto_bind_connected_v6(connp, &ire_mp,
 		    icmp->icmp_proto, &icmp->icmp_v6src, 0,
 		    &icmp->icmp_v6dst.sin6_addr,
-		    NULL, sin6->sin6_port, B_TRUE, B_TRUE);
+		    NULL, sin6->sin6_port, B_TRUE, B_TRUE, cr);
 	} else {
 		error = ip_proto_bind_connected_v4(connp, &ire_mp,
 		    icmp->icmp_proto, &V4_PART_OF_V6(icmp->icmp_v6src), 0,
 		    V4_PART_OF_V6(icmp->icmp_v6dst.sin6_addr), sin->sin_port,
-		    B_TRUE, B_TRUE);
+		    B_TRUE, B_TRUE, cr);
 	}
 	rawip_post_ip_bind_connect(icmp, ire_mp, error);
 	return (error);
@@ -4370,7 +4402,6 @@
 		}
 	}
 
-	mblk_setcred(mp, connp->conn_cred);
 	ip_output_options(connp, mp, q, IP_WPUT, &optinfo);
 	return (0);
 }
@@ -4381,9 +4412,21 @@
 	int err;
 	uchar_t opt_storage[IP_MAX_OPT_LENGTH];
 	icmp_stack_t		*is = icmp->icmp_is;
-	conn_t	*connp = icmp->icmp_connp;
+	conn_t			*connp = icmp->icmp_connp;
+	cred_t			*cr;
 
-	err = tsol_compute_label(DB_CREDDEF(mp, connp->conn_cred), dst,
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this message, hence we ASSERT.
+	 * On production kernels we return an error to be robust against
+	 * random streams modules sitting on top of us.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL)
+		return (EINVAL);
+
+	err = tsol_compute_label(cr, dst,
 	    opt_storage, connp->conn_mac_exempt,
 	    is->is_netstack->netstack_ip);
 	if (err == 0) {
@@ -4740,7 +4783,6 @@
 	}
 
 	BUMP_MIB(&is->is_rawip_mib, rawipOutDatagrams);
-	mblk_setcred(mp, connp->conn_cred);
 	ip_output_options(connp, mp, q, IP_WPUT, &optinfo);
 	return (0);
 }
@@ -4751,9 +4793,21 @@
 	int err;
 	uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
 	icmp_stack_t		*is = icmp->icmp_is;
-	conn_t	*connp = icmp->icmp_connp;
+	conn_t			*connp = icmp->icmp_connp;
+	cred_t			*cr;
 
-	err = tsol_compute_label_v6(DB_CREDDEF(mp, connp->conn_cred), dst,
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this message, hence we ASSERT.
+	 * On production kernels we return an error to be robust against
+	 * random streams modules sitting on top of us.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL)
+		return (EINVAL);
+
+	err = tsol_compute_label_v6(cr, dst,
 	    opt_storage, connp->conn_mac_exempt,
 	    is->is_netstack->netstack_ip);
 	if (err == 0) {
@@ -5331,8 +5385,6 @@
 	icmp_stack_t *is = icmp->icmp_is;
 	cred_t *cr;
 
-	cr = DB_CREDDEF(mp, connp->conn_cred);
-
 	switch (mp->b_datap->db_type) {
 	case M_PROTO:
 	case M_PCPROTO:
@@ -5374,6 +5426,20 @@
 			return;
 
 		case T_SVR4_OPTMGMT_REQ:
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				icmp_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
+
 			if (!snmpcom_req(q, mp, icmp_snmp_set, ip_snmp_get,
 			    cr)) {
 				/* Only IP can return anything meaningful */
@@ -5383,6 +5449,19 @@
 			return;
 
 		case T_OPTMGMT_REQ:
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				icmp_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
 			/* Only IP can return anything meaningful */
 			(void) tpi_optcom_req(q, mp, cr, &icmp_opt_obj, B_TRUE);
 			return;
@@ -5568,7 +5647,6 @@
 icmp_unitdata_opt_process(queue_t *q, mblk_t *mp, int *errorp,
     void *thisdg_attrs)
 {
-	conn_t	*connp = Q_TO_CONN(q);
 	struct T_unitdata_req *udreqp;
 	int is_absreq_failure;
 	cred_t *cr;
@@ -5576,7 +5654,17 @@
 	udreqp = (struct T_unitdata_req *)mp->b_rptr;
 	*errorp = 0;
 
-	cr = DB_CREDDEF(mp, connp->conn_cred);
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL)
+		return (-1);
 
 	*errorp = tpi_optcom_buf(q, mp, &udreqp->OPT_length,
 	    udreqp->OPT_offset, cr, &icmp_opt_obj,
@@ -5747,6 +5835,9 @@
 	conn_t  *connp = (conn_t *)proto_handle;
 	int error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	/* Binding to a NULL address really means unbind */
 	if (sa == NULL)
 		error = rawip_do_unbind(connp);
@@ -5820,6 +5911,9 @@
 	int	error;
 	boolean_t did_bind = B_FALSE;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (sa == NULL) {
 		/*
 		 * Disconnect
@@ -5854,7 +5948,7 @@
 	 */
 	icmp->icmp_dgram_errind = B_TRUE;
 
-	error = rawip_do_connect(connp, sa, len);
+	error = rawip_do_connect(connp, sa, len, cr);
 
 	if (error != 0 && did_bind) {
 		int unbind_err;
@@ -5927,9 +6021,9 @@
 
 	laddrlen = faddrlen = sizeof (sin6_t);
 	(void) rawip_getsockname((sock_lower_handle_t)connp,
-	    (struct sockaddr *)&laddr, &laddrlen, NULL);
+	    (struct sockaddr *)&laddr, &laddrlen, CRED());
 	error = rawip_getpeername((sock_lower_handle_t)connp,
-	    (struct sockaddr *)&faddr, &faddrlen, NULL);
+	    (struct sockaddr *)&faddr, &faddrlen, CRED());
 	if (error != 0)
 		faddrlen = 0;
 	opts = 0;
@@ -6038,6 +6132,9 @@
 	icmp_stack_t 		*is = connp->conn_icmp->icmp_is;
 	struct sock_proto_props sopp;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	connp->conn_upcalls = sock_upcalls;
 	connp->conn_upper_handle = sock_handle;
 
@@ -6169,6 +6266,9 @@
 	icmp_t  *icmp = connp->conn_icmp;
 	int	error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(icmp != NULL);
 
 	rw_enter(&icmp->icmp_rwlock, RW_READER);
@@ -6189,6 +6289,9 @@
 	icmp_t	*icmp = connp->conn_icmp;
 	int	error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(icmp != NULL);
 	rw_enter(&icmp->icmp_rwlock, RW_READER);
 
@@ -6207,6 +6310,9 @@
 	icmp_t *icmp = connp->conn_icmp;
 	int error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	error = proto_opt_check(level, option_name, optlen, NULL,
 	    icmp_opt_obj.odb_opt_des_arr,
 	    icmp_opt_obj.odb_opt_arr_cnt,
@@ -6253,6 +6359,9 @@
 	void		*optvalp_buf;
 	int		len;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	error = proto_opt_check(level, option_name, *optlen, &max_optbuf_len,
 	    icmp_opt_obj.odb_opt_des_arr,
 	    icmp_opt_obj.odb_opt_arr_cnt,
@@ -6296,6 +6405,10 @@
 rawip_close(sock_lower_handle_t proto_handle, int flags, cred_t *cr)
 {
 	conn_t	*connp = (conn_t *)proto_handle;
+
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	(void) rawip_do_close(connp);
 	return (0);
 }
@@ -6306,6 +6419,9 @@
 {
 	conn_t  *connp = (conn_t *)proto_handle;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	/* shut down the send side */
 	if (how != SHUT_RD)
 		(*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
@@ -6335,6 +6451,9 @@
 	conn_t  	*connp = (conn_t *)proto_handle;
 	int		error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	switch (cmd) {
 	case ND_SET:
 	case ND_GET:
@@ -6371,8 +6490,11 @@
 
 	ASSERT(DB_TYPE(mp) == M_DATA);
 
-	if (is_system_labeled())
-		msg_setcredpid(mp, cr, curproc->p_pid);
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
+	/* If labeled then sockfs should have already set db_credp */
+	ASSERT(!is_system_labeled() || msg_getcred(mp, NULL) != NULL);
 
 	/* do an implicit bind if necessary */
 	if (icmp->icmp_state == TS_UNBND) {
@@ -6454,7 +6576,7 @@
 		if (msg->msg_controllen != 0) {
 			error = process_auxiliary_options(connp,
 			    msg->msg_control, msg->msg_controllen,
-			    ipp, &icmp_opt_obj, icmp_opt_set);
+			    ipp, &icmp_opt_obj, icmp_opt_set, cr);
 			if (error != 0) {
 				goto done_lock;
 			}
@@ -6524,7 +6646,7 @@
 		if (msg->msg_controllen != 0) {
 			error = process_auxiliary_options(connp,
 			    msg->msg_control, msg->msg_controllen,
-			    pktinfop, &icmp_opt_obj, icmp_opt_set);
+			    pktinfop, &icmp_opt_obj, icmp_opt_set, cr);
 			if (error != 0) {
 				goto done_lock;
 			}
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 5994e06..66f4737 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -722,7 +722,8 @@
 
 static void	ip_wput_frag(ire_t *, mblk_t *, ip_pkt_t, uint32_t, uint32_t,
 		    zoneid_t, ip_stack_t *, conn_t *);
-static mblk_t	*ip_wput_frag_copyhdr(uchar_t *, int, int, ip_stack_t *);
+static mblk_t	*ip_wput_frag_copyhdr(uchar_t *, int, int, ip_stack_t *,
+		    mblk_t *);
 static void	ip_wput_local_options(ipha_t *, ip_stack_t *);
 static int	ip_wput_options(queue_t *, mblk_t *, ipha_t *, boolean_t,
 		    zoneid_t, ip_stack_t *);
@@ -2153,7 +2154,7 @@
 	if (nexthop_addr != INADDR_ANY) {
 		/* nexthop set */
 		first_ire = ire_ctable_lookup(ipha->ipha_dst,
-		    nexthop_addr, 0, NULL, ALL_ZONES, MBLK_GETLABEL(mp),
+		    nexthop_addr, 0, NULL, ALL_ZONES, msg_getlabel(mp),
 		    MATCH_IRE_MARK_PRIVATE_ADDR | MATCH_IRE_GW, ipst);
 	} else {
 		/* nexthop not set */
@@ -3327,6 +3328,7 @@
 		(void) adjmsg(mp, len_needed - msg_len);
 		msg_len = len_needed;
 	}
+	/* Make sure we propagate the cred/label for TX */
 	mp1 = allocb_tmpl(sizeof (icmp_ipha) + len, mp);
 	if (mp1 == NULL) {
 		BUMP_MIB(&ipst->ips_icmp_mib, icmpOutErrors);
@@ -4050,7 +4052,7 @@
 			ipif->ipif_addr_ready = 1;
 			ipif_refrele(ipif);
 		}
-		ire = ire_cache_lookup(src, ALL_ZONES, MBLK_GETLABEL(mp), ipst);
+		ire = ire_cache_lookup(src, ALL_ZONES, msg_getlabel(mp), ipst);
 		if (ire != NULL) {
 			ire->ire_defense_count = 0;
 			ire_refrele(ire);
@@ -4212,6 +4214,24 @@
 }
 
 /*
+ * Used to determine the most accurate cred_t to use for TX.
+ * First priority is SCM_UCRED having set the label in the message,
+ * which is used for MLP on UDP. Second priority is the peers label (aka
+ * conn_peercred), which is needed for MLP on TCP/SCTP. Last priority is the
+ * open credentials.
+ */
+cred_t *
+ip_best_cred(mblk_t *mp, conn_t *connp)
+{
+	cred_t *cr;
+
+	cr = msg_getcred(mp, NULL);
+	if (cr != NULL && crgetlabel(cr) != NULL)
+		return (cr);
+	return (CONN_CRED(connp));
+}
+
+/*
  * Latch in the IPsec state for a stream based on the ipsec_in_t passed in as
  * part of the bind request.
  */
@@ -4301,6 +4321,21 @@
 	int		error = 0;
 	int		protocol;
 	ipa_conn_x_t	*acx;
+	cred_t		*cr;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		error = EINVAL;
+		goto bad_addr;
+	}
 
 	ASSERT(!connp->conn_af_isv6);
 	connp->conn_pkt_isv6 = B_FALSE;
@@ -4403,7 +4438,7 @@
 		/* Always verify destination reachability. */
 		error = ip_bind_connected_v4(connp, &mp1, protocol,
 		    &ac->ac_laddr, ac->ac_lport, ac->ac_faddr, ac->ac_fport,
-		    B_TRUE, B_TRUE);
+		    B_TRUE, B_TRUE, cr);
 		break;
 
 	case sizeof (ipa_conn_x_t):
@@ -4415,7 +4450,7 @@
 		error = ip_bind_connected_v4(connp, &mp1, protocol,
 		    &acx->acx_conn.ac_laddr, acx->acx_conn.ac_lport,
 		    acx->acx_conn.ac_faddr, acx->acx_conn.ac_fport,
-		    B_TRUE, (acx->acx_flags & ACX_VERIFY_DST) != 0);
+		    B_TRUE, (acx->acx_flags & ACX_VERIFY_DST) != 0, cr);
 		break;
 	}
 	ASSERT(error != EINPROGRESS);
@@ -4664,7 +4699,7 @@
 int
 ip_bind_connected_v4(conn_t *connp, mblk_t **mpp, uint8_t protocol,
     ipaddr_t *src_addrp, uint16_t lport, ipaddr_t dst_addr, uint16_t fport,
-    boolean_t fanout_insert, boolean_t verify_dst)
+    boolean_t fanout_insert, boolean_t verify_dst, cred_t *cr)
 {
 
 	ire_t		*src_ire;
@@ -4688,8 +4723,9 @@
 	if (mp != NULL) {
 		ire_requested = (DB_TYPE(mp) == IRE_DB_REQ_TYPE);
 		ipsec_policy_set = (DB_TYPE(mp) == IPSEC_POLICY_SET);
-		tsl = MBLK_GETLABEL(mp);
 	}
+	if (cr != NULL)
+		tsl = crgetlabel(cr);
 
 	src_ire = dst_ire = NULL;
 
@@ -4791,7 +4827,7 @@
 	 */
 	if (dst_ire != NULL && is_system_labeled() &&
 	    !IPCL_IS_TCP(connp) &&
-	    tsol_compute_label(DB_CREDDEF(mp, connp->conn_cred), dst_addr, NULL,
+	    tsol_compute_label(cr, dst_addr, NULL,
 	    connp->conn_mac_exempt, ipst) != 0) {
 		error = EHOSTUNREACH;
 		if (ip_debug > 2) {
@@ -5142,7 +5178,7 @@
 int
 ip_proto_bind_connected_v4(conn_t *connp, mblk_t **ire_mpp, uint8_t protocol,
     ipaddr_t *src_addrp, uint16_t lport, ipaddr_t dst_addr, uint16_t fport,
-    boolean_t fanout_insert, boolean_t verify_dst)
+    boolean_t fanout_insert, boolean_t verify_dst, cred_t *cr)
 {
 	int error;
 	mblk_t	*mp = NULL;
@@ -5160,7 +5196,7 @@
 	if (lport == 0)
 		lport = connp->conn_lport;
 	error = ip_bind_connected_v4(connp, ire_mpp, protocol,
-	    src_addrp, lport, dst_addr, fport, fanout_insert, verify_dst);
+	    src_addrp, lport, dst_addr, fport, fanout_insert, verify_dst, cr);
 	if (error == 0) {
 		ip_bind_post_handling(connp, ire_mpp ? *ire_mpp : NULL,
 		    ire_requested);
@@ -7123,7 +7159,7 @@
 	unlabeled = B_FALSE;
 	if (is_system_labeled())
 		/* Cred cannot be null on IPv4 */
-		unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
+		unlabeled = (msg_getlabel(mp)->tsl_flags &
 		    TSLF_UNLABELED) != 0;
 	shared_addr = (zoneid == ALL_ZONES);
 	if (shared_addr) {
@@ -7851,14 +7887,14 @@
 		 * destination address via the specified nexthop.
 		 */
 		ire = ire_cache_lookup(nexthop_addr, zoneid,
-		    MBLK_GETLABEL(mp), ipst);
+		    msg_getlabel(mp), ipst);
 		if (ire != NULL) {
 			gw = nexthop_addr;
 			ire_marks |= IRE_MARK_PRIVATE_ADDR;
 		} else {
 			ire = ire_ftable_lookup(nexthop_addr, 0, 0,
 			    IRE_INTERFACE, NULL, NULL, zoneid, 0,
-			    MBLK_GETLABEL(mp),
+			    msg_getlabel(mp),
 			    MATCH_IRE_TYPE | MATCH_IRE_SECATTR,
 			    ipst);
 			if (ire != NULL) {
@@ -7867,7 +7903,7 @@
 		}
 	} else {
 		ire = ire_ftable_lookup(dst, 0, 0, 0,
-		    NULL, &sire, zoneid, 0, MBLK_GETLABEL(mp),
+		    NULL, &sire, zoneid, 0, msg_getlabel(mp),
 		    MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
 		    MATCH_IRE_RJ_BHOLE | MATCH_IRE_PARENT |
 		    MATCH_IRE_SECATTR | MATCH_IRE_COMPLETE,
@@ -7912,7 +7948,7 @@
 			ASSERT(sire != NULL);
 			multirt_is_resolvable =
 			    ire_multirt_lookup(&ire, &sire, multirt_flags,
-			    MBLK_GETLABEL(mp), ipst);
+			    msg_getlabel(mp), ipst);
 
 			ip3dbg(("ip_newroute: multirt_is_resolvable %d, "
 			    "ire %p, sire %p\n",
@@ -9189,7 +9225,7 @@
 			if ((flags & RTF_MULTIRT) && (copy_mp != NULL)) {
 				boolean_t need_resolve =
 				    ire_multirt_need_resolve(ipha_dst,
-				    MBLK_GETLABEL(copy_mp), ipst);
+				    msg_getlabel(copy_mp), ipst);
 				if (!need_resolve) {
 					MULTIRT_DEBUG_UNTAG(copy_mp);
 					freemsg(copy_mp);
@@ -9373,7 +9409,7 @@
 			if ((flags & RTF_MULTIRT) && (copy_mp != NULL)) {
 				boolean_t need_resolve =
 				    ire_multirt_need_resolve(ipha_dst,
-				    MBLK_GETLABEL(copy_mp), ipst);
+				    msg_getlabel(copy_mp), ipst);
 				if (!need_resolve) {
 					MULTIRT_DEBUG_UNTAG(copy_mp);
 					freemsg(copy_mp);
@@ -9838,9 +9874,24 @@
 		mp = connp->conn_ipsec_opt_mp;
 		connp->conn_ipsec_opt_mp = NULL;
 		connp->conn_state_flags  &= ~CONN_IPSEC_LOAD_WAIT;
-		cr = DB_CREDDEF(mp, GET_QUEUE_CRED(CONNP_TO_WQ(connp)));
 		mutex_exit(&connp->conn_lock);
 
+		/*
+		 * All Solaris components should pass a db_credp
+		 * for this TPI message, hence we ASSERT.
+		 * But in case there is some other M_PROTO that looks
+		 * like a TPI message sent by some other kernel
+		 * component, we check and return an error.
+		 */
+		cr = msg_getcred(mp, NULL);
+		ASSERT(cr != NULL);
+		if (cr == NULL) {
+			mp = mi_tpi_err_ack_alloc(mp, TSYSERR, EINVAL);
+			if (mp != NULL)
+				qreply(connp->conn_wq, mp);
+			return;
+		}
+
 		ASSERT(DB_TYPE(mp) == M_PROTO || DB_TYPE(mp) == M_PCPROTO);
 
 		optreq_prim = ((union T_primitives *)mp->b_rptr)->type;
@@ -11328,7 +11379,7 @@
 
 /*
  * This routine gets socket options.  For MRT_VERSION and MRT_ASSERT, error
- * checking of GET_QUEUE_CRED(q) and that ip_g_mrouter is set should be done and
+ * checking of cred and that ip_g_mrouter is set should be done and
  * isn't.  This doesn't matter as the error checking is done properly for the
  * other MRT options coming in through ip_opt_set.
  */
@@ -13476,7 +13527,7 @@
 	DB_CKSUMFLAGS(mp) = 0;
 
 	ire = ire_forward(dst, &ret_action, NULL, NULL,
-	    MBLK_GETLABEL(mp), ipst);
+	    msg_getlabel(mp), ipst);
 
 	if (ire == NULL && ret_action == Forward_check_multirt) {
 		/* Let ip_newroute handle CGTP  */
@@ -15106,7 +15157,7 @@
 
 		if (ire == NULL) {
 			ire = ire_cache_lookup(dst, ALL_ZONES,
-			    MBLK_GETLABEL(mp), ipst);
+			    msg_getlabel(mp), ipst);
 		}
 
 		if (ire != NULL && ire->ire_stq != NULL &&
@@ -15118,7 +15169,7 @@
 			 */
 			ire_refrele(ire);
 			ire = ire_cache_lookup(dst, GLOBAL_ZONEID,
-			    MBLK_GETLABEL(mp), ipst);
+			    msg_getlabel(mp), ipst);
 		}
 
 		if (ire == NULL) {
@@ -15397,7 +15448,7 @@
 			ire = NULL;
 		}
 
-		ire = ire_cache_lookup(dst, ALL_ZONES, MBLK_GETLABEL(mp),
+		ire = ire_cache_lookup(dst, ALL_ZONES, msg_getlabel(mp),
 		    ipst);
 		if (ire == NULL || ire->ire_type == IRE_BROADCAST ||
 		    ire->ire_stq != NULL) {
@@ -16740,7 +16791,7 @@
 	if (ipif->ipif_flags & IPIF_POINTOPOINT)
 		dst = ipif->ipif_pp_dst_addr;
 
-	ire = ire_ctable_lookup(dst, 0, 0, ipif, ALL_ZONES, MBLK_GETLABEL(mp),
+	ire = ire_ctable_lookup(dst, 0, 0, ipif, ALL_ZONES, msg_getlabel(mp),
 	    MATCH_IRE_ILL | MATCH_IRE_SECATTR, ipst);
 	if (ire == NULL) {
 		/*
@@ -17059,7 +17110,7 @@
 
 		if (ire == NULL) {
 			ire = ire_cache_lookup(dst, ii->ipsec_in_zoneid,
-			    MBLK_GETLABEL(mp), ipst);
+			    msg_getlabel(mp), ipst);
 			if (ire == NULL) {
 				if (ill_need_rele)
 					ill_refrele(ill);
@@ -18042,7 +18093,7 @@
 			if (optval == IPOPT_SSRR) {
 				ire = ire_ftable_lookup(dst, 0, 0,
 				    IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0,
-				    MBLK_GETLABEL(mp),
+				    msg_getlabel(mp),
 				    MATCH_IRE_TYPE | MATCH_IRE_SECATTR, ipst);
 				if (ire == NULL) {
 					ip1dbg(("ip_rput_options: SSRR not "
@@ -20463,7 +20514,7 @@
 		 * address, SO_DONTROUTE and IP_NEXTHOP go through the
 		 * standard path.
 		 */
-		ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp), ipst);
+		ire = ire_cache_lookup(dst, zoneid, msg_getlabel(mp), ipst);
 		if ((ire == NULL) || (ire->ire_type &
 		    (IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK)) == 0) {
 			if (ire != NULL) {
@@ -20497,7 +20548,7 @@
 	 */
 	if (IP_FLOW_CONTROLLED_ULP(connp->conn_ulp) &&
 	    !connp->conn_fully_bound) {
-		ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp), ipst);
+		ire = ire_cache_lookup(dst, zoneid, msg_getlabel(mp), ipst);
 		if (ire == NULL)
 			goto noirefound;
 		TRACE_2(TR_FAC_IP, TR_IP_WPUT_END,
@@ -20534,7 +20585,7 @@
 			 */
 			multirt_need_resolve =
 			    ire_multirt_need_resolve(ire->ire_addr,
-			    MBLK_GETLABEL(first_mp), ipst);
+			    msg_getlabel(first_mp), ipst);
 			ip2dbg(("ip_wput[TCP]: ire %p, "
 			    "multirt_need_resolve %d, first_mp %p\n",
 			    (void *)ire, multirt_need_resolve,
@@ -20603,7 +20654,7 @@
 		if (ire != NULL && sctp_ire == NULL)
 			IRE_REFRELE_NOTR(ire);
 
-		ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp), ipst);
+		ire = ire_cache_lookup(dst, zoneid, msg_getlabel(mp), ipst);
 		if (ire == NULL)
 			goto noirefound;
 		IRE_REFHOLD_NOTR(ire);
@@ -20662,7 +20713,7 @@
 		 * to initiate additional route resolutions.
 		 */
 		multirt_need_resolve = ire_multirt_need_resolve(ire->ire_addr,
-		    MBLK_GETLABEL(first_mp), ipst);
+		    msg_getlabel(first_mp), ipst);
 		ip2dbg(("ip_wput[not TCP]: ire %p, "
 		    "multirt_need_resolve %d, first_mp %p\n",
 		    (void *)ire, multirt_need_resolve, (void *)first_mp));
@@ -21167,7 +21218,7 @@
 		ire = NULL;
 		if (xmit_ill == NULL) {
 			ire = ire_ctable_lookup(dst, 0, 0, ipif,
-			    zoneid, MBLK_GETLABEL(mp), match_flags, ipst);
+			    zoneid, msg_getlabel(mp), match_flags, ipst);
 		}
 
 		if (ire == NULL) {
@@ -21228,7 +21279,7 @@
 			}
 		}
 	} else {
-		ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp), ipst);
+		ire = ire_cache_lookup(dst, zoneid, msg_getlabel(mp), ipst);
 		if ((ire != NULL) && (ire->ire_type &
 		    (IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK))) {
 			ignore_dontroute = B_TRUE;
@@ -21326,7 +21377,7 @@
 			 */
 			match_flags |= MATCH_IRE_ILL | MATCH_IRE_SECATTR;
 			ire = ire_ctable_lookup(dst, 0, 0, ipif, zoneid,
-			    MBLK_GETLABEL(mp), match_flags, ipst);
+			    msg_getlabel(mp), match_flags, ipst);
 			/*
 			 * If an ire exists use it or else create
 			 * an ire but don't add it to the cache.
@@ -21358,9 +21409,9 @@
 			match_flags = MATCH_IRE_MARK_PRIVATE_ADDR |
 			    MATCH_IRE_GW;
 			ire = ire_ctable_lookup(dst, nexthop_addr, 0,
-			    NULL, zoneid, MBLK_GETLABEL(mp), match_flags, ipst);
+			    NULL, zoneid, msg_getlabel(mp), match_flags, ipst);
 		} else {
-			ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp),
+			ire = ire_cache_lookup(dst, zoneid, msg_getlabel(mp),
 			    ipst);
 		}
 		if (!ire) {
@@ -21452,7 +21503,7 @@
 		 * to initiate additional route resolutions.
 		 */
 		multirt_need_resolve = ire_multirt_need_resolve(ire->ire_addr,
-		    MBLK_GETLABEL(first_mp), ipst);
+		    msg_getlabel(first_mp), ipst);
 		ip2dbg(("ip_wput[noirefound]: ire %p, "
 		    "multirt_need_resolve %d, first_mp %p\n",
 		    (void *)ire, multirt_need_resolve, (void *)first_mp));
@@ -24084,7 +24135,8 @@
 	}
 
 	/* Get a copy of the header for the trailing frags */
-	hdr_mp = ip_wput_frag_copyhdr((uchar_t *)ipha, hdr_len, offset, ipst);
+	hdr_mp = ip_wput_frag_copyhdr((uchar_t *)ipha, hdr_len, offset, ipst,
+	    mp);
 	if (!hdr_mp) {
 		BUMP_MIB(mibptr, ipIfStatsOutFragFails);
 		freemsg(mp);
@@ -24093,8 +24145,6 @@
 		    "couldn't copy hdr");
 		return;
 	}
-	if (DB_CRED(mp) != NULL)
-		mblk_setcred(hdr_mp, DB_CRED(mp));
 
 	/* Store the starting offset, with the MoreFrags flag. */
 	i1 = offset | IPH_MF | frag_flag;
@@ -24309,8 +24359,7 @@
 		 */
 		} else {
 			xmit_mp->b_cont = mp;
-			if (DB_CRED(mp) != NULL)
-				mblk_setcred(xmit_mp, DB_CRED(mp));
+
 			/*
 			 * Get priority marking, if any.
 			 * We propagate the CoS marking from the
@@ -24607,8 +24656,6 @@
 			 */
 			} else if ((xmit_mp = copyb(ll_hdr_mp)) != NULL) {
 				xmit_mp->b_cont = mp;
-				if (DB_CRED(mp) != NULL)
-					mblk_setcred(xmit_mp, DB_CRED(mp));
 				/* Get priority marking, if any. */
 				if (DB_TYPE(xmit_mp) == M_DATA)
 					xmit_mp->b_band = mp->b_band;
@@ -24738,9 +24785,11 @@
 
 /*
  * Copy the header plus those options which have the copy bit set
+ * src is the template to make sure we preserve the cred for TX purposes.
  */
 static mblk_t *
-ip_wput_frag_copyhdr(uchar_t *rptr, int hdr_len, int offset, ip_stack_t *ipst)
+ip_wput_frag_copyhdr(uchar_t *rptr, int hdr_len, int offset, ip_stack_t *ipst,
+    mblk_t *src)
 {
 	mblk_t	*mp;
 	uchar_t	*up;
@@ -24749,7 +24798,7 @@
 	 * Quick check if we need to look for options without the copy bit
 	 * set
 	 */
-	mp = allocb(ipst->ips_ip_wroff_extra + hdr_len, BPRI_HI);
+	mp = allocb_tmpl(ipst->ips_ip_wroff_extra + hdr_len, src);
 	if (!mp)
 		return (mp);
 	mp->b_rptr += ipst->ips_ip_wroff_extra;
@@ -25364,15 +25413,6 @@
 			mp1->b_band = mp->b_band;
 			mp1->b_cont = mp;
 			/*
-			 * certain system generated traffic may not
-			 * have cred/label in ip header block. This
-			 * is true even for a labeled system. But for
-			 * labeled traffic, inherit the label in the
-			 * new header.
-			 */
-			if (DB_CRED(mp) != NULL)
-				mblk_setcred(mp1, DB_CRED(mp));
-			/*
 			 * XXX disable ICK_VALID and compute checksum
 			 * here; can happen if nce_fp_mp changes and
 			 * it can't be copied now due to insufficient
@@ -25392,15 +25432,6 @@
 		}
 		UNLOCK_IRE_FP_MP(ire);
 		mp1->b_cont = mp;
-		/*
-		 * certain system generated traffic may not
-		 * have cred/label in ip header block. This
-		 * is true even for a labeled system. But for
-		 * labeled traffic, inherit the label in the
-		 * new header.
-		 */
-		if (DB_CRED(mp) != NULL)
-			mblk_setcred(mp1, DB_CRED(mp));
 		if (!qos_done && (proc != 0) && IPP_ENABLED(proc, ipst)) {
 			ip_process(proc, &mp1, ill_index);
 			if (mp1 == NULL)
@@ -25490,7 +25521,7 @@
 			ire = ire_arg;
 		} else {
 			ire = ire_ctable_lookup_v6(v6dstp, 0, 0, ipif,
-			    zoneid, MBLK_GETLABEL(mp), match_flags, ipst);
+			    zoneid, msg_getlabel(mp), match_flags, ipst);
 			ire_need_rele = B_TRUE;
 		}
 		if (ire != NULL) {
@@ -25771,7 +25802,7 @@
 		 * an ire to send this downstream.
 		 */
 		ire = ire_ctable_lookup(dst, 0, 0, ipif, zoneid,
-		    MBLK_GETLABEL(mp), match_flags, ipst);
+		    msg_getlabel(mp), match_flags, ipst);
 		if (ire != NULL) {
 			ill_t *ill1;
 			/*
@@ -25820,7 +25851,7 @@
 			ire_need_rele = B_FALSE;
 		} else {
 			ire = ire_cache_lookup(dst, zoneid,
-			    MBLK_GETLABEL(mp), ipst);
+			    msg_getlabel(mp), ipst);
 		}
 		if (ire != NULL) {
 			goto send;
@@ -26634,6 +26665,7 @@
 	opt_restart_t	*or;
 	int	err;
 	conn_t	*connp;
+	cred_t	*cr;
 
 	ASSERT(CONN_Q(q));
 	connp = Q_TO_CONN(q);
@@ -26641,16 +26673,18 @@
 	ASSERT(first_mp->b_datap->db_type == M_CTL);
 	or = (opt_restart_t *)first_mp->b_rptr;
 	/*
-	 * We don't need to pass any credentials here since this is just
-	 * a restart. The credentials are passed in when svr4_optcom_req
-	 * is called the first time (from ip_wput_nondata).
+	 * We checked for a db_credp the first time svr4_optcom_req
+	 * was called (from ip_wput_nondata). So we can just ASSERT here.
 	 */
+	cr = msg_getcred(first_mp, NULL);
+	ASSERT(cr != NULL);
+
 	if (or->or_type == T_SVR4_OPTMGMT_REQ) {
-		err = svr4_optcom_req(q, first_mp, NULL,
+		err = svr4_optcom_req(q, first_mp, cr,
 		    &ip_opt_obj, B_FALSE);
 	} else {
 		ASSERT(or->or_type == T_OPTMGMT_REQ);
-		err = tpi_optcom_req(q, first_mp, NULL,
+		err = tpi_optcom_req(q, first_mp, cr,
 		    &ip_opt_obj, B_FALSE);
 	}
 	if (err != EINPROGRESS) {
@@ -26954,8 +26988,6 @@
 		ipst = ILLQ_TO_IPST(q);
 	}
 
-	cr = DB_CREDDEF(mp, GET_QUEUE_CRED(q));
-
 	switch (DB_TYPE(mp)) {
 	case M_IOCTL:
 		/*
@@ -27233,6 +27265,22 @@
 				goto protonak;
 			}
 
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				mp = mi_tpi_err_ack_alloc(mp, TSYSERR, EINVAL);
+				if (mp != NULL)
+					qreply(q, mp);
+				return;
+			}
+
 			if (!snmpcom_req(q, mp, ip_snmp_set,
 			    ip_snmp_get, cr)) {
 				/*
@@ -27269,6 +27317,21 @@
 				goto protonak;
 			}
 
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				mp = mi_tpi_err_ack_alloc(mp, TSYSERR, EINVAL);
+				if (mp != NULL)
+					qreply(q, mp);
+				return;
+			}
 			ASSERT(ipsq == NULL);
 			/*
 			 * We don't come here for restart. ip_restart_optmgmt
@@ -27742,7 +27805,7 @@
 			if (optval == IPOPT_SSRR) {
 				ire = ire_ftable_lookup(dst, 0, 0,
 				    IRE_INTERFACE, NULL, NULL, ALL_ZONES, 0,
-				    MBLK_GETLABEL(mp),
+				    msg_getlabel(mp),
 				    MATCH_IRE_TYPE | MATCH_IRE_SECATTR, ipst);
 				if (ire == NULL) {
 					ip1dbg(("ip_wput_options: SSRR not"
diff --git a/usr/src/uts/common/inet/ip/ip6.c b/usr/src/uts/common/inet/ip/ip6.c
index eb541c9..686e2ad 100644
--- a/usr/src/uts/common/inet/ip/ip6.c
+++ b/usr/src/uts/common/inet/ip/ip6.c
@@ -192,7 +192,7 @@
 static void	icmp_redirect_v6(queue_t *, mblk_t *, ill_t *ill);
 static int	ip_bind_connected_v6(conn_t *, mblk_t **, uint8_t, in6_addr_t *,
     uint16_t, const in6_addr_t *, ip6_pkt_t *, uint16_t,
-    boolean_t, boolean_t);
+    boolean_t, boolean_t, cred_t *);
 static boolean_t ip_bind_get_ire_v6(mblk_t **, ire_t *, const in6_addr_t *,
     iulp_t *, ip_stack_t *);
 static void	ip_bind_post_handling_v6(conn_t *, mblk_t *, boolean_t,
@@ -1565,7 +1565,7 @@
 		}
 		msg_len = len_needed;
 	}
-	mp1 = allocb_cred(IPV6_HDR_LEN + len, DB_CRED(mp));
+	mp1 = allocb_tmpl(IPV6_HDR_LEN + len, mp);
 	if (mp1 == NULL) {
 		BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpOutErrors);
 		freemsg(ipsec_mp);
@@ -1992,6 +1992,21 @@
 	ipa6_conn_x_t		*acx6;
 	boolean_t		verify_dst;
 	ip_stack_t		*ipst = connp->conn_netstack->netstack_ip;
+	cred_t			*cr;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		error = EINVAL;
+		goto bad_addr;
+	}
 
 	ASSERT(connp->conn_af_isv6);
 	len = mp->b_wptr - mp->b_rptr;
@@ -2118,7 +2133,7 @@
 		    v6srcp, lport, tbr->ADDR_length != IPV6_ADDR_LEN);
 	} else {
 		error = ip_proto_bind_connected_v6(connp, &mp->b_cont, protocol,
-		    v6srcp, lport, v6dstp, ipp, fport, B_TRUE, verify_dst);
+		    v6srcp, lport, v6dstp, ipp, fport, B_TRUE, verify_dst, cr);
 	}
 
 	if (error == 0) {
@@ -2418,7 +2433,7 @@
 ip_bind_connected_v6(conn_t *connp, mblk_t **mpp, uint8_t protocol,
     in6_addr_t *v6src, uint16_t lport, const in6_addr_t *v6dst,
     ip6_pkt_t *ipp, uint16_t fport, boolean_t fanout_insert,
-    boolean_t verify_dst)
+    boolean_t verify_dst, cred_t *cr)
 {
 	ire_t		*src_ire;
 	ire_t		*dst_ire;
@@ -2442,8 +2457,9 @@
 	if (mp != NULL) {
 		ire_requested = (DB_TYPE(mp) == IRE_DB_REQ_TYPE);
 		ipsec_policy_set = (DB_TYPE(mp) == IPSEC_POLICY_SET);
-		tsl = MBLK_GETLABEL(mp);
 	}
+	if (cr != NULL)
+		tsl = crgetlabel(cr);
 
 	src_ire = dst_ire = NULL;
 	/*
@@ -2546,8 +2562,8 @@
 	 */
 	if (dst_ire != NULL && is_system_labeled() &&
 	    !IPCL_IS_TCP(connp) &&
-	    tsol_compute_label_v6(DB_CREDDEF(mp, connp->conn_cred),
-	    v6dst, NULL, connp->conn_mac_exempt, ipst) != 0) {
+	    tsol_compute_label_v6(cr, v6dst, NULL,
+	    connp->conn_mac_exempt, ipst) != 0) {
 		error = EHOSTUNREACH;
 		if (ip_debug > 2) {
 			pr_addr_dbg("ip_bind_connected: no label for dst %s\n",
@@ -2874,7 +2890,7 @@
 ip_proto_bind_connected_v6(conn_t *connp, mblk_t **mpp, uint8_t protocol,
     in6_addr_t *v6srcp, uint16_t lport, const in6_addr_t *v6dstp,
     ip6_pkt_t *ipp, uint16_t fport, boolean_t fanout_insert,
-    boolean_t verify_dst)
+    boolean_t verify_dst, cred_t *cr)
 {
 	int error = 0;
 	boolean_t orig_pkt_isv6 = connp->conn_pkt_isv6;
@@ -2917,7 +2933,7 @@
 
 		/* Always verify destination reachability. */
 		error = ip_bind_connected_v4(connp, mpp, protocol, &v4src,
-		    lport, v4dst, fport, B_TRUE, B_TRUE);
+		    lport, v4dst, fport, B_TRUE, B_TRUE, cr);
 		if (error != 0)
 			goto bad_addr;
 		IN6_IPADDR_TO_V4MAPPED(v4src, v6srcp);
@@ -2928,7 +2944,7 @@
 		goto bad_addr;
 	} else {
 		error = ip_bind_connected_v6(connp, mpp, protocol, v6srcp,
-		    lport, v6dstp, ipp, fport, B_TRUE, verify_dst);
+		    lport, v6dstp, ipp, fport, B_TRUE, verify_dst, cr);
 		if (error != 0)
 			goto bad_addr;
 		connp->conn_pkt_isv6 = B_TRUE;
@@ -4290,7 +4306,7 @@
 		match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
 		    MATCH_IRE_PARENT | MATCH_IRE_RJ_BHOLE | MATCH_IRE_SECATTR;
 		ire = ire_ftable_lookup_v6(v6dstp, 0, 0, 0,
-		    NULL, &sire, zoneid, 0, MBLK_GETLABEL(mp),
+		    NULL, &sire, zoneid, 0, msg_getlabel(mp),
 		    match_flags, ipst);
 	} else {
 		match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT |
@@ -4311,7 +4327,7 @@
 		}
 
 		ire = ire_ftable_lookup_v6(v6dstp, NULL, NULL, 0, ill->ill_ipif,
-		    &sire, zoneid, 0, MBLK_GETLABEL(mp), match_flags, ipst);
+		    &sire, zoneid, 0, msg_getlabel(mp), match_flags, ipst);
 	}
 
 	ip3dbg(("ip_newroute_v6: ire_ftable_lookup_v6() "
@@ -4346,7 +4362,7 @@
 			 * the destination contained in sire.
 			 */
 			multirt_is_resolvable = ire_multirt_lookup_v6(&ire,
-			    &sire, multirt_flags, MBLK_GETLABEL(mp), ipst);
+			    &sire, multirt_flags, msg_getlabel(mp), ipst);
 
 			ip3dbg(("ip_newroute_v6: multirt_is_resolvable %d, "
 			    "ire %p, sire %p\n",
@@ -5773,7 +5789,7 @@
 			if (copy_mp != NULL) {
 				boolean_t need_resolve =
 				    ire_multirt_need_resolve_v6(v6dstp,
-				    MBLK_GETLABEL(copy_mp), ipst);
+				    msg_getlabel(copy_mp), ipst);
 				if (!need_resolve) {
 					MULTIRT_DEBUG_UNTAG(copy_mp);
 					freemsg(copy_mp);
@@ -5902,7 +5918,7 @@
 				if (copy_mp != NULL) {
 					boolean_t need_resolve =
 					    ire_multirt_need_resolve_v6(v6dstp,
-					    MBLK_GETLABEL(copy_mp), ipst);
+					    msg_getlabel(copy_mp), ipst);
 					if (!need_resolve) {
 						MULTIRT_DEBUG_UNTAG(copy_mp);
 						freemsg(copy_mp);
@@ -5980,7 +5996,7 @@
 				if (copy_mp != NULL) {
 					boolean_t need_resolve =
 					    ire_multirt_need_resolve_v6(v6dstp,
-					    MBLK_GETLABEL(copy_mp), ipst);
+					    msg_getlabel(copy_mp), ipst);
 					if (!need_resolve) {
 						MULTIRT_DEBUG_UNTAG(copy_mp);
 						freemsg(copy_mp);
@@ -7212,7 +7228,7 @@
 		    MATCH_IRE_TYPE | MATCH_IRE_ILL, ipst);
 	} else {
 		ire = ire_cache_lookup_v6(&ip6h->ip6_dst, ALL_ZONES,
-		    MBLK_GETLABEL(mp), ipst);
+		    msg_getlabel(mp), ipst);
 
 		if (ire != NULL && ire->ire_stq != NULL &&
 		    ire->ire_zoneid != GLOBAL_ZONEID &&
@@ -7223,7 +7239,7 @@
 			 */
 			ire_refrele(ire);
 			ire = ire_cache_lookup_v6(&ip6h->ip6_dst,
-			    GLOBAL_ZONEID, MBLK_GETLABEL(mp), ipst);
+			    GLOBAL_ZONEID, msg_getlabel(mp), ipst);
 		}
 	}
 
@@ -9229,13 +9245,14 @@
 
 	if (is_system_labeled() && DB_TYPE(mp) == M_DATA &&
 	    (connp == NULL || !connp->conn_ulp_labeled)) {
+		cred_t		*cr;
+
 		if (connp != NULL) {
 			ASSERT(CONN_CRED(connp) != NULL);
 			err = tsol_check_label_v6(BEST_CRED(mp, connp),
 			    &mp, connp->conn_mac_exempt, ipst);
-		} else if (DB_CRED(mp) != NULL) {
-			err = tsol_check_label_v6(DB_CRED(mp),
-			    &mp, B_FALSE, ipst);
+		} else if ((cr = msg_getcred(mp, NULL)) != NULL) {
+			err = tsol_check_label_v6(cr, &mp, B_FALSE, ipst);
 		}
 		if (mctl_present)
 			first_mp->b_cont = mp;
@@ -9452,7 +9469,7 @@
 			}
 		}
 		if (ip6i->ip6i_flags & IP6I_VERIFY_SRC) {
-			cred_t *cr = DB_CREDDEF(mp, GET_QUEUE_CRED(q));
+			cred_t *cr = msg_getcred(mp, NULL);
 
 			ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src));
 			if (secpolicy_net_rawaccess(cr) != 0) {
@@ -9570,7 +9587,7 @@
 		 * as it does not really have a real destination to
 		 * talk to.
 		 */
-		ire = ire_cache_lookup_v6(v6dstp, zoneid, MBLK_GETLABEL(mp),
+		ire = ire_cache_lookup_v6(v6dstp, zoneid, msg_getlabel(mp),
 		    ipst);
 	} else {
 		/*
@@ -9598,7 +9615,7 @@
 				IRE_REFRELE_NOTR(ire);
 
 			ire = ire_cache_lookup_v6(v6dstp, zoneid,
-			    MBLK_GETLABEL(mp), ipst);
+			    msg_getlabel(mp), ipst);
 			if (ire != NULL) {
 				IRE_REFHOLD_NOTR(ire);
 
@@ -9677,7 +9694,7 @@
 			 */
 			multirt_need_resolve =
 			    ire_multirt_need_resolve_v6(&ire->ire_addr_v6,
-			    MBLK_GETLABEL(first_mp), ipst);
+			    msg_getlabel(first_mp), ipst);
 			ip2dbg(("ip_wput_v6: ire %p, "
 			    "multirt_need_resolve %d, first_mp %p\n",
 			    (void *)ire, multirt_need_resolve,
@@ -10040,7 +10057,7 @@
 	 *	  It is used only when ire_cache_lookup is used above.
 	 */
 	ire = ire_ctable_lookup_v6(v6dstp, 0, 0, ill->ill_ipif,
-	    zoneid, MBLK_GETLABEL(mp), match_flags, ipst);
+	    zoneid, msg_getlabel(mp), match_flags, ipst);
 	if (ire != NULL) {
 		/*
 		 * Check if the ire has the RTF_MULTIRT flag, inherited
@@ -10080,7 +10097,7 @@
 			 */
 			multirt_need_resolve =
 			    ire_multirt_need_resolve_v6(&ire->ire_addr_v6,
-			    MBLK_GETLABEL(first_mp), ipst);
+			    msg_getlabel(first_mp), ipst);
 			ip2dbg(("ip_wput_v6[send_from_ill]: ire %p, "
 			    "multirt_need_resolve %d, first_mp %p\n",
 			    (void *)ire, multirt_need_resolve,
@@ -11510,8 +11527,8 @@
 	 * fragment header.  This (or a copy) will be used as the
 	 * first mblk for each fragment we send.
 	 */
-	hmp = allocb(unfragmentable_len + sizeof (ip6_frag_t) +
-	    ipst->ips_ip_wroff_extra, BPRI_HI);
+	hmp = allocb_tmpl(unfragmentable_len + sizeof (ip6_frag_t) +
+	    ipst->ips_ip_wroff_extra, mp);
 	if (hmp == NULL) {
 		BUMP_MIB(ill->ill_ip_mib, ipIfStatsOutFragFails);
 		freemsg(mp);
diff --git a/usr/src/uts/common/inet/ip/ip_ftable.c b/usr/src/uts/common/inet/ip/ip_ftable.c
index e03b358..77da022 100644
--- a/usr/src/uts/common/inet/ip/ip_ftable.c
+++ b/usr/src/uts/common/inet/ip/ip_ftable.c
@@ -1676,7 +1676,7 @@
 		match_flags = (MATCH_IRE_DSTONLY | MATCH_IRE_DEFAULT |
 		    MATCH_IRE_RECURSIVE | MATCH_IRE_RJ_BHOLE);
 		ire = ire_route_lookup(dst,
-		    0, 0, 0, NULL, &sire, zoneid, MBLK_GETLABEL(mp),
+		    0, 0, 0, NULL, &sire, zoneid, msg_getlabel(mp),
 		    match_flags, ipst);
 	} else {
 		ipif_t *supplied_ipif;
@@ -1704,7 +1704,7 @@
 		}
 
 		ire = ire_route_lookup(dst, 0, 0, 0, supplied_ipif,
-		    &sire, zoneid, MBLK_GETLABEL(mp), match_flags, ipst);
+		    &sire, zoneid, msg_getlabel(mp), match_flags, ipst);
 		ipif_refrele(supplied_ipif);
 		ill_refrele(ill);
 	}
@@ -1763,7 +1763,7 @@
 		 * to the ire cache table
 		 */
 		ire_cache = ire_forward(dst, &ret_action, ire, sire,
-		    MBLK_GETLABEL(mp), ipst);
+		    msg_getlabel(mp), ipst);
 		if (ire_cache == NULL) {
 			ip1dbg(("ipfil_sendpkt: failed to create the"
 			    " ire cache entry \n"));
diff --git a/usr/src/uts/common/inet/ip/ip_helper_stream.c b/usr/src/uts/common/inet/ip/ip_helper_stream.c
index a3ff2b5..6f5608e 100644
--- a/usr/src/uts/common/inet/ip/ip_helper_stream.c
+++ b/usr/src/uts/common/inet/ip/ip_helper_stream.c
@@ -321,7 +321,8 @@
 	mblk_t			*mp;
 
 	size = sizeof (struct T_optmgmt_req) + sizeof (struct opthdr) + optlen;
-	mp = allocb_cred(size, cr);
+	/* Not used to generate UCRED, thus don't need correct pid */
+	mp = allocb_cred(size, cr, NOPID);
 	if (mp == NULL)
 		return (ENOMEM);
 
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index 1fd00aa..64f9789 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -34,6 +34,7 @@
 #include <sys/stropts.h>
 #include <sys/strsun.h>
 #include <sys/sysmacros.h>
+#include <sys/strsubr.h>
 #include <sys/strlog.h>
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
@@ -10220,7 +10221,9 @@
 	 * the framework; the caller of ioctl needs to hold the reference
 	 * for the duration of the call).
 	 */
-	cr = DB_CREDDEF(mp, iocp->ioc_cr);
+	cr = msg_getcred(mp, NULL);
+	if (cr == NULL)
+		cr = iocp->ioc_cr;
 
 	/* Make sure normal users don't send down privileged ioctls */
 	if ((ipip->ipi_flags & IPI_PRIV) &&
@@ -12952,7 +12955,9 @@
 	 * prefer credential from mblk over ioctl;
 	 * see ip_sioctl_copyin_setup
 	 */
-	cr = DB_CREDDEF(mp, iocp->ioc_cr);
+	cr = msg_getcred(mp, NULL);
+	if (cr == NULL)
+		cr = iocp->ioc_cr;
 
 	/*
 	 * Refhold the conn in case the request gets queued up in some lookup
diff --git a/usr/src/uts/common/inet/ip/ip_ire.c b/usr/src/uts/common/inet/ip/ip_ire.c
index 40e0989..5113405 100644
--- a/usr/src/uts/common/inet/ip/ip_ire.c
+++ b/usr/src/uts/common/inet/ip/ip_ire.c
@@ -32,6 +32,7 @@
 #include <sys/stream.h>
 #include <sys/stropts.h>
 #include <sys/strsun.h>
+#include <sys/strsubr.h>
 #include <sys/ddi.h>
 #include <sys/cmn_err.h>
 #include <sys/policy.h>
@@ -1255,12 +1256,12 @@
 		if (ire->ire_ipversion == IPV4_VERSION) {
 			ipha = (ipha_t *)data_mp->b_rptr;
 			dst_ire = ire_cache_lookup(ipha->ipha_dst,
-			    ire->ire_zoneid, MBLK_GETLABEL(mp), ipst);
+			    ire->ire_zoneid, msg_getlabel(mp), ipst);
 		} else {
 			ASSERT(ire->ire_ipversion == IPV6_VERSION);
 			ip6h = (ip6_t *)data_mp->b_rptr;
 			dst_ire = ire_cache_lookup_v6(&ip6h->ip6_dst,
-			    ire->ire_zoneid, MBLK_GETLABEL(mp), ipst);
+			    ire->ire_zoneid, msg_getlabel(mp), ipst);
 		}
 		if (dst_ire != NULL) {
 			if (dst_ire->ire_flags & RTF_MULTIRT) {
diff --git a/usr/src/uts/common/inet/ip/ip_multi.c b/usr/src/uts/common/inet/ip/ip_multi.c
index cbea9be..656080b 100644
--- a/usr/src/uts/common/inet/ip/ip_multi.c
+++ b/usr/src/uts/common/inet/ip/ip_multi.c
@@ -1241,12 +1241,15 @@
 
 		if (((mp = allocb(hdrsz, BPRI_MED)) != NULL) &&
 		    (mp_orig = dupmsg(mp_orig)) != NULL) {
+			cred_t *cr;
+
 			bcopy(mp_orig->b_rptr, mp->b_rptr, hdrsz);
 			mp->b_wptr += hdrsz;
 			mp->b_cont = mp_orig;
 			mp_orig->b_rptr += hdrsz;
-			if (is_system_labeled() && DB_CRED(mp_orig) != NULL)
-				mblk_setcred(mp, DB_CRED(mp_orig));
+			if (is_system_labeled() &&
+			    (cr = msg_getcred(mp_orig, NULL)) != NULL)
+				mblk_setcred(mp, cr, NOPID);
 			if (MBLKL(mp_orig) == 0) {
 				mp->b_cont = mp_orig->b_cont;
 				mp_orig->b_cont = NULL;
diff --git a/usr/src/uts/common/inet/ip/ip_rts.c b/usr/src/uts/common/inet/ip/ip_rts.c
index 77ab2cc..ca39678 100644
--- a/usr/src/uts/common/inet/ip/ip_rts.c
+++ b/usr/src/uts/common/inet/ip/ip_rts.c
@@ -46,6 +46,7 @@
 #include <sys/stream.h>
 #include <sys/stropts.h>
 #include <sys/ddi.h>
+#include <sys/strsubr.h>
 #include <sys/cmn_err.h>
 #include <sys/debug.h>
 #include <sys/policy.h>
@@ -233,7 +234,7 @@
 static void
 ip_rts_request_retry(ipsq_t *dummy_sq, queue_t *q, mblk_t *mp, void *dummy)
 {
-	(void) ip_rts_request(q, mp, DB_CRED(mp));
+	(void) ip_rts_request(q, mp, msg_getcred(mp, NULL));
 }
 
 /*
diff --git a/usr/src/uts/common/inet/ip/ipclassifier.c b/usr/src/uts/common/inet/ip/ipclassifier.c
index 5afa701..0aafd8e 100644
--- a/usr/src/uts/common/inet/ip/ipclassifier.c
+++ b/usr/src/uts/common/inet/ip/ipclassifier.c
@@ -672,10 +672,10 @@
 
 	DTRACE_PROBE1(conn__destroy, conn_t *, connp);
 
-	if (connp->conn_peercred != NULL &&
-	    connp->conn_peercred != connp->conn_cred)
+	if (connp->conn_peercred != NULL) {
 		crfree(connp->conn_peercred);
-	connp->conn_peercred = NULL;
+		connp->conn_peercred = NULL;
+	}
 
 	if (connp->conn_cred != NULL) {
 		crfree(connp->conn_cred);
@@ -1568,9 +1568,12 @@
 		lport = up[1];
 		unlabeled = B_FALSE;
 		/* Cred cannot be null on IPv4 */
-		if (is_system_labeled())
-			unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
+		if (is_system_labeled()) {
+			cred_t *cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			unlabeled = (crgetlabel(cr)->tsl_flags &
 			    TSLF_UNLABELED) != 0;
+		}
 		shared_addr = (zoneid == ALL_ZONES);
 		if (shared_addr) {
 			/*
@@ -1640,9 +1643,12 @@
 		lport = up[1];
 		unlabeled = B_FALSE;
 		/* Cred cannot be null on IPv4 */
-		if (is_system_labeled())
-			unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
+		if (is_system_labeled()) {
+			cred_t *cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			unlabeled = (crgetlabel(cr)->tsl_flags &
 			    TSLF_UNLABELED) != 0;
+		}
 		shared_addr = (zoneid == ALL_ZONES);
 		if (shared_addr) {
 			/*
@@ -1761,7 +1767,7 @@
 		unlabeled = B_FALSE;
 		/* Cred can be null on IPv6 */
 		if (is_system_labeled()) {
-			cred_t *cr = DB_CRED(mp);
+			cred_t *cr = msg_getcred(mp, NULL);
 
 			unlabeled = (cr != NULL &&
 			    crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
@@ -1834,7 +1840,7 @@
 		unlabeled = B_FALSE;
 		/* Cred can be null on IPv6 */
 		if (is_system_labeled()) {
-			cred_t *cr = DB_CRED(mp);
+			cred_t *cr = msg_getcred(mp, NULL);
 
 			unlabeled = (cr != NULL &&
 			    crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
@@ -1951,7 +1957,7 @@
 	unlabeled = B_FALSE;
 	/* Cred can be null on IPv6 */
 	if (is_system_labeled()) {
-		cred_t *cr = DB_CRED(mp);
+		cred_t *cr = msg_getcred(mp, NULL);
 
 		unlabeled = (cr != NULL &&
 		    crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
diff --git a/usr/src/uts/common/inet/ip/ipsecah.c b/usr/src/uts/common/inet/ip/ipsecah.c
index 65199df..7782f62 100644
--- a/usr/src/uts/common/inet/ip/ipsecah.c
+++ b/usr/src/uts/common/inet/ip/ipsecah.c
@@ -3060,8 +3060,7 @@
 			return (NULL);
 	}
 
-	if ((phdr_mp = allocb_cred(hdr_size + ah_data_sz,
-	    DB_CRED(mp))) == NULL) {
+	if ((phdr_mp = allocb_tmpl(hdr_size + ah_data_sz, mp)) == NULL) {
 		return (NULL);
 	}
 
@@ -3192,7 +3191,7 @@
 		size += option_length;
 	}
 
-	if ((phdr_mp = allocb_cred(size, DB_CRED(mp))) == NULL) {
+	if ((phdr_mp = allocb_tmpl(size, mp)) == NULL) {
 		return (NULL);
 	}
 
@@ -4235,6 +4234,11 @@
 		while (--dest >= mp->b_rptr)
 			*dest = *(dest - newpos);
 	}
+	/*
+	 * The db_credp should be in mp (if needed) and never in phdr_mp
+	 */
+	ASSERT(msg_getcred(phdr_mp, NULL) == NULL);
+
 	freeb(phdr_mp);
 	ipsec_in->b_cont = mp;
 	if (assoc->ipsa_state == IPSA_STATE_IDLE) {
diff --git a/usr/src/uts/common/inet/ip/keysock.c b/usr/src/uts/common/inet/ip/keysock.c
index 67a21f6..ca82eee 100644
--- a/usr/src/uts/common/inet/ip/keysock.c
+++ b/usr/src/uts/common/inet/ip/keysock.c
@@ -912,10 +912,6 @@
 			freemsg(mp);
 			return;
 		}
-		cr = zone_get_kcred(netstackid_to_zoneid(
-		    keystack->keystack_netstack->netstack_stackid));
-		ASSERT(cr != NULL);
-
 		switch (((union T_primitives *)mp->b_rptr)->type) {
 		case T_CAPABILITY_REQ:
 			keysock_capability_req(q, mp);
@@ -924,12 +920,28 @@
 			keysock_info_req(q, mp);
 			break;
 		case T_SVR4_OPTMGMT_REQ:
-			(void) svr4_optcom_req(q, mp, DB_CREDDEF(mp, cr),
-			    &keysock_opt_obj, B_FALSE);
-			break;
 		case T_OPTMGMT_REQ:
-			(void) tpi_optcom_req(q, mp, DB_CREDDEF(mp, cr),
-			    &keysock_opt_obj, B_FALSE);
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				keysock_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
+			if (((union T_primitives *)mp->b_rptr)->type ==
+			    T_SVR4_OPTMGMT_REQ) {
+				(void) svr4_optcom_req(q, mp, cr,
+				    &keysock_opt_obj, B_FALSE);
+			} else {
+				(void) tpi_optcom_req(q, mp, cr,
+				    &keysock_opt_obj, B_FALSE);
+			}
 			break;
 		case T_DATA_REQ:
 		case T_EXDATA_REQ:
@@ -943,7 +955,6 @@
 			keysock_err_ack(q, mp, TNOTSUPPORT, 0);
 			break;
 		}
-		crfree(cr);
 		return;
 	case M_IOCTL:
 		iocp = (struct iocblk *)mp->b_rptr;
diff --git a/usr/src/uts/common/inet/ip/rts.c b/usr/src/uts/common/inet/ip/rts.c
index 0bc00f6..ce3ac6f 100644
--- a/usr/src/uts/common/inet/ip/rts.c
+++ b/usr/src/uts/common/inet/ip/rts.c
@@ -114,7 +114,7 @@
 static void 	rts_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error,
     int sys_error);
 static void	rts_input(void *, mblk_t *, void *);
-static mblk_t	*rts_ioctl_alloc(mblk_t *data, cred_t *cr);
+static mblk_t	*rts_ioctl_alloc(mblk_t *data);
 static int	rts_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
 static boolean_t rts_param_register(IDP *ndp, rtsparam_t *rtspa, int cnt);
 static int	rts_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
@@ -159,17 +159,17 @@
  * user data.
  */
 static mblk_t *
-rts_ioctl_alloc(mblk_t *data, cred_t *cr)
+rts_ioctl_alloc(mblk_t *data)
 {
 	mblk_t	*mp = NULL;
 	mblk_t	*mp1 = NULL;
 	ipllc_t	*ipllc;
 	struct iocblk	*ioc;
 
-	mp = allocb_cred(sizeof (ipllc_t), cr);
+	mp = allocb_tmpl(sizeof (ipllc_t), data);
 	if (mp == NULL)
 		return (NULL);
-	mp1 = allocb_cred(sizeof (struct iocblk), cr);
+	mp1 = allocb_tmpl(sizeof (struct iocblk), data);
 	if (mp1 == NULL) {
 		freeb(mp);
 		return (NULL);
@@ -1045,7 +1045,9 @@
 	}
 
 
-	mp1 = rts_ioctl_alloc(mp, DB_CRED(mp));
+	ASSERT(msg_getcred(mp, NULL) != NULL);
+
+	mp1 = rts_ioctl_alloc(mp);
 	if (mp1 == NULL) {
 		ASSERT(rts != NULL);
 		freemsg(mp);
@@ -1076,8 +1078,6 @@
 
 	rtss = rts->rts_rtss;
 
-	cr = DB_CREDDEF(mp, connp->conn_cred);
-
 	switch (mp->b_datap->db_type) {
 	case M_PROTO:
 	case M_PCPROTO:
@@ -1104,11 +1104,28 @@
 			rts_info_req(q, mp);
 			return;
 		case T_SVR4_OPTMGMT_REQ:
-			(void) svr4_optcom_req(q, mp, cr, &rts_opt_obj,
-			    B_TRUE);
-			return;
 		case T_OPTMGMT_REQ:
-			(void) tpi_optcom_req(q, mp, cr, &rts_opt_obj, B_TRUE);
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				rts_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
+			if (((union T_primitives *)rptr)->type ==
+			    T_SVR4_OPTMGMT_REQ) {
+				(void) svr4_optcom_req(q, mp, cr,
+				    &rts_opt_obj, B_TRUE);
+			} else {
+				(void) tpi_optcom_req(q, mp, cr,
+				    &rts_opt_obj, B_TRUE);
+			}
 			return;
 		case O_T_CONN_RES:
 		case T_CONN_RES:
@@ -1537,7 +1554,7 @@
 	rtm = (rt_msghdr_t *)mp->b_rptr;
 	rtm->rtm_pid = curproc->p_pid;
 
-	mp1 = rts_ioctl_alloc(mp, DB_CRED(mp));
+	mp1 = rts_ioctl_alloc(mp);
 	if (mp1 == NULL) {
 		ASSERT(rts != NULL);
 		freemsg(mp);
@@ -1567,8 +1584,7 @@
 
 	CONN_INC_REF(connp);
 
-	error = ip_rts_request_common(rts->rts_connp->conn_wq, mp1, connp,
-	    DB_CREDDEF(mp, connp->conn_cred));
+	error = ip_rts_request_common(rts->rts_connp->conn_wq, mp1, connp, cr);
 
 	mutex_enter(&rts->rts_send_mutex);
 	if (error == EINPROGRESS) {
diff --git a/usr/src/uts/common/inet/ip/sadb.c b/usr/src/uts/common/inet/ip/sadb.c
index 189b6ad..eff4dfc 100644
--- a/usr/src/uts/common/inet/ip/sadb.c
+++ b/usr/src/uts/common/inet/ip/sadb.c
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/stropts.h>
+#include <sys/strsubr.h>
 #include <sys/errno.h>
 #include <sys/ddi.h>
 #include <sys/debug.h>
@@ -6175,7 +6176,7 @@
 	struct T_bind_req *tbr;
 	mblk_t *mp;
 
-	mp = allocb(sizeof (struct T_bind_req) + 1, BPRI_HI);
+	mp = allocb_cred(sizeof (struct T_bind_req) + 1, kcred, NOPID);
 	if (mp == NULL) {
 		/* cmn_err(CE_WARN, */
 		/* "sadb_t_bind_req(%d): couldn't allocate mblk\n", proto); */
diff --git a/usr/src/uts/common/inet/ip/spdsock.c b/usr/src/uts/common/inet/ip/spdsock.c
index 749db40..a0e63ac 100644
--- a/usr/src/uts/common/inet/ip/spdsock.c
+++ b/usr/src/uts/common/inet/ip/spdsock.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -591,10 +591,13 @@
 		spdsock_flush_one(iph, ns);
 		if (audit_active) {
 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+			cred_t *cr;
+			pid_t cpid;
 
+			cr = msg_getcred(mp, &cpid);
 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-			audit_pf_policy(SPD_FLUSH, DB_CRED(mp), ns,
-			    ITP_NAME(itp), active, 0, DB_CPID(mp));
+			audit_pf_policy(SPD_FLUSH, cr, ns,
+			    ITP_NAME(itp), active, 0, cpid);
 		}
 	} else {
 		active = (iph == ALL_ACTIVE_POLHEADS);
@@ -603,14 +606,23 @@
 		spdsock_flush_one(active ? ipsec_system_policy(ns) :
 		    ipsec_inactive_policy(ns), ns);
 		if (audit_active) {
-			audit_pf_policy(SPD_FLUSH, DB_CRED(mp), ns, NULL,
-			    active, 0, DB_CPID(mp));
+			cred_t *cr;
+			pid_t cpid;
+
+			cr = msg_getcred(mp, &cpid);
+			audit_pf_policy(SPD_FLUSH, cr, ns, NULL,
+			    active, 0, cpid);
 		}
 		/* Then flush every tunnel's appropriate one. */
 		itp_walk(spdsock_flush_node, (void *)active, ns);
-		if (audit_active)
-			audit_pf_policy(SPD_FLUSH, DB_CRED(mp), ns,
-			    "all tunnels", active, 0, DB_CPID(mp));
+		if (audit_active) {
+			cred_t *cr;
+			pid_t cpid;
+
+			cr = msg_getcred(mp, &cpid);
+			audit_pf_policy(SPD_FLUSH, cr, ns,
+			    "all tunnels", active, 0, cpid);
+		}
 	}
 
 	spd_echo(q, mp);
@@ -1014,11 +1026,14 @@
 		spdsock_diag(q, mp, SPD_DIAGNOSTIC_NO_RULE_EXT);
 		if (audit_active) {
 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+			cred_t *cr;
+			pid_t cpid;
 
+			cr = msg_getcred(mp, &cpid);
 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-			audit_pf_policy(SPD_ADDRULE, DB_CRED(mp),
+			audit_pf_policy(SPD_ADDRULE, cr,
 			    spds->spds_netstack, ITP_NAME(itp), active,
-			    SPD_DIAGNOSTIC_NO_RULE_EXT, DB_CPID(mp));
+			    SPD_DIAGNOSTIC_NO_RULE_EXT, cpid);
 		}
 		return;
 	}
@@ -1121,10 +1136,13 @@
 	spd_echo(q, mp);
 	if (audit_active) {
 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+		cred_t *cr;
+		pid_t cpid;
 
+		cr = msg_getcred(mp, &cpid);
 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-		audit_pf_policy(SPD_ADDRULE, DB_CRED(mp), spds->spds_netstack,
-		    ITP_NAME(itp), active, 0, DB_CPID(mp));
+		audit_pf_policy(SPD_ADDRULE, cr, spds->spds_netstack,
+		    ITP_NAME(itp), active, 0, cpid);
 	}
 	return;
 
@@ -1143,10 +1161,13 @@
 	spdsock_error(q, mp, error, diag);
 	if (audit_active) {
 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+		cred_t *cr;
+		pid_t cpid;
 
+		cr = msg_getcred(mp, &cpid);
 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-		audit_pf_policy(SPD_ADDRULE, DB_CRED(mp), spds->spds_netstack,
-		    ITP_NAME(itp), active, error, DB_CPID(mp));
+		audit_pf_policy(SPD_ADDRULE, cr, spds->spds_netstack,
+		    ITP_NAME(itp), active, error, cpid);
 	}
 }
 
@@ -1165,11 +1186,14 @@
 		if (audit_active) {
 			boolean_t active;
 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+			cred_t *cr;
+			pid_t cpid;
 
+			cr = msg_getcred(mp, &cpid);
 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-			audit_pf_policy(SPD_DELETERULE, DB_CRED(mp), ns,
+			audit_pf_policy(SPD_DELETERULE, cr, ns,
 			    ITP_NAME(itp), active, SPD_DIAGNOSTIC_NO_RULE_EXT,
-			    DB_CPID(mp));
+			    cpid);
 		}
 		return;
 	}
@@ -1223,10 +1247,13 @@
 	if (audit_active) {
 		boolean_t active;
 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+		cred_t *cr;
+		pid_t cpid;
 
+		cr = msg_getcred(mp, &cpid);
 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-		audit_pf_policy(SPD_DELETERULE, DB_CRED(mp), ns, ITP_NAME(itp),
-		    active, 0, DB_CPID(mp));
+		audit_pf_policy(SPD_DELETERULE, cr, ns, ITP_NAME(itp),
+		    active, 0, cpid);
 	}
 	return;
 fail:
@@ -1236,10 +1263,13 @@
 	if (audit_active) {
 		boolean_t active;
 		spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+		cred_t *cr;
+		pid_t cpid;
 
+		cr = msg_getcred(mp, &cpid);
 		active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-		audit_pf_policy(SPD_DELETERULE, DB_CRED(mp), ns, ITP_NAME(itp),
-		    active, err, DB_CPID(mp));
+		audit_pf_policy(SPD_DELETERULE, cr, ns, ITP_NAME(itp),
+		    active, err, cpid);
 	}
 }
 
@@ -1270,19 +1300,25 @@
 			if (audit_active) {
 				boolean_t active;
 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+				cred_t *cr;
+				pid_t cpid;
 
+				cr = msg_getcred(mp, &cpid);
 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-				audit_pf_policy(SPD_FLIP, DB_CRED(mp),
-				    ns, NULL, active, 0, DB_CPID(mp));
+				audit_pf_policy(SPD_FLIP, cr, ns,
+				    NULL, active, 0, cpid);
 			}
 			itp_walk(spdsock_flip_node, NULL, ns);
 			if (audit_active) {
 				boolean_t active;
 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+				cred_t *cr;
+				pid_t cpid;
 
+				cr = msg_getcred(mp, &cpid);
 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-				audit_pf_policy(SPD_FLIP, DB_CRED(mp), ns,
-				    "all tunnels", active, 0, DB_CPID(mp));
+				audit_pf_policy(SPD_FLIP, cr, ns,
+				    "all tunnels", active, 0, cpid);
 			}
 		} else {
 			itp = get_tunnel_policy(tname, ns);
@@ -1293,12 +1329,15 @@
 					boolean_t active;
 					spd_msg_t *spmsg =
 					    (spd_msg_t *)mp->b_rptr;
+					cred_t *cr;
+					pid_t cpid;
 
+					cr = msg_getcred(mp, &cpid);
 					active = (spmsg->spd_msg_spdid ==
 					    SPD_ACTIVE);
-					audit_pf_policy(SPD_FLIP, DB_CRED(mp),
-					    ns, ITP_NAME(itp), active,
-					    ESRCH, DB_CPID(mp));
+					audit_pf_policy(SPD_FLIP, cr, ns,
+					    ITP_NAME(itp), active,
+					    ESRCH, cpid);
 				}
 				return;
 			}
@@ -1306,10 +1345,13 @@
 			if (audit_active) {
 				boolean_t active;
 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+				cred_t *cr;
+				pid_t cpid;
 
+				cr = msg_getcred(mp, &cpid);
 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-				audit_pf_policy(SPD_FLIP, DB_CRED(mp), ns,
-				    ITP_NAME(itp), active, 0, DB_CPID(mp));
+				audit_pf_policy(SPD_FLIP, cr, ns,
+				    ITP_NAME(itp), active, 0, cpid);
 			}
 			ITP_REFRELE(itp, ns);
 		}
@@ -1318,10 +1360,13 @@
 		if (audit_active) {
 			boolean_t active;
 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+			cred_t *cr;
+			pid_t cpid;
 
+			cr = msg_getcred(mp, &cpid);
 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-			audit_pf_policy(SPD_FLIP, DB_CRED(mp),
-			    ns, NULL, active, 0, DB_CPID(mp));
+			audit_pf_policy(SPD_FLIP, cr,
+			    ns, NULL, active, 0, cpid);
 		}
 	}
 	spd_echo(q, mp);
@@ -2059,10 +2104,13 @@
 			if (audit_active) {
 				boolean_t active;
 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+				cred_t *cr;
+				pid_t cpid;
 
+				cr = msg_getcred(mp, &cpid);
 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-				audit_pf_policy(SPD_CLONE, DB_CRED(mp), ns,
-				    NULL, active, error, DB_CPID(mp));
+				audit_pf_policy(SPD_CLONE, cr, ns,
+				    NULL, active, error, cpid);
 			}
 			if (error == 0) {
 				itp_walk(spdsock_clone_node, &error, ns);
@@ -2070,12 +2118,15 @@
 					boolean_t active;
 					spd_msg_t *spmsg =
 					    (spd_msg_t *)mp->b_rptr;
+					cred_t *cr;
+					pid_t cpid;
 
+					cr = msg_getcred(mp, &cpid);
 					active = (spmsg->spd_msg_spdid ==
 					    SPD_ACTIVE);
-					audit_pf_policy(SPD_CLONE, DB_CRED(mp),
+					audit_pf_policy(SPD_CLONE, cr,
 					    ns, "all tunnels", active, 0,
-					    DB_CPID(mp));
+					    cpid);
 				}
 			}
 		} else {
@@ -2086,12 +2137,15 @@
 					boolean_t active;
 					spd_msg_t *spmsg =
 					    (spd_msg_t *)mp->b_rptr;
+					cred_t *cr;
+					pid_t cpid;
 
+					cr = msg_getcred(mp, &cpid);
 					active = (spmsg->spd_msg_spdid ==
 					    SPD_ACTIVE);
-					audit_pf_policy(SPD_CLONE, DB_CRED(mp),
+					audit_pf_policy(SPD_CLONE, cr,
 					    ns, ITP_NAME(itp), active, ENOENT,
-					    DB_CPID(mp));
+					    cpid);
 				}
 				return;
 			}
@@ -2100,10 +2154,13 @@
 			if (audit_active) {
 				boolean_t active;
 				spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+				cred_t *cr;
+				pid_t cpid;
 
+				cr = msg_getcred(mp, &cpid);
 				active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-				audit_pf_policy(SPD_CLONE, DB_CRED(mp), ns,
-				    ITP_NAME(itp), active, error, DB_CPID(mp));
+				audit_pf_policy(SPD_CLONE, cr, ns,
+				    ITP_NAME(itp), active, error, cpid);
 			}
 		}
 	} else {
@@ -2111,10 +2168,13 @@
 		if (audit_active) {
 			boolean_t active;
 			spd_msg_t *spmsg = (spd_msg_t *)mp->b_rptr;
+			cred_t *cr;
+			pid_t cpid;
 
+			cr = msg_getcred(mp, &cpid);
 			active = (spmsg->spd_msg_spdid == SPD_ACTIVE);
-			audit_pf_policy(SPD_CLONE, DB_CRED(mp), ns, NULL,
-			    active, error, DB_CPID(mp));
+			audit_pf_policy(SPD_CLONE, cr, ns, NULL,
+			    active, error, cpid);
 		}
 	}
 
@@ -2658,10 +2718,15 @@
 		spds->spds_mp_algs = mp;
 		spds->spds_algs_pending = B_TRUE;
 		mutex_exit(&spds->spds_alg_lock);
-		if (audit_active)
-			audit_pf_policy(SPD_UPDATEALGS, DB_CRED(mp),
+		if (audit_active) {
+			cred_t *cr;
+			pid_t cpid;
+
+			cr = msg_getcred(mp, &cpid);
+			audit_pf_policy(SPD_UPDATEALGS, cr,
 			    spds->spds_netstack, NULL, B_TRUE, EAGAIN,
-			    DB_CPID(mp));
+			    cpid);
+		}
 		spd_echo(q, new_mp);
 	} else {
 		/*
@@ -2674,16 +2739,26 @@
 		mutex_exit(&spds->spds_alg_lock);
 		if (diag == -1) {
 			spd_echo(q, mp);
-		if (audit_active)
-			audit_pf_policy(SPD_UPDATEALGS, DB_CRED(mp),
-			    spds->spds_netstack, NULL, B_TRUE, 0,
-			    DB_CPID(mp));
+			if (audit_active) {
+				cred_t *cr;
+				pid_t cpid;
+
+				cr = msg_getcred(mp, &cpid);
+				audit_pf_policy(SPD_UPDATEALGS, cr,
+				    spds->spds_netstack, NULL, B_TRUE, 0,
+				    cpid);
+			}
 		} else {
 			spdsock_diag(q, mp, diag);
-		if (audit_active)
-			audit_pf_policy(SPD_UPDATEALGS, DB_CRED(mp),
-			    spds->spds_netstack, NULL, B_TRUE, diag,
-			    DB_CPID(mp));
+			if (audit_active) {
+				cred_t *cr;
+				pid_t cpid;
+
+				cr = msg_getcred(mp, &cpid);
+				audit_pf_policy(SPD_UPDATEALGS, cr,
+				    spds->spds_netstack, NULL, B_TRUE, diag,
+				    cpid);
+			}
 		}
 	}
 }
@@ -3228,10 +3303,6 @@
 			freemsg(mp);
 			return;
 		}
-		cr = zone_get_kcred(netstackid_to_zoneid(
-		    spds->spds_netstack->netstack_stackid));
-		ASSERT(cr != NULL);
-
 		switch (((union T_primitives *)mp->b_rptr)->type) {
 		case T_CAPABILITY_REQ:
 			spdsock_capability_req(q, mp);
@@ -3240,12 +3311,28 @@
 			spdsock_info_req(q, mp);
 			break;
 		case T_SVR4_OPTMGMT_REQ:
-			(void) svr4_optcom_req(q, mp, DB_CREDDEF(mp, cr),
-			    &spdsock_opt_obj, B_FALSE);
-			break;
 		case T_OPTMGMT_REQ:
-			(void) tpi_optcom_req(q, mp, DB_CREDDEF(mp, cr),
-			    &spdsock_opt_obj, B_FALSE);
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				spdsock_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
+			if (((union T_primitives *)mp->b_rptr)->type ==
+			    T_SVR4_OPTMGMT_REQ) {
+				(void) svr4_optcom_req(q, mp, cr,
+				    &spdsock_opt_obj, B_FALSE);
+			} else {
+				(void) tpi_optcom_req(q, mp, cr,
+				    &spdsock_opt_obj, B_FALSE);
+			}
 			break;
 		case T_DATA_REQ:
 		case T_EXDATA_REQ:
@@ -3259,7 +3346,6 @@
 			spdsock_err_ack(q, mp, TNOTSUPPORT, 0);
 			break;
 		}
-		crfree(cr);
 		return;
 	case M_IOCTL:
 		iocp = (struct iocblk *)mp->b_rptr;
diff --git a/usr/src/uts/common/inet/ip/tn_ipopt.c b/usr/src/uts/common/inet/ip/tn_ipopt.c
index 7c6f713..c187c8c 100644
--- a/usr/src/uts/common/inet/ip/tn_ipopt.c
+++ b/usr/src/uts/common/inet/ip/tn_ipopt.c
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/systm.h>
 #include <sys/kmem.h>
@@ -211,6 +209,8 @@
 	tsol_ire_gw_secattr_t *attrp;
 	zoneid_t	zoneid, ip_zoneid;
 
+	ASSERT(credp != NULL);
+
 	if (opt_storage != NULL)
 		opt_storage[IPOPT_OLEN] = 0;
 
@@ -674,8 +674,8 @@
 		copylen = MBLKL(mp);
 		if (copylen > 256)
 			copylen = 256;
-		new_mp = allocb_cred(hlen + copylen +
-		    (mp->b_rptr - mp->b_datap->db_base), DB_CRED(mp));
+		new_mp = allocb_tmpl(hlen + copylen +
+		    (mp->b_rptr - mp->b_datap->db_base), mp);
 		if (new_mp == NULL)
 			return (ENOMEM);
 
@@ -744,6 +744,8 @@
 	tsol_ire_gw_secattr_t *attrp;
 	boolean_t	compute_label;
 
+	ASSERT(credp != NULL);
+
 	if (ip6opt_ls == 0)
 		return (EINVAL);
 
@@ -1249,8 +1251,8 @@
 			copylen = 256;
 		if (copylen < hdr_len)
 			copylen = hdr_len;
-		new_mp = allocb_cred(hlen + copylen +
-		    (mp->b_rptr - mp->b_datap->db_base), DB_CRED(mp));
+		new_mp = allocb_tmpl(hlen + copylen +
+		    (mp->b_rptr - mp->b_datap->db_base), mp);
 		if (new_mp == NULL)
 			return (ENOMEM);
 
diff --git a/usr/src/uts/common/inet/ip/tnet.c b/usr/src/uts/common/inet/ip/tnet.c
index 84fce1b..57104e5 100644
--- a/usr/src/uts/common/inet/ip/tnet.c
+++ b/usr/src/uts/common/inet/ip/tnet.c
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/strsubr.h>
@@ -684,6 +682,8 @@
 	const cipso_option_t *co;
 	const void	*src;
 	const ip6_t	*ip6h;
+	cred_t		*credp;
+	pid_t		cpid;
 
 	ASSERT(DB_TYPE(mp) == M_DATA);
 
@@ -824,33 +824,36 @@
 
 	/* Make sure no other thread is messing with this mblk */
 	ASSERT(DB_REF(mp) == 1);
-	if (DB_CRED(mp) == NULL) {
-		DB_CRED(mp) = newcred_from_bslabel(&sl, doi, KM_NOSLEEP);
-		if (DB_CRED(mp) == NULL)
+	/* Preserve db_cpid */
+	credp = msg_extractcred(mp, &cpid);
+	if (credp == NULL) {
+		credp = newcred_from_bslabel(&sl, doi, KM_NOSLEEP);
+		if (credp == NULL)
 			return (B_FALSE);
+		mblk_setcred(mp, credp, cpid);
 	} else {
 		cred_t	*newcr;
 
-		newcr = copycred_from_bslabel(DB_CRED(mp), &sl, doi,
+		newcr = copycred_from_bslabel(credp, &sl, doi,
 		    KM_NOSLEEP);
+		crfree(credp);
 		if (newcr == NULL)
 			return (B_FALSE);
-		crfree(DB_CRED(mp));
-		DB_CRED(mp) = newcr;
+		mblk_setcred(mp, newcr, cpid);
+		credp = newcr;
 	}
 
 	/*
 	 * If the source was unlabeled, then flag as such,
 	 * while remembering that CIPSO routers add headers.
 	 */
-	if (label_type == OPT_NONE)
-		crgetlabel(DB_CRED(mp))->tsl_flags |= TSLF_UNLABELED;
-	else if (label_type == OPT_CIPSO) {
+	if (label_type == OPT_NONE) {
+		crgetlabel(credp)->tsl_flags |= TSLF_UNLABELED;
+	} else if (label_type == OPT_CIPSO) {
 		if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
 			return (B_FALSE);
 		if (src_rhtp->tpc_tp.host_type == UNLABELED)
-			crgetlabel(DB_CRED(mp))->tsl_flags |=
-			    TSLF_UNLABELED;
+			crgetlabel(credp)->tsl_flags |= TSLF_UNLABELED;
 		TPC_RELE(src_rhtp);
 	}
 
@@ -882,7 +885,7 @@
 	 * We trust that all valid paths in the code set the cred pointer when
 	 * needed.
 	 */
-	if ((credp = DB_CRED(mp)) == NULL)
+	if ((credp = msg_getcred(mp, NULL)) == NULL)
 		return (B_TRUE);
 
 	/*
@@ -1020,9 +1023,11 @@
 	ts_label_t	*plabel = NULL;
 	tsol_tpc_t	*src_rhtp, *dst_rhtp;
 	boolean_t	retv;
+	cred_t		*credp;
 
-	if (DB_CRED(mp) != NULL)
-		plabel = crgetlabel(DB_CRED(mp));
+	credp = msg_getcred(mp, NULL);
+	if (credp != NULL)
+		plabel = crgetlabel(credp);
 
 	/* We are bootstrapping or the internal template was never deleted */
 	if (plabel == NULL)
@@ -1119,6 +1124,7 @@
 	const ip6_t	*ip6h;
 	boolean_t	retv;
 	bslabel_t	*pktbs;
+	cred_t		*credp;
 
 	/* Caller must pull up at least the IP header */
 	ASSERT(MBLKL(mp) >= (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ?
@@ -1127,8 +1133,9 @@
 	if (!tsol_strict_error)
 		return (B_TRUE);
 
-	if (DB_CRED(mp) != NULL)
-		plabel = crgetlabel(DB_CRED(mp));
+	credp = msg_getcred(mp, NULL);
+	if (credp != NULL)
+		plabel = crgetlabel(credp);
 
 	/* We are bootstrapping or the internal template was never deleted */
 	if (plabel == NULL)
@@ -1196,7 +1203,7 @@
 zoneid_t
 tsol_packet_to_zoneid(const mblk_t *mp)
 {
-	cred_t *cr = DB_CRED(mp);
+	cred_t *cr = msg_getcred(mp, NULL);
 	zone_t *zone;
 	ts_label_t *label;
 
@@ -1471,6 +1478,7 @@
 	boolean_t	need_tpc_rele = B_FALSE;
 	ipaddr_t	*gw;
 	ip_stack_t	*ipst = ire->ire_ipst;
+	cred_t		*credp;
 
 	ASSERT(ire != NULL && mp != NULL);
 	ASSERT(ire->ire_stq != NULL);
@@ -1517,7 +1525,7 @@
 		off_link = !IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6);
 	}
 
-	if ((tsl = MBLK_GETLABEL(mp)) == NULL)
+	if ((tsl = msg_getlabel(mp)) == NULL)
 		return (mp);
 
 	label_type = tsol_get_option(mp, &opt_ptr);
@@ -1669,10 +1677,12 @@
 	    (!off_link || gw_rhtp->tpc_tp.host_type == UNLABELED))
 		goto keep_label;
 
+
+	credp = msg_getcred(mp, NULL);
 	if ((af == AF_INET &&
-	    tsol_check_label(DB_CRED(mp), &mp, B_FALSE, ipst) != 0) ||
+	    tsol_check_label(credp, &mp, B_FALSE, ipst) != 0) ||
 	    (af == AF_INET6 &&
-	    tsol_check_label_v6(DB_CRED(mp), &mp, B_FALSE, ipst) != 0)) {
+	    tsol_check_label_v6(credp, &mp, B_FALSE, ipst) != 0)) {
 		mp = NULL;
 		goto keep_label;
 	}
diff --git a/usr/src/uts/common/inet/ip/tun.c b/usr/src/uts/common/inet/ip/tun.c
index 632601b..dc5af5e 100644
--- a/usr/src/uts/common/inet/ip/tun.c
+++ b/usr/src/uts/common/inet/ip/tun.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,6 +35,7 @@
 #include <sys/stream.h>
 #include <sys/dlpi.h>
 #include <sys/stropts.h>
+#include <sys/strsubr.h>
 #include <sys/strlog.h>
 #include <sys/tihdr.h>
 #include <sys/tiuser.h>
@@ -396,6 +397,8 @@
 	atp->tun_dev = *devp;
 	atp->tun_zoneid = zoneid;
 	atp->tun_netstack = ns;
+	atp->tun_cred = credp;
+	crhold(credp);
 
 	/*
 	 * Based on the lower version of IP, initialize stuff that
@@ -429,6 +432,7 @@
 		atp->tun_ip6h.ip6_hops = IPV6_DEFAULT_HOPS;
 	} else {
 		netstack_rele(ns);
+		crfree(credp);
 		kmem_free(atp, sizeof (tun_t));
 		return (ENXIO);
 	}
@@ -449,6 +453,7 @@
 		} else {
 			/* Error. */
 			netstack_rele(ns);
+			crfree(credp);
 			kmem_free(atp, sizeof (tun_t));
 			return (ENXIO);
 		}
@@ -463,6 +468,7 @@
 		} else {
 			/* Error. */
 			netstack_rele(ns);
+			crfree(credp);
 			kmem_free(atp, sizeof (tun_t));
 			return (ENXIO);
 		}
@@ -501,6 +507,9 @@
 
 	qprocsoff(q);
 
+	crfree(atp->tun_cred);
+	atp->tun_cred = NULL;
+
 	/* NOTE:  tun_rem_ppa_list() may unlink tun_itp from its AVL tree. */
 	if (atp->tun_stats != NULL)
 		tun_rem_ppa_list(atp);
@@ -4734,8 +4743,7 @@
 		if ((mp->b_rptr - mp->b_datap->db_base) < hdrlen) {
 			/* no */
 
-			nmp = allocb_cred(hdrlen + atp->tun_extra_offset,
-			    DB_CRED(mp));
+			nmp = allocb_tmpl(hdrlen + atp->tun_extra_offset, mp);
 			if (nmp == NULL) {
 				atomic_add_32(&atp->tun_OutDiscard, 1);
 				atomic_add_32(&atp->tun_allocbfail, 1);
@@ -4779,8 +4787,7 @@
 
 		if ((mp->b_rptr - mp->b_datap->db_base) < hdrlen) {
 			/* no */
-			nmp = allocb_cred(hdrlen + atp->tun_extra_offset,
-			    DB_CRED(mp));
+			nmp = allocb_tmpl(hdrlen + atp->tun_extra_offset, mp);
 			if (nmp == NULL) {
 				atomic_add_32(&atp->tun_OutDiscard, 1);
 				atomic_add_32(&atp->tun_allocbfail, 1);
@@ -5257,8 +5264,8 @@
 		if ((mp->b_rptr - mp->b_datap->db_base) < sizeof (ipha_t)) {
 			/* no */
 
-			nmp = allocb_cred(sizeof (ipha_t) +
-			    atp->tun_extra_offset, DB_CRED(mp));
+			nmp = allocb_tmpl(sizeof (ipha_t) +
+			    atp->tun_extra_offset, mp);
 			if (nmp == NULL) {
 				atomic_add_32(&atp->tun_OutDiscard, 1);
 				atomic_add_32(&atp->tun_allocbfail, 1);
@@ -5444,8 +5451,7 @@
 
 		if ((mp->b_rptr - mp->b_datap->db_base) < hdrlen) {
 			/* no */
-			nmp = allocb_cred(hdrlen + atp->tun_extra_offset,
-			    DB_CRED(mp));
+			nmp = allocb_tmpl(hdrlen + atp->tun_extra_offset, mp);
 			if (nmp == NULL) {
 				atomic_add_32(&atp->tun_OutDiscard, 1);
 				atomic_add_32(&atp->tun_allocbfail, 1);
@@ -5568,6 +5574,7 @@
 		freeb(mp);
 		return (ENOMEM);
 	}
+	mblk_setcred(mp, atp->tun_cred, NOPID);
 	mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
 	tbr = (struct T_bind_req *)mp->b_rptr;
 	tbr->CONIND_number = 0;
diff --git a/usr/src/uts/common/inet/ip6.h b/usr/src/uts/common/inet/ip6.h
index cc425db..5408ab9 100644
--- a/usr/src/uts/common/inet/ip6.h
+++ b/usr/src/uts/common/inet/ip6.h
@@ -392,7 +392,7 @@
     const in6_addr_t *, uint16_t, boolean_t);
 extern int	ip_proto_bind_connected_v6(conn_t *, mblk_t **,
     uint8_t, in6_addr_t *, uint16_t, const in6_addr_t *, ip6_pkt_t *,
-    uint16_t, boolean_t, boolean_t);
+    uint16_t, boolean_t, boolean_t, cred_t *);
 
 #endif	/* _KERNEL */
 
diff --git a/usr/src/uts/common/inet/ipclassifier.h b/usr/src/uts/common/inet/ipclassifier.h
index d80123a..2ecc445 100644
--- a/usr/src/uts/common/inet/ipclassifier.h
+++ b/usr/src/uts/common/inet/ipclassifier.h
@@ -135,7 +135,6 @@
 #define	IPCL_IS_RTS(connp)						\
 	((connp)->conn_flags & IPCL_RTSCONN)
 
-/* FIXME: Isn't it sufficient to check IPCL_IPTUN? */
 #define	IPCL_IS_IPTUN(connp)						\
 	(((connp)->conn_ulp == IPPROTO_ENCAP ||				\
 	(connp)->conn_ulp == IPPROTO_IPV6) &&				\
@@ -316,7 +315,7 @@
 	in6_addr_t	conn_nexthop_v6;	/* nexthop IP address */
 	uchar_t		conn_broadcast_ttl; 	/* IP_BROADCAST_TTL */
 #define	conn_nexthop_v4	V4_PART_OF_V6(conn_nexthop_v6)
-	cred_t		*conn_peercred;		/* Peer credentials, if any */
+	cred_t		*conn_peercred;		/* Peer TX label, if any */
 	int		conn_rtaware; 		/* RT_AWARE sockopt value */
 	kcondvar_t	conn_sq_cv;		/* For non-STREAMS socket IO */
 	kthread_t	*conn_sq_caller;	/* Caller of squeue sync ops */
@@ -341,10 +340,17 @@
 #endif
 };
 
+/*
+ * These two macros are used by TX. First priority is SCM_UCRED having
+ * set the label in the mblk. Second priority is the peers label (aka
+ * conn_peercred). Last priority is the open credentials.
+ * BEST_CRED takes all three into account in the above order.
+ * CONN_CRED is for connection-oriented cases when we don't need to look
+ * at the mblk.
+ */
 #define	CONN_CRED(connp) ((connp)->conn_peercred == NULL ? \
 	(connp)->conn_cred : (connp)->conn_peercred)
-#define	BEST_CRED(mp, connp) ((DB_CRED(mp) != NULL &&	\
-	crgetlabel(DB_CRED(mp)) != NULL) ? DB_CRED(mp) : CONN_CRED(connp))
+#define	BEST_CRED(mp, connp) ip_best_cred(mp, connp)
 
 /*
  * connf_t - connection fanout data.
diff --git a/usr/src/uts/common/inet/optcom.c b/usr/src/uts/common/inet/optcom.c
index f241599..e35b7f6 100644
--- a/usr/src/uts/common/inet/optcom.c
+++ b/usr/src/uts/common/inet/optcom.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1990 Mentat Inc. */
@@ -444,7 +444,7 @@
 		 */
 		max_optbuf_len = optcom_max_optbuf_len(opt_arr,
 		    opt_arr_cnt);
-		mp1 = allocb_cred(max_optbuf_len, cr);
+		mp1 = allocb_tmpl(max_optbuf_len, mp);
 		if (!mp1)
 			goto no_mem;
 		/* Initialize the header. */
@@ -694,7 +694,7 @@
 	 * the operation.
 	 */
 
-	toa_mp = allocb_cred(toa_len, cr);
+	toa_mp = allocb_tmpl(toa_len, mp);
 	if (!toa_mp) {
 		optcom_err_ack(q, mp, TSYSERR, ENOMEM);
 		return (0);
@@ -2210,7 +2210,7 @@
 int
 process_auxiliary_options(conn_t *connp, void *control, t_uscalar_t controllen,
     void *optbuf, optdb_obj_t *dbobjp, int (*opt_set_fn)(conn_t *, uint_t, int,
-    int, uint_t, uchar_t *, uint_t *, uchar_t *, void *, cred_t *))
+    int, uint_t, uchar_t *, uint_t *, uchar_t *, void *, cred_t *), cred_t *cr)
 {
 	struct cmsghdr *cmsg;
 	opdes_t *optd;
@@ -2231,10 +2231,10 @@
 		if (optd == NULL) {
 			return (EINVAL);
 		}
-		if (OA_READONLY_PERMISSION(optd, connp->conn_cred)) {
+		if (OA_READONLY_PERMISSION(optd, cr)) {
 			return (EACCES);
 		}
-		if (OA_MATCHED_PRIV(optd, connp->conn_cred)) {
+		if (OA_MATCHED_PRIV(optd, cr)) {
 			/*
 			 * For privileged options, we DO perform
 			 * access checks as is common sense
@@ -2254,8 +2254,7 @@
 		}
 		error = opt_set_fn(connp, SETFN_UD_NEGOTIATE, optd->opdes_level,
 		    optd->opdes_name, len, (uchar_t *)CMSG_CONTENT(cmsg),
-		    &outlen, (uchar_t *)CMSG_CONTENT(cmsg), (void *)optbuf,
-		    connp->conn_cred);
+		    &outlen, (uchar_t *)CMSG_CONTENT(cmsg), (void *)optbuf, cr);
 		if (error > 0) {
 			return (error);
 		} else if (outlen > len) {
diff --git a/usr/src/uts/common/inet/optcom.h b/usr/src/uts/common/inet/optcom.h
index 07cb7cf..df4f227 100644
--- a/usr/src/uts/common/inet/optcom.h
+++ b/usr/src/uts/common/inet/optcom.h
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1990 Mentat Inc. */
@@ -222,7 +222,7 @@
 
 extern int process_auxiliary_options(conn_t *, void *, t_uscalar_t,
     void *, optdb_obj_t *, int (*)(conn_t *, uint_t, int, int, uint_t,
-    uchar_t *, uint_t *, uchar_t *, void *, cred_t *));
+    uchar_t *, uint_t *, uchar_t *, void *, cred_t *), cred_t *);
 
 #endif	/* defined(_KERNEL) && defined(__STDC__) */
 
diff --git a/usr/src/uts/common/inet/sctp/sctp.c b/usr/src/uts/common/inet/sctp/sctp.c
index 1dc96a6..7a64587 100644
--- a/usr/src/uts/common/inet/sctp/sctp.c
+++ b/usr/src/uts/common/inet/sctp/sctp.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -242,6 +242,8 @@
 
 	connp->conn_allzones = pconnp->conn_allzones;
 	connp->conn_zoneid = pconnp->conn_zoneid;
+	sctp->sctp_cpid = psctp->sctp_cpid;
+	sctp->sctp_open_time = lbolt64;
 
 	sctp->sctp_mss = psctp->sctp_mss;
 	sctp->sctp_detached = B_TRUE;
@@ -1484,6 +1486,9 @@
 		sctp->sctp_zoneid = zoneid;
 	}
 
+	sctp->sctp_cpid = curproc->p_pid;
+	sctp->sctp_open_time = lbolt64;
+
 	sctp_connp->conn_cred = credp;
 	crhold(credp);
 
diff --git a/usr/src/uts/common/inet/sctp/sctp_common.c b/usr/src/uts/common/inet/sctp/sctp_common.c
index 7c00010..82b7113 100644
--- a/usr/src/uts/common/inet/sctp/sctp_common.c
+++ b/usr/src/uts/common/inet/sctp/sctp_common.c
@@ -342,7 +342,7 @@
 	}
 
 	mp = allocb_cred(ipsctplen + sctps->sctps_wroff_xtra + trailer,
-	    CONN_CRED(sctp->sctp_connp));
+	    CONN_CRED(sctp->sctp_connp), sctp->sctp_cpid);
 	if (mp == NULL) {
 		ip1dbg(("sctp_make_mp: error making mp..\n"));
 		return (NULL);
diff --git a/usr/src/uts/common/inet/sctp/sctp_conn.c b/usr/src/uts/common/inet/sctp/sctp_conn.c
index b4a9b56..7f0522b 100644
--- a/usr/src/uts/common/inet/sctp/sctp_conn.c
+++ b/usr/src/uts/common/inet/sctp/sctp_conn.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -86,7 +86,7 @@
 	aconnp = acceptor->sctp_connp;
 	lconnp = listener->sctp_connp;
 	if (lconnp->conn_mlp_type != mlptSingle) {
-		cr = aconnp->conn_peercred = DB_CRED(cr_pkt);
+		cr = aconnp->conn_peercred = msg_getcred(cr_pkt, NULL);
 		if (cr != NULL)
 			crhold(cr);
 	}
@@ -171,6 +171,8 @@
 	conn_t	*connp, *econnp;
 	sctp_stack_t	*sctps;
 	struct sock_proto_props sopp;
+	cred_t		*cr;
+	pid_t		cpid;
 
 	/*
 	 * No need to check for duplicate as this is the listener
@@ -252,6 +254,9 @@
 		return (NULL);
 	}
 
+	/* Save for getpeerucred */
+	cr = msg_getcred(mp, &cpid);
+
 	err = sctp_accept_comm(sctp, eager, mp, ip_hdr_len, iack);
 	if (err) {
 		sctp_close_eager(eager);
@@ -294,7 +299,7 @@
 
 	/* Connection established, so send up the conn_ind */
 	if ((eager->sctp_ulpd = sctp->sctp_ulp_newconn(sctp->sctp_ulpd,
-	    (sock_lower_handle_t)eager, NULL, NULL, 0,
+	    (sock_lower_handle_t)eager, NULL, cr, cpid,
 	    &eager->sctp_upcalls)) == NULL) {
 		sctp_close_eager(eager);
 		BUMP_MIB(&sctps->sctps_mib, sctpListenDrop);
diff --git a/usr/src/uts/common/inet/sctp/sctp_cookie.c b/usr/src/uts/common/inet/sctp/sctp_cookie.c
index 3fe6f68..e3a6cc4 100644
--- a/usr/src/uts/common/inet/sctp/sctp_cookie.c
+++ b/usr/src/uts/common/inet/sctp/sctp_cookie.c
@@ -586,8 +586,10 @@
 	 * added to cover this possibility.
 	 */
 	if (sctp->sctp_connp->conn_mlp_type != mlptSingle) {
-		initlabel = MBLK_GETLABEL(initmp);
-		if (initlabel == NULL) {
+		pid_t cpid;
+
+		cr = msg_getcred(initmp, &cpid);
+		if (cr == NULL || (initlabel = crgetlabel(cr)) == NULL) {
 			sctp_send_abort(sctp, sctp_init2vtag(ch),
 			    SCTP_ERR_UNKNOWN, NULL, 0, initmp, 0, B_FALSE);
 			return;
@@ -599,11 +601,12 @@
 			    SCTP_ERR_NO_RESOURCES, NULL, 0, initmp, 0, B_FALSE);
 			return;
 		}
-		iackmp = allocb_cred(ipsctplen + sctps->sctps_wroff_xtra, cr);
+		iackmp = allocb_cred(ipsctplen + sctps->sctps_wroff_xtra,
+		    cr, cpid);
 		crfree(cr);
 	} else {
 		iackmp = allocb_cred(ipsctplen + sctps->sctps_wroff_xtra,
-		    CONN_CRED(sctp->sctp_connp));
+		    CONN_CRED(sctp->sctp_connp), sctp->sctp_cpid);
 	}
 	if (iackmp == NULL) {
 		sctp_send_abort(sctp, sctp_init2vtag(ch),
@@ -767,7 +770,7 @@
 
 	iackmp->b_cont = errmp;		/*  OK if NULL */
 
-	if (is_system_labeled() && (cr = DB_CRED(iackmp)) != NULL &&
+	if (is_system_labeled() && (cr = msg_getcred(iackmp, NULL)) != NULL &&
 	    crgetlabel(cr) != NULL) {
 		conn_t *connp = sctp->sctp_connp;
 		int err;
@@ -897,8 +900,8 @@
 	else
 		hdrlen = sctp->sctp_hdr6_len;
 
-	cemp = allocb(sctps->sctps_wroff_xtra + hdrlen + ceclen + pad,
-	    BPRI_MED);
+	cemp = allocb_cred(sctps->sctps_wroff_xtra + hdrlen + ceclen + pad,
+	    CONN_CRED(sctp->sctp_connp), sctp->sctp_cpid);
 	if (cemp == NULL) {
 		SCTP_FADDR_TIMER_RESTART(sctp, sctp->sctp_current,
 		    sctp->sctp_current->rto);
diff --git a/usr/src/uts/common/inet/sctp/sctp_error.c b/usr/src/uts/common/inet/sctp/sctp_error.c
index 9e8daf5..02db60c 100644
--- a/usr/src/uts/common/inet/sctp/sctp_error.c
+++ b/usr/src/uts/common/inet/sctp/sctp_error.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -193,7 +193,7 @@
 		return;
 
 	hmp = allocb_cred(sctps->sctps_wroff_xtra + ahlen,
-	    CONN_CRED(sctp->sctp_connp));
+	    CONN_CRED(sctp->sctp_connp), sctp->sctp_cpid);
 	if (hmp == NULL) {
 		/* XXX no resources */
 		return;
@@ -262,7 +262,7 @@
 
 	ipst = sctps->sctps_netstack->netstack_ip;
 	connp = sctp->sctp_connp;
-	if (is_system_labeled() && (cr = DB_CRED(inmp)) != NULL &&
+	if (is_system_labeled() && (cr = msg_getcred(inmp, NULL)) != NULL &&
 	    crgetlabel(cr) != NULL) {
 		int err;
 		boolean_t exempt = connp->conn_mac_exempt;
diff --git a/usr/src/uts/common/inet/sctp/sctp_impl.h b/usr/src/uts/common/inet/sctp/sctp_impl.h
index 5a137ec..35e5e12 100644
--- a/usr/src/uts/common/inet/sctp/sctp_impl.h
+++ b/usr/src/uts/common/inet/sctp/sctp_impl.h
@@ -935,6 +935,9 @@
 	int		sctp_pd_point;		/* Partial delivery point */
 	mblk_t		*sctp_err_chunks;	/* Error chunks */
 	uint32_t	sctp_err_len;		/* Total error chunks length */
+
+	pid_t		sctp_cpid;	/* Process id when this was opened */
+	uint64_t	sctp_open_time;	/* time when this was opened */
 } sctp_t;
 
 #define	SCTP_TXQ_LEN(sctp)	((sctp)->sctp_unsent + (sctp)->sctp_unacked)
diff --git a/usr/src/uts/common/inet/sctp/sctp_input.c b/usr/src/uts/common/inet/sctp/sctp_input.c
index 87c79ee..749b9cf 100644
--- a/usr/src/uts/common/inet/sctp/sctp_input.c
+++ b/usr/src/uts/common/inet/sctp/sctp_input.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -3522,6 +3522,8 @@
 	sctp_stack_t		*sctps = sctp->sctp_sctps;
 	ip_stack_t		*ipst = sctps->sctps_netstack->netstack_ip;
 	boolean_t		hb_already = B_FALSE;
+	cred_t			*cr;
+	pid_t			cpid;
 
 	if (DB_TYPE(mp) != M_DATA) {
 		ASSERT(DB_TYPE(mp) == M_CTL);
@@ -3879,7 +3881,8 @@
 				if (mlen > ntohs(ch->sch_len)) {
 					eager->sctp_cookie_mp = dupb(mp);
 					mblk_setcred(eager->sctp_cookie_mp,
-					    CONN_CRED(eager->sctp_connp));
+					    CONN_CRED(eager->sctp_connp),
+					    eager->sctp_cpid);
 					/*
 					 * If no mem, just let
 					 * the peer retransmit.
@@ -3950,6 +3953,8 @@
 				sctp_send_initack(sctp, sctph, ch, mp);
 				break;
 			case CHUNK_COOKIE:
+				cr = msg_getcred(mp, &cpid);
+
 				if (sctp_process_cookie(sctp, ch, mp, &iack,
 				    sctph, &recv_adaptation, NULL) == -1) {
 					BUMP_MIB(&sctps->sctps_mib,
@@ -3960,8 +3965,9 @@
 				sctp_stop_faddr_timers(sctp);
 				if (!SCTP_IS_DETACHED(sctp)) {
 					sctp->sctp_ulp_connected(
-					    sctp->sctp_ulpd, 0, NULL, -1);
+					    sctp->sctp_ulpd, 0, cr, cpid);
 					sctp_set_ulp_prop(sctp);
+
 				}
 				sctp->sctp_state = SCTPS_ESTABLISHED;
 				sctp->sctp_assoc_start_time = (uint32_t)lbolt;
@@ -3994,9 +4000,11 @@
 		case SCTPS_COOKIE_ECHOED:
 			switch (ch->sch_id) {
 			case CHUNK_COOKIE_ACK:
+				cr = msg_getcred(mp, &cpid);
+
 				if (!SCTP_IS_DETACHED(sctp)) {
 					sctp->sctp_ulp_connected(
-					    sctp->sctp_ulpd, 0, NULL, -1);
+					    sctp->sctp_ulpd, 0, cr, cpid);
 					sctp_set_ulp_prop(sctp);
 				}
 				if (sctp->sctp_unacked == 0)
@@ -4023,6 +4031,8 @@
 				sctp_process_abort(sctp, ch, ECONNREFUSED);
 				goto done;
 			case CHUNK_COOKIE:
+				cr = msg_getcred(mp, &cpid);
+
 				if (sctp_process_cookie(sctp, ch, mp, &iack,
 				    sctph, &recv_adaptation, NULL) == -1) {
 					BUMP_MIB(&sctps->sctps_mib,
@@ -4033,8 +4043,9 @@
 
 				if (!SCTP_IS_DETACHED(sctp)) {
 					sctp->sctp_ulp_connected(
-					    sctp->sctp_ulpd, 0, NULL, -1);
+					    sctp->sctp_ulpd, 0, cr, cpid);
 					sctp_set_ulp_prop(sctp);
+
 				}
 				if (sctp->sctp_unacked == 0)
 					sctp_stop_faddr_timers(sctp);
diff --git a/usr/src/uts/common/inet/sctp/sctp_ioc.c b/usr/src/uts/common/inet/sctp/sctp_ioc.c
index 53512c7..d92be9b 100644
--- a/usr/src/uts/common/inet/sctp/sctp_ioc.c
+++ b/usr/src/uts/common/inet/sctp/sctp_ioc.c
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/strsubr.h>
@@ -129,7 +127,14 @@
 	}
 
 	iocp = (struct iocblk *)mp->b_rptr;
-	cr = DB_CREDDEF(mp, iocp->ioc_cr);
+	/*
+	 * prefer credential from mblk over ioctl;
+	 * see ip_sioctl_copyin_setup
+	 */
+	cr = msg_getcred(mp, NULL);
+	if (cr == NULL)
+		cr = iocp->ioc_cr;
+
 	switch (iocp->ioc_cmd) {
 	case SCTP_IOC_DEFAULT_Q:
 		/* Wants to be the default wq. */
diff --git a/usr/src/uts/common/inet/sctp/sctp_output.c b/usr/src/uts/common/inet/sctp/sctp_output.c
index 938573b..540177d 100644
--- a/usr/src/uts/common/inet/sctp/sctp_output.c
+++ b/usr/src/uts/common/inet/sctp/sctp_output.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -589,7 +589,7 @@
 		 * or things like snoop is running.
 		 */
 		nmp = allocb_cred(sctps->sctps_wroff_xtra + hdrlen + sacklen,
-		    CONN_CRED(sctp->sctp_connp));
+		    CONN_CRED(sctp->sctp_connp), sctp->sctp_cpid);
 		if (nmp == NULL) {
 			if (error !=  NULL)
 				*error = ENOMEM;
@@ -601,7 +601,7 @@
 		mp = nmp;
 	} else {
 		mp->b_rptr -= (hdrlen + sacklen);
-		mblk_setcred(mp, CONN_CRED(sctp->sctp_connp));
+		mblk_setcred(mp, CONN_CRED(sctp->sctp_connp), sctp->sctp_cpid);
 	}
 	bcopy(hdr, mp->b_rptr, hdrlen);
 	if (sacklen) {
@@ -1381,7 +1381,8 @@
 		xtralen = sctp->sctp_hdr_len + sctps->sctps_wroff_xtra;
 	else
 		xtralen = sctp->sctp_hdr6_len + sctps->sctps_wroff_xtra;
-	ftsn_mp = allocb_cred(xtralen + seglen, CONN_CRED(sctp->sctp_connp));
+	ftsn_mp = allocb_cred(xtralen + seglen, CONN_CRED(sctp->sctp_connp),
+	    sctp->sctp_cpid);
 	if (ftsn_mp == NULL)
 		return (NULL);
 	ftsn_mp->b_rptr += xtralen;
diff --git a/usr/src/uts/common/inet/sockmods/socksctp.c b/usr/src/uts/common/inet/sockmods/socksctp.c
index 39bec0b..48cbe1b 100644
--- a/usr/src/uts/common/inet/sockmods/socksctp.c
+++ b/usr/src/uts/common/inet/sockmods/socksctp.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -672,7 +672,8 @@
 		 * packets, each mblk will have the extra space before
 		 * data to accommodate what SCTP wants to put in there.
 		 */
-		while ((mp = allocb_cred(size + wroff, cr)) == NULL) {
+		while ((mp = allocb_cred(size + wroff, cr,
+		    curproc->p_pid)) == NULL) {
 			if ((uiop->uio_fmode & (FNDELAY|FNONBLOCK)) ||
 			    (flags & MSG_DONTWAIT)) {
 				return (EAGAIN);
@@ -1530,6 +1531,28 @@
 		    (mode & (int)FKIOCTL)))
 			return (EFAULT);
 		return (0);
+	case _I_GETPEERCRED: {
+		int error = 0;
+
+		if ((mode & FKIOCTL) == 0)
+			return (EINVAL);
+
+		mutex_enter(&so->so_lock);
+		if ((so->so_mode & SM_CONNREQUIRED) == 0) {
+			error = ENOTSUP;
+		} else if ((so->so_state & SS_ISCONNECTED) == 0) {
+			error = ENOTCONN;
+		} else if (so->so_peercred != NULL) {
+			k_peercred_t *kp = (k_peercred_t *)arg;
+			kp->pc_cr = so->so_peercred;
+			kp->pc_cpid = so->so_cpid;
+			crhold(so->so_peercred);
+		} else {
+			error = EINVAL;
+		}
+		mutex_exit(&so->so_lock);
+		return (error);
+	}
 	case SIOCSCTPGOPT:
 		STRUCT_INIT(opt, mode);
 
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index f7d078b..95b2551 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -3052,6 +3052,21 @@
 	socklen_t	len;
 	sin_t	*sin;
 	sin6_t	*sin6;
+	cred_t		*cr;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
+		return;
+	}
 
 	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
 	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) {
@@ -3118,7 +3133,7 @@
 		return;
 	}
 
-	error = tcp_bind_check(connp, sa, len, DB_CRED(mp),
+	error = tcp_bind_check(connp, sa, len, cr,
 	    tbr->PRIM_type != O_T_BIND_REQ);
 	if (error == 0) {
 		if (tcp->tcp_family == AF_INET) {
@@ -3130,7 +3145,7 @@
 		}
 
 		if (backlog > 0) {
-			error = tcp_do_listen(connp, backlog, DB_CRED(mp));
+			error = tcp_do_listen(connp, backlog, cr);
 		}
 	}
 done:
@@ -4397,7 +4412,6 @@
 	mblk_t	*mp;
 	char	*optp = NULL;
 	int	optlen = 0;
-	cred_t	*cr;
 
 	if (defermp != NULL)
 		*defermp = NULL;
@@ -4458,17 +4472,18 @@
 	if (!mp)
 		return (B_FALSE);
 
-	if ((cr = DB_CRED(idmp)) != NULL) {
-		mblk_setcred(mp, cr);
-		DB_CPID(mp) = DB_CPID(idmp);
-	}
+	mblk_copycred(mp, idmp);
 
 	if (defermp == NULL) {
 		conn_t *connp = tcp->tcp_connp;
 		if (IPCL_IS_NONSTR(connp)) {
+			cred_t *cr;
+			pid_t cpid;
+
+			cr = msg_getcred(mp, &cpid);
 			(*connp->conn_upcalls->su_connected)
 			    (connp->conn_upper_handle, tcp->tcp_connid, cr,
-			    DB_CPID(mp));
+			    cpid);
 			freemsg(mp);
 		} else {
 			putnext(tcp->tcp_rq, mp);
@@ -4560,7 +4575,6 @@
 	in6_addr_t 	v6dst;
 	int		err;
 	int		ifindex = 0;
-	cred_t		*cr;
 	tcp_stack_t	*tcps = tcp->tcp_tcps;
 
 	if (ipvers == IPV4_VERSION) {
@@ -4796,10 +4810,8 @@
 	 * If the SYN contains a credential, it's a loopback packet; attach
 	 * the credential to the TPI message.
 	 */
-	if ((cr = DB_CRED(idmp)) != NULL) {
-		mblk_setcred(tpi_mp, cr);
-		DB_CPID(tpi_mp) = DB_CPID(idmp);
-	}
+	mblk_copycred(tpi_mp, idmp);
+
 	tcp->tcp_conn.tcp_eager_conn_ind = tpi_mp;
 
 	/* Inherit the listener's SSL protection state */
@@ -4827,7 +4839,6 @@
 	sin_t		sin;
 	mblk_t		*tpi_mp = NULL;
 	int		err;
-	cred_t		*cr;
 	tcp_stack_t	*tcps = tcp->tcp_tcps;
 
 	sin = sin_null;
@@ -4923,10 +4934,8 @@
 	 * If the SYN contains a credential, it's a loopback packet; attach
 	 * the credential to the TPI message.
 	 */
-	if ((cr = DB_CRED(idmp)) != NULL) {
-		mblk_setcred(tpi_mp, cr);
-		DB_CPID(tpi_mp) = DB_CPID(idmp);
-	}
+	mblk_copycred(tpi_mp, idmp);
+
 	tcp->tcp_conn.tcp_eager_conn_ind = tpi_mp;
 
 	/* Inherit the listener's SSL protection state */
@@ -5519,7 +5528,7 @@
 		cred_t *cr;
 
 		if (connp->conn_mlp_type != mlptSingle) {
-			cr = econnp->conn_peercred = DB_CRED(mp);
+			cr = econnp->conn_peercred = msg_getcred(mp, NULL);
 			if (cr != NULL)
 				crhold(cr);
 			else
@@ -5708,8 +5717,17 @@
 		goto error;
 	}
 
-	DB_CPID(mp1) = tcp->tcp_cpid;
-	mblk_setcred(mp1, CONN_CRED(eager->tcp_connp));
+	/*
+	 * Note that in theory this should use the current pid
+	 * so that getpeerucred on the client returns the actual listener
+	 * that does accept. But accept() hasn't been called yet. We could use
+	 * the pid of the process that did bind/listen on the server.
+	 * However, with common usage like inetd() the bind/listen can be done
+	 * by a different process than the accept().
+	 * Hence we do the simple thing of using the open pid here.
+	 * Note that db_credp is set later in tcp_send_data().
+	 */
+	mblk_setcred(mp1, credp, tcp->tcp_cpid);
 	eager->tcp_cpid = tcp->tcp_cpid;
 	eager->tcp_open_time = lbolt64;
 
@@ -5924,6 +5942,22 @@
 	struct sockaddr	*sa;
 	socklen_t	len;
 	int		error;
+	cred_t		*cr;
+	pid_t		cpid;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, &cpid);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
+		return;
+	}
 
 	tcr = (struct T_conn_req *)mp->b_rptr;
 
@@ -6103,8 +6137,7 @@
 	}
 
 	/* call the non-TPI version */
-	error = tcp_do_connect(tcp->tcp_connp, sa, len, DB_CRED(mp),
-	    DB_CPID(mp));
+	error = tcp_do_connect(tcp->tcp_connp, sa, len, cr, cpid);
 	if (error < 0) {
 		mp = mi_tpi_err_ack_alloc(mp, -error, 0);
 	} else if (error > 0) {
@@ -6255,7 +6288,7 @@
 	if (tcp->tcp_family == AF_INET) {
 		error = ip_proto_bind_connected_v4(tcp->tcp_connp, &mp,
 		    IPPROTO_TCP, &tcp->tcp_ipha->ipha_src, tcp->tcp_lport,
-		    tcp->tcp_remote, tcp->tcp_fport, B_TRUE, B_TRUE);
+		    tcp->tcp_remote, tcp->tcp_fport, B_TRUE, B_TRUE, cr);
 	} else {
 		in6_addr_t v6src;
 		if (tcp->tcp_ipversion == IPV4_VERSION) {
@@ -6265,7 +6298,7 @@
 		}
 		error = ip_proto_bind_connected_v6(tcp->tcp_connp, &mp,
 		    IPPROTO_TCP, &v6src, tcp->tcp_lport, &tcp->tcp_remote_v6,
-		    &tcp->tcp_sticky_ipp, tcp->tcp_fport, B_TRUE, B_TRUE);
+		    &tcp->tcp_sticky_ipp, tcp->tcp_fport, B_TRUE, B_TRUE, cr);
 	}
 	BUMP_MIB(&tcps->tcps_mib, tcpActiveOpens);
 	tcp->tcp_active_open = 1;
@@ -6445,7 +6478,7 @@
 		}
 		error = ip_proto_bind_connected_v6(connp, &mp, IPPROTO_TCP,
 		    &v6src, tcp->tcp_lport, &tcp->tcp_remote_v6,
-		    &tcp->tcp_sticky_ipp, tcp->tcp_fport, B_TRUE, B_TRUE);
+		    &tcp->tcp_sticky_ipp, tcp->tcp_fport, B_TRUE, B_TRUE, cr);
 		BUMP_MIB(&tcps->tcps_mib, tcpActiveOpens);
 		tcp->tcp_active_open = 1;
 
@@ -12713,6 +12746,11 @@
 tcp_ulp_newconn(conn_t *lconnp, conn_t *econnp, mblk_t *mp)
 {
 	if (IPCL_IS_NONSTR(lconnp)) {
+		cred_t	*cr;
+		pid_t	cpid;
+
+		cr = msg_getcred(mp, &cpid);
+
 		ASSERT(econnp->conn_tcp->tcp_listener == lconnp->conn_tcp);
 		ASSERT(econnp->conn_tcp->tcp_saved_listener ==
 		    lconnp->conn_tcp);
@@ -12732,7 +12770,7 @@
 		if ((*lconnp->conn_upcalls->su_newconn)
 		    (lconnp->conn_upper_handle,
 		    (sock_lower_handle_t)econnp,
-		    &sock_tcp_downcalls, DB_CRED(mp), DB_CPID(mp),
+		    &sock_tcp_downcalls, cr, cpid,
 		    &econnp->conn_upcalls) == NULL) {
 			/* Failed to allocate a socket */
 			BUMP_MIB(&lconnp->conn_tcp->tcp_tcps->tcps_mib,
@@ -13220,12 +13258,14 @@
 						/* Send up T_CONN_CON */
 						putnext(tcp->tcp_rq, mp1);
 					} else {
+						cred_t	*cr;
+						pid_t	cpid;
+
+						cr = msg_getcred(mp1, &cpid);
 						(*connp->conn_upcalls->
 						    su_connected)
 						    (connp->conn_upper_handle,
-						    tcp->tcp_connid,
-						    DB_CRED(mp1),
-						    DB_CPID(mp1));
+						    tcp->tcp_connid, cr, cpid);
 						freemsg(mp1);
 					}
 
@@ -13244,10 +13284,13 @@
 				if (!IPCL_IS_NONSTR(connp)) {
 					putnext(tcp->tcp_rq, mp1);
 				} else {
+					cred_t	*cr;
+					pid_t	cpid;
+
+					cr = msg_getcred(mp1, &cpid);
 					(*connp->conn_upcalls->su_connected)
 					    (connp->conn_upper_handle,
-					    tcp->tcp_connid, DB_CRED(mp1),
-					    DB_CPID(mp1));
+					    tcp->tcp_connid, cr, cpid);
 					freemsg(mp1);
 				}
 			}
@@ -13275,6 +13318,10 @@
 		mp1 = tcp_xmit_mp(tcp, tcp->tcp_xmit_head, tcp->tcp_mss,
 		    NULL, NULL, tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
 		if (mp1) {
+			/*
+			 * See comment in tcp_conn_request() for why we use
+			 * the open() time pid here.
+			 */
 			DB_CPID(mp1) = tcp->tcp_cpid;
 			tcp_send_data(tcp, tcp->tcp_wq, mp1);
 			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
@@ -17275,10 +17322,14 @@
 	if (mp == NULL) {
 		return;
 	}
-	/* Attach credentials to retransmitted initial SYNs. */
+	/*
+	 * Attach credentials to retransmitted initial SYNs.
+	 * In theory we should use the credentials from the connect()
+	 * call to ensure that getpeerucred() on the peer will be correct.
+	 * But we assume that SYN's are not dropped for loopback connections.
+	 */
 	if (tcp->tcp_state == TCPS_SYN_SENT) {
-		mblk_setcred(mp, tcp->tcp_cred);
-		DB_CPID(mp) = tcp->tcp_cpid;
+		mblk_setcred(mp, tcp->tcp_cred, tcp->tcp_cpid);
 	}
 
 	tcp->tcp_csuna = tcp->tcp_snxt;
@@ -18486,9 +18537,25 @@
 	struct T_ok_ack *ok;
 	t_scalar_t PRIM_type;
 	conn_t *econnp;
+	cred_t *cr;
 
 	ASSERT(DB_TYPE(mp) == M_PROTO);
 
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		mp = mi_tpi_err_ack_alloc(mp, TSYSERR, EINVAL);
+		if (mp != NULL)
+			putnext(rq, mp);
+		return;
+	}
 	conn_res = (struct T_conn_res *)mp->b_rptr;
 	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
 	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_conn_res)) {
@@ -18535,7 +18602,7 @@
 		 */
 		eager->tcp_sodirect = SOD_QTOSODP(eager->tcp_rq);
 		if (tcp_accept_common(listener->tcp_connp,
-		    econnp, CRED()) < 0) {
+		    econnp, cr) < 0) {
 			mp = mi_tpi_err_ack_alloc(mp, TPROTO, 0);
 			if (mp != NULL)
 				putnext(rq, mp);
@@ -18769,7 +18836,20 @@
 			return;
 		}
 		if (type == T_SVR4_OPTMGMT_REQ) {
-			cred_t	*cr = DB_CREDDEF(mp, tcp->tcp_cred);
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cred_t	*cr = msg_getcred(mp, NULL);
+
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
+				return;
+			}
 			if (snmpcom_req(q, mp, tcp_snmp_set, ip_snmp_get,
 			    cr)) {
 				/*
@@ -19194,11 +19274,24 @@
 	uint_t		ire_fp_mp_len;
 	tcp_stack_t	*tcps = tcp->tcp_tcps;
 	ip_stack_t	*ipst = tcps->tcps_netstack->netstack_ip;
+	cred_t		*cr;
+	pid_t		cpid;
 
 	ASSERT(DB_TYPE(mp) == M_DATA);
 
-	if (is_system_labeled() && DB_CRED(mp) == NULL)
-		mblk_setcred(mp, CONN_CRED(tcp->tcp_connp));
+	/*
+	 * Here we need to handle the overloading of the cred_t for
+	 * both getpeerucred and TX.
+	 * If this is a SYN then the caller already set db_credp so
+	 * that getpeerucred will work. But if TX is in use we might have
+	 * a conn_peercred which is different, and we need to use that cred
+	 * to make TX use the correct label and label dependent route.
+	 */
+	if (is_system_labeled()) {
+		cr = msg_getcred(mp, &cpid);
+		if (cr == NULL || connp->conn_peercred != NULL)
+			mblk_setcred(mp, CONN_CRED(connp), cpid);
+	}
 
 	ipha = (ipha_t *)mp->b_rptr;
 	src = ipha->ipha_src;
@@ -22329,7 +22422,7 @@
 	union T_primitives *tprim = (union T_primitives *)mp->b_rptr;
 	uchar_t *rptr;
 	t_scalar_t type;
-	cred_t *cr = DB_CREDDEF(mp, tcp->tcp_cred);
+	cred_t *cr;
 
 	/*
 	 * Try and ASSERT the minimum possible references on the
@@ -22417,29 +22510,41 @@
 		tcp_info_req(tcp, mp);
 		break;
 	case T_SVR4_OPTMGMT_REQ:	/* manage options req */
+	case T_OPTMGMT_REQ:
+		/*
+		 * Note:  no support for snmpcom_req() through new
+		 * T_OPTMGMT_REQ. See comments in ip.c
+		 */
+
+		/*
+		 * All Solaris components should pass a db_credp
+		 * for this TPI message, hence we ASSERT.
+		 * But in case there is some other M_PROTO that looks
+		 * like a TPI message sent by some other kernel
+		 * component, we check and return an error.
+		 */
+		cr = msg_getcred(mp, NULL);
+		ASSERT(cr != NULL);
+		if (cr == NULL) {
+			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
+			return;
+		}
 		/*
 		 * If EINPROGRESS is returned, the request has been queued
 		 * for subsequent processing by ip_restart_optmgmt(), which
 		 * will do the CONN_DEC_REF().
 		 */
 		CONN_INC_REF(connp);
-		if (svr4_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj,
-		    B_TRUE) != EINPROGRESS) {
-			CONN_DEC_REF(connp);
-		}
-		break;
-	case T_OPTMGMT_REQ:
-		/*
-		 * Note:  no support for snmpcom_req() through new
-		 * T_OPTMGMT_REQ. See comments in ip.c
-		 *
-		 * see comments above in T_SVR4_OPTMGMT_REQ for conn
-		 * reference changes.
-		 */
-		CONN_INC_REF(connp);
-		if (tpi_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj,
-		    B_TRUE) != EINPROGRESS) {
-			CONN_DEC_REF(connp);
+		if ((int)tprim->type == T_SVR4_OPTMGMT_REQ) {
+			if (svr4_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj,
+			    B_TRUE) != EINPROGRESS) {
+				CONN_DEC_REF(connp);
+			}
+		} else {
+			if (tpi_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj,
+			    B_TRUE) != EINPROGRESS) {
+				CONN_DEC_REF(connp);
+			}
 		}
 		break;
 
@@ -22878,7 +22983,7 @@
 	}
 
 	/* IP trusts us to set up labels when required. */
-	if (is_system_labeled() && (cr = DB_CRED(mp)) != NULL &&
+	if (is_system_labeled() && (cr = msg_getcred(mp, NULL)) != NULL &&
 	    crgetlabel(cr) != NULL) {
 		int err;
 
@@ -24344,7 +24449,17 @@
 	struct T_conn_res *tcresp;
 	cred_t *cr;
 
-	cr = DB_CREDDEF(mp, tcp->tcp_cred);
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL)
+		return (-1);
 
 	prim_type = ((union T_primitives *)mp->b_rptr)->type;
 	ASSERT(prim_type == T_CONN_REQ || prim_type == O_T_CONN_RES ||
@@ -26648,8 +26763,7 @@
 				cr = tcp->tcp_cred;
 				pid = tcp->tcp_cpid;
 			}
-			mblk_setcred(syn_mp, cr);
-			DB_CPID(syn_mp) = pid;
+			mblk_setcred(syn_mp, cr, pid);
 			tcp_send_data(tcp, tcp->tcp_wq, syn_mp);
 		}
 	after_syn_sent:
@@ -26914,10 +27028,9 @@
     boolean_t bind_to_req_port_only)
 {
 	tcp_t	*tcp = connp->conn_tcp;
-
 	sin_t	*sin;
 	sin6_t  *sin6;
-	sin6_t		sin6addr;
+	sin6_t	sin6addr;
 	in_port_t requested_port;
 	ipaddr_t	v4addr;
 	in6_addr_t	v6addr;
@@ -27091,6 +27204,9 @@
 	conn_t		*connp = (conn_t *)proto_handle;
 	squeue_t	*sqp = connp->conn_sqp;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(sqp != NULL);
 	ASSERT(connp->conn_upper_handle != NULL);
 
@@ -27259,6 +27375,9 @@
 
 	ASSERT(connp->conn_upper_handle != NULL);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	error = proto_verify_ip_addr(tcp->tcp_family, sa, len);
 	if (error != 0) {
 		return (error);
@@ -27352,6 +27471,9 @@
 
 	ASSERT(connp->conn_upper_handle == NULL);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	sopp.sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_RCVLOWAT |
 	    SOCKOPT_MAXPSZ | SOCKOPT_MAXBLK | SOCKOPT_RCVTIMER |
 	    SOCKOPT_RCVTHRESH | SOCKOPT_MAXADDRLEN | SOCKOPT_MINPSZ;
@@ -27380,6 +27502,9 @@
 
 	ASSERT(connp->conn_upper_handle != NULL);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	tcp_close_common(connp, flags);
 
 	ip_free_helper_stream(connp);
@@ -27410,6 +27535,9 @@
 	conn_t *connp = (conn_t *)proto_handle;
 	int32_t		tcpstate;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(connp->conn_ref >= 2);
 	ASSERT(connp->conn_upper_handle != NULL);
 
@@ -27516,6 +27644,9 @@
 	tcp_t	*tcp = connp->conn_tcp;
 
 	ASSERT(connp->conn_upper_handle != NULL);
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(tcp != NULL);
 
 	return (tcp_do_getpeername(tcp, addr, addrlenp));
@@ -27529,6 +27660,9 @@
 	conn_t	*connp = (conn_t *)proto_handle;
 	tcp_t	*tcp = connp->conn_tcp;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(connp->conn_upper_handle != NULL);
 
 	return (tcp_do_getsockname(tcp, addr, addrlenp));
@@ -27779,6 +27913,9 @@
 
 	ASSERT(connp->conn_upper_handle != NULL);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	/*
 	 * X/Open requires that we check the connected state.
 	 */
@@ -27819,6 +27956,9 @@
 
 	ASSERT(connp->conn_upper_handle != NULL);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	error = squeue_synch_enter(sqp, connp, 0);
 	if (error != 0) {
 		/* failed to enter */
@@ -27848,6 +27988,9 @@
 	int		error = 0;
 	tcp_stack_t	*tcps = tcp->tcp_tcps;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (tcp->tcp_state >= TCPS_BOUND) {
 		if ((tcp->tcp_state == TCPS_BOUND ||
 		    tcp->tcp_state == TCPS_LISTEN) && backlog > 0) {
@@ -27981,6 +28124,9 @@
 
 	ASSERT(connp->conn_upper_handle != NULL);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	switch (cmd) {
 		case ND_SET:
 		case ND_GET:
diff --git a/usr/src/uts/common/inet/tun.h b/usr/src/uts/common/inet/tun.h
index 6175e82..8154c0f 100644
--- a/usr/src/uts/common/inet/tun.h
+++ b/usr/src/uts/common/inet/tun.h
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -27,8 +27,6 @@
 #ifndef	_INET_TUN_H
 #define	_INET_TUN_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -202,6 +200,7 @@
 	uint64_t tun_HCOutUcastPkts;	/* # Packets requested */
 	uint64_t tun_HCOutMulticastPkts; /* Multicast Packets requested */
 	netstack_t	*tun_netstack;
+	cred_t		*tun_cred;
 } tun_t;
 
 
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c
index 662c162..30c876b 100644
--- a/usr/src/uts/common/inet/udp/udp.c
+++ b/usr/src/uts/common/inet/udp/udp.c
@@ -241,7 +241,8 @@
     struct sockaddr *, socklen_t *, cred_t *);
 int		udp_getpeername(sock_lower_handle_t,
     struct sockaddr *, socklen_t *, cred_t *);
-static int	udp_do_connect(conn_t *, const struct sockaddr *, socklen_t);
+static int	udp_do_connect(conn_t *, const struct sockaddr *, socklen_t,
+    cred_t *cr);
 static int	udp_post_ip_bind_connect(udp_t *, mblk_t *, int);
 
 #define	UDP_RECV_HIWATER	(56 * 1024)
@@ -640,6 +641,21 @@
 	udp_t		*udp;
 	int		error;
 	struct sockaddr	*sa;
+	cred_t		*cr;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		udp_err_ack(q, mp, TSYSERR, EINVAL);
+		return;
+	}
 
 	connp = Q_TO_CONN(q);
 	udp = connp->conn_udp;
@@ -728,8 +744,6 @@
 		return;
 	}
 
-
-	cred_t *cr = DB_CREDDEF(mp, connp->conn_cred);
 	error = udp_do_bind(connp, sa, tbr->ADDR_length, cr,
 	    tbr->PRIM_type != O_T_BIND_REQ);
 
@@ -771,6 +785,21 @@
 	socklen_t	len;
 	struct sockaddr		*sa;
 	struct T_conn_req	*tcr;
+	cred_t		*cr;
+
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		udp_err_ack(q, mp, TSYSERR, EINVAL);
+		return;
+	}
 
 	udp = connp->conn_udp;
 	tcr = (struct T_conn_req *)mp->b_rptr;
@@ -842,7 +871,7 @@
 		return;
 	}
 
-	error = udp_do_connect(connp, sa, len);
+	error = udp_do_connect(connp, sa, len, cr);
 	if (error != 0) {
 		freeb(mp1);
 		if (error < 0)
@@ -2469,11 +2498,12 @@
 				return (EINVAL);
 			if (!checkonly) {
 				mblk_t *mb;
+				pid_t  cpid;
 
 				if (attrs == NULL ||
 				    (mb = attrs->udpattr_mb) == NULL)
 					return (EINVAL);
-				if ((cr = DB_CRED(mb)) == NULL)
+				if ((cr = msg_getcred(mb, &cpid)) == NULL)
 					cr = udp->udp_connp->conn_cred;
 				ASSERT(cr != NULL);
 				if ((tsl = crgetlabel(cr)) == NULL)
@@ -2482,7 +2512,7 @@
 				    tsl->tsl_doi, KM_NOSLEEP);
 				if (newcr == NULL)
 					return (ENOSR);
-				mblk_setcred(mb, newcr);
+				mblk_setcred(mb, newcr, cpid);
 				attrs->udpattr_credset = B_TRUE;
 				crfree(newcr);
 			}
@@ -3858,7 +3888,7 @@
 	}
 
 
-	/* Walk past the headers unless IP_RECVHDR was set. */
+	/* Walk past the headers unless UDP_RCVHDR was set. */
 	if (!udp_bits.udpb_rcvhdr) {
 		mp->b_rptr = rptr + hdr_length;
 		mp_len -= hdr_length;
@@ -3916,9 +3946,8 @@
 		}
 
 		if ((udp_bits.udpb_recvucred) &&
-		    (cr = DB_CRED(mp)) != NULL) {
+		    (cr = msg_getcred(mp, &cpid)) != NULL) {
 			udi_size += sizeof (struct T_opthdr) + ucredsize;
-			cpid = DB_CPID(mp);
 			UDP_STAT(us, udp_in_recvucred);
 		}
 
@@ -4191,9 +4220,8 @@
 
 		}
 		if ((udp_bits.udpb_recvucred) &&
-		    (cr = DB_CRED(mp)) != NULL) {
+		    (cr = msg_getcred(mp, &cpid)) != NULL) {
 			udi_size += sizeof (struct T_opthdr) + ucredsize;
-			cpid = DB_CPID(mp);
 			UDP_STAT(us, udp_in_recvucred);
 		}
 
@@ -4980,8 +5008,21 @@
 	uchar_t opt_storage[IP_MAX_OPT_LENGTH];
 	udp_t *udp = Q_TO_UDP(wq);
 	udp_stack_t	*us = udp->udp_us;
+	cred_t			*cr;
 
-	err = tsol_compute_label(DB_CREDDEF(mp, udp->udp_connp->conn_cred), dst,
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this message, hence we ASSERT.
+	 * On production kernels we return an error to be robust against
+	 * random streams modules sitting on top of us.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL)
+		return (EINVAL);
+
+	/* Note that we use the cred/label from the message to handle MLP */
+	err = tsol_compute_label(cr, dst,
 	    opt_storage, udp->udp_connp->conn_mac_exempt,
 	    us->us_netstack->netstack_ip);
 	if (err == 0) {
@@ -5049,7 +5090,7 @@
 			rw_enter(&udp->udp_rwlock, RW_WRITER);
 			*error = process_auxiliary_options(connp,
 			    msg->msg_control, msg->msg_controllen,
-			    &attrs, &udp_opt_obj, udp_opt_set);
+			    &attrs, &udp_opt_obj, udp_opt_set, cr);
 			rw_exit(&udp->udp_rwlock);
 			if (*error)
 				goto done;
@@ -5081,13 +5122,15 @@
 	/*
 	 * Determine whether we need to mark the mblk with the user's
 	 * credentials.
+	 * If labeled then sockfs would have already done this.
 	 */
+	ASSERT(!is_system_labeled() || msg_getcred(mp, NULL) != NULL);
+
 	ire = connp->conn_ire_cache;
-	if (is_system_labeled() || CLASSD(v4dst) || (ire == NULL) ||
-	    (ire->ire_addr != v4dst) ||
+	if (CLASSD(v4dst) || (ire == NULL) || (ire->ire_addr != v4dst) ||
 	    (ire->ire_type & (IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK))) {
-		if (cr != NULL && DB_CRED(mp) == NULL)
-			msg_setcredpid(mp, cr, pid);
+		if (cr != NULL && msg_getcred(mp, NULL) == NULL)
+			mblk_setcred(mp, cr, pid);
 	}
 
 	rw_enter(&udp->udp_rwlock, RW_READER);
@@ -5336,10 +5379,19 @@
 	ASSERT(!lock_held);
 	/* Set UDP length and checksum */
 	*((uint32_t *)&udpha->uha_length) = ip_len;
-	if (DB_CRED(mp) != NULL)
-		mblk_setcred(mp1, DB_CRED(mp));
 
 	if (DB_TYPE(mp) != M_DATA) {
+		cred_t *cr;
+		pid_t cpid;
+
+		/* Move any cred from the T_UNITDATA_REQ to the packet */
+		cr = msg_extractcred(mp, &cpid);
+		if (cr != NULL) {
+			if (mp1->b_datap->db_credp != NULL)
+				crfree(mp1->b_datap->db_credp);
+			mp1->b_datap->db_credp = cr;
+			mp1->b_datap->db_cpid = cpid;
+		}
 		ASSERT(mp != mp1);
 		freeb(mp);
 	}
@@ -5446,12 +5498,12 @@
 		if (CLASSD(dst)) {
 			ASSERT(ipif != NULL);
 			ire = ire_ctable_lookup(dst, 0, 0, ipif,
-			    connp->conn_zoneid, MBLK_GETLABEL(mp),
+			    connp->conn_zoneid, msg_getlabel(mp),
 			    MATCH_IRE_ILL, ipst);
 		} else {
 			ASSERT(ipif == NULL);
 			ire = ire_cache_lookup(dst, connp->conn_zoneid,
-			    MBLK_GETLABEL(mp), ipst);
+			    msg_getlabel(mp), ipst);
 		}
 
 		if (ire == NULL) {
@@ -5691,8 +5743,21 @@
 	int err;
 	uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
 	udp_stack_t		*us = udp->udp_us;
+	cred_t			*cr;
 
-	err = tsol_compute_label_v6(DB_CREDDEF(mp, udp->udp_connp->conn_cred),
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this message, hence we ASSERT.
+	 * On production kernels we return an error to be robust against
+	 * random streams modules sitting on top of us.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL)
+		return (EINVAL);
+
+	/* Note that we use the cred/label from the message to handle MLP */
+	err = tsol_compute_label_v6(cr,
 	    dst, opt_storage, udp->udp_connp->conn_mac_exempt,
 	    us->us_netstack->netstack_ip);
 	if (err == 0) {
@@ -6065,7 +6130,7 @@
 			rw_enter(&udp->udp_rwlock, RW_WRITER);
 			*error = process_auxiliary_options(connp,
 			    msg->msg_control, msg->msg_controllen,
-			    &attrs, &udp_opt_obj, udp_opt_set);
+			    &attrs, &udp_opt_obj, udp_opt_set, cr);
 			rw_exit(&udp->udp_rwlock);
 			if (*error)
 				goto done;
@@ -6092,14 +6157,15 @@
 	/*
 	 * Determine whether we need to mark the mblk with the user's
 	 * credentials.
+	 * If labeled then sockfs would have already done this.
 	 */
+	ASSERT(!is_system_labeled() || msg_getcred(mp, NULL) != NULL);
 	ire = connp->conn_ire_cache;
-	if (is_system_labeled() || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) ||
-	    (ire == NULL) ||
+	if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) || (ire == NULL) ||
 	    (!IN6_ARE_ADDR_EQUAL(&ire->ire_addr_v6, &sin6->sin6_addr)) ||
 	    (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK))) {
-		if (cr != NULL && DB_CRED(mp) == NULL)
-			msg_setcredpid(mp, cr, pid);
+		if (cr != NULL && msg_getcred(mp, NULL) == NULL)
+			mblk_setcred(mp, cr, pid);
 	}
 
 	rw_enter(&udp->udp_rwlock, RW_READER);
@@ -6653,10 +6719,20 @@
 	ip_len = htons(ip_len);
 #endif
 	ip6h->ip6_plen = ip_len;
-	if (DB_CRED(mp) != NULL)
-		mblk_setcred(mp1, DB_CRED(mp));
 
 	if (DB_TYPE(mp) != M_DATA) {
+		cred_t *cr;
+		pid_t cpid;
+
+		/* Move any cred from the T_UNITDATA_REQ to the packet */
+		cr = msg_extractcred(mp, &cpid);
+		if (cr != NULL) {
+			if (mp1->b_datap->db_credp != NULL)
+				crfree(mp1->b_datap->db_credp);
+			mp1->b_datap->db_credp = cr;
+			mp1->b_datap->db_cpid = cpid;
+		}
+
 		ASSERT(mp != mp1);
 		freeb(mp);
 	}
@@ -6853,8 +6929,6 @@
 	us = udp->udp_us;
 	db = mp->b_datap;
 
-	cr = DB_CREDDEF(mp, connp->conn_cred);
-
 	switch (db->db_type) {
 	case M_CMD:
 		udp_wput_cmdblk(q, mp);
@@ -6911,6 +6985,19 @@
 			    "udp_wput_other_end: q %p (%S)", q, "unbindreq");
 			return;
 		case T_SVR4_OPTMGMT_REQ:
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				udp_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
 			if (!snmpcom_req(q, mp, udp_snmp_set, ip_snmp_get,
 			    cr)) {
 				(void) svr4_optcom_req(q,
@@ -6921,6 +7008,19 @@
 			return;
 
 		case T_OPTMGMT_REQ:
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				udp_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
 			(void) tpi_optcom_req(q, mp, cr, &udp_opt_obj, B_TRUE);
 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
 			    "udp_wput_other_end: q %p (%S)", q, "optmgmtreq");
@@ -7140,12 +7240,22 @@
 	struct T_unitdata_req *udreqp;
 	int is_absreq_failure;
 	cred_t *cr;
-	conn_t	*connp = Q_TO_CONN(q);
 
 	ASSERT(((t_primp_t)mp->b_rptr)->type);
 
-	cr = DB_CREDDEF(mp, connp->conn_cred);
-
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we should ASSERT.
+	 * However, RPC (svc_clts_ksend) does this odd thing where it
+	 * passes the options from a T_UNITDATA_IND unchanged in a
+	 * T_UNITDATA_REQ. While that is the right thing to do for
+	 * some options, SCM_UCRED being the key one, this also makes it
+	 * pass down IP_RECVDSTADDR. Hence we can't ASSERT here.
+	 */
+	cr = msg_getcred(mp, NULL);
+	if (cr == NULL) {
+		cr = Q_TO_CONN(q)->conn_cred;
+	}
 	udreqp = (struct T_unitdata_req *)mp->b_rptr;
 
 	*errorp = tpi_optcom_buf(q, mp, &udreqp->OPT_length,
@@ -7882,6 +7992,9 @@
 	udp_stack_t	*us = udp->udp_us;
 	struct sock_proto_props sopp;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	connp->conn_upcalls = sock_upcalls;
 	connp->conn_upper_handle = sock_handle;
 
@@ -7959,6 +8072,9 @@
 {
 	conn_t	*connp = (conn_t *)proto_handle;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	udp_do_close(connp);
 	return (0);
 }
@@ -8394,7 +8510,6 @@
 	if (is_system_labeled() && (!connp->conn_anon_port ||
 	    connp->conn_anon_mlp)) {
 		uint16_t mlpport;
-		cred_t *cr = connp->conn_cred;
 		zone_t *zone;
 
 		zone = crgetzone(cr);
@@ -8520,6 +8635,9 @@
 	int		error;
 	conn_t		*connp;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	connp = (conn_t *)proto_handle;
 
 	if (sa == NULL)
@@ -8542,6 +8660,9 @@
 {
 	int error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	error = udp_do_bind(connp, NULL, 0, cr, B_FALSE);
 	return ((error < 0) ? proto_tlitosyserr(-error) : error);
 }
@@ -8698,7 +8819,8 @@
  * It associates a default destination address with the stream.
  */
 static int
-udp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len)
+udp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
+    cred_t *cr)
 {
 	sin6_t		*sin6;
 	sin_t		*sin;
@@ -8897,11 +9019,11 @@
 		error = ip_proto_bind_connected_v4(connp, &ire_mp, IPPROTO_UDP,
 		    &V4_PART_OF_V6(udp->udp_v6src), udp->udp_port,
 		    V4_PART_OF_V6(udp->udp_v6dst), udp->udp_dstport,
-		    B_TRUE, B_TRUE);
+		    B_TRUE, B_TRUE, cr);
 	} else {
 		error = ip_proto_bind_connected_v6(connp, &ire_mp, IPPROTO_UDP,
 		    &udp->udp_v6src, udp->udp_port, &udp->udp_v6dst,
-		    &udp->udp_sticky_ipp, udp->udp_dstport, B_TRUE, B_TRUE);
+		    &udp->udp_sticky_ipp, udp->udp_dstport, B_TRUE, B_TRUE, cr);
 	}
 
 	return (udp_post_ip_bind_connect(udp, ire_mp, error));
@@ -8917,6 +9039,9 @@
 	int	error;
 	boolean_t did_bind = B_FALSE;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (sa == NULL) {
 		/*
 		 * Disconnect
@@ -8950,7 +9075,7 @@
 	 */
 	udp->udp_dgram_errind = B_TRUE;
 
-	error = udp_do_connect(connp, sa, len);
+	error = udp_do_connect(connp, sa, len, cr);
 
 	if (error != 0 && did_bind) {
 		int unbind_err;
@@ -8991,6 +9116,12 @@
 
 	ASSERT(DB_TYPE(mp) == M_DATA);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
+	/* If labeled then sockfs should have already set db_credp */
+	ASSERT(!is_system_labeled() || msg_getcred(mp, NULL) != NULL);
+
 	/*
 	 * If the socket is connected and no change in destination
 	 */
@@ -9145,9 +9276,9 @@
 
 	laddrlen = faddrlen = sizeof (sin6_t);
 	(void) udp_getsockname((sock_lower_handle_t)connp,
-	    (struct sockaddr *)&laddr, &laddrlen, NULL);
+	    (struct sockaddr *)&laddr, &laddrlen, CRED());
 	error = udp_getpeername((sock_lower_handle_t)connp,
-	    (struct sockaddr *)&faddr, &faddrlen, NULL);
+	    (struct sockaddr *)&faddr, &faddrlen, CRED());
 	if (error != 0)
 		faddrlen = 0;
 
@@ -9241,6 +9372,9 @@
 	udp_t	*udp = connp->conn_udp;
 	int error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(udp != NULL);
 
 	rw_enter(&udp->udp_rwlock, RW_READER);
@@ -9329,6 +9463,9 @@
 	udp_t	*udp = connp->conn_udp;
 	int error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	ASSERT(udp != NULL);
 	rw_enter(&udp->udp_rwlock, RW_READER);
 
@@ -9350,6 +9487,9 @@
 	void		*optvalp_buf;
 	int		len;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	error = proto_opt_check(level, option_name, *optlen, &max_optbuf_len,
 	    udp_opt_obj.odb_opt_des_arr,
 	    udp_opt_obj.odb_opt_arr_cnt,
@@ -9394,6 +9534,9 @@
 	udp_t		*udp = connp->conn_udp;
 	int		error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	error = proto_opt_check(level, option_name, optlen, NULL,
 	    udp_opt_obj.odb_opt_des_arr,
 	    udp_opt_obj.odb_opt_arr_cnt,
@@ -9440,6 +9583,9 @@
 {
 	conn_t	*connp = (conn_t *)proto_handle;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	/* shut down the send side */
 	if (how != SHUT_RD)
 		(*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
@@ -9458,6 +9604,9 @@
 	conn_t  	*connp = (conn_t *)proto_handle;
 	int		error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	switch (cmd) {
 		case ND_SET:
 		case ND_GET:
diff --git a/usr/src/uts/common/io/ib/clients/rds/rdsddi.c b/usr/src/uts/common/io/ib/clients/rds/rdsddi.c
index 877e56f..a4a9c6c 100644
--- a/usr/src/uts/common/io/ib/clients/rds/rdsddi.c
+++ b/usr/src/uts/common/io/ib/clients/rds/rdsddi.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -608,12 +608,10 @@
 static void
 rds_wput_other(queue_t *q, mblk_t *mp)
 {
-	rds_t *rds = (rds_t *)q->q_ptr;
 	uchar_t *rptr = mp->b_rptr;
 	struct datab *db;
 	cred_t *cr;
 
-	cr = DB_CREDDEF(mp, rds->rds_cred);
 	db = mp->b_datap;
 	switch (db->db_type) {
 	case M_DATA:
@@ -640,11 +638,28 @@
 			rds_bind(q, mp);
 			return;
 		case T_SVR4_OPTMGMT_REQ:
-			(void) svr4_optcom_req(q, mp, cr, &rds_opt_obj,
-			    B_FALSE);
-			return;
 		case T_OPTMGMT_REQ:
-			(void) tpi_optcom_req(q, mp, cr, &rds_opt_obj, B_FALSE);
+			/*
+			 * All Solaris components should pass a db_credp
+			 * for this TPI message, hence we ASSERT.
+			 * But in case there is some other M_PROTO that looks
+			 * like a TPI message sent by some other kernel
+			 * component, we check and return an error.
+			 */
+			cr = msg_getcred(mp, NULL);
+			ASSERT(cr != NULL);
+			if (cr == NULL) {
+				rds_err_ack(q, mp, TSYSERR, EINVAL);
+				return;
+			}
+			if (((union T_primitives *)(uintptr_t)rptr)->type ==
+			    T_SVR4_OPTMGMT_REQ) {
+				(void) svr4_optcom_req(q, mp, cr, &rds_opt_obj,
+				    B_FALSE);
+			} else {
+				(void) tpi_optcom_req(q, mp, cr, &rds_opt_obj,
+				    B_FALSE);
+			}
 			return;
 		case T_CONN_REQ:
 			/*
diff --git a/usr/src/uts/common/io/ksocket/ksocket.c b/usr/src/uts/common/io/ksocket/ksocket.c
index 512cab5..28b4f71 100644
--- a/usr/src/uts/common/io/ksocket/ksocket.c
+++ b/usr/src/uts/common/io/ksocket/ksocket.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -52,6 +52,9 @@
 	struct sonode *so;
 	*ksp = NULL;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (domain == AF_NCA || domain == AF_UNIX)
 		return (EAFNOSUPPORT);
 
@@ -99,6 +102,9 @@
 {
 	int error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -110,6 +116,9 @@
 int
 ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
 {
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -123,6 +132,9 @@
 	int error;
 	struct sonode *nso = NULL;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	*nks = NULL;
 
 	if (!KSOCKET_VALID(ks))
@@ -157,6 +169,9 @@
 ksocket_connect(ksocket_t ks, const struct sockaddr *addr, socklen_t addrlen,
     struct cred *cr)
 {
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -173,6 +188,9 @@
 	struct uio auio;
 	struct iovec iov;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks)) {
 		if (sent != NULL)
 			*sent = 0;
@@ -222,6 +240,9 @@
 	struct uio auio;
 	struct iovec iov;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks)) {
 		if (sent != NULL)
 			*sent = 0;
@@ -272,6 +293,9 @@
 	int i;
 	struct uio auio;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks)) {
 		if (sent != NULL)
 			*sent = 0;
@@ -323,6 +347,9 @@
 	struct uio auio;
 	struct iovec iov;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks)) {
 		if (recv != NULL)
 			*recv = 0;
@@ -373,6 +400,9 @@
 	struct uio auio;
 	struct iovec iov;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks)) {
 		if (recv != NULL)
 			*recv = 0;
@@ -425,6 +455,9 @@
 	int i;
 	struct uio auio;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks)) {
 		if (recv != NULL)
 			*recv = 0;
@@ -473,6 +506,9 @@
 {
 	struct sonode *so;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -487,6 +523,9 @@
 	struct sonode *so;
 	so = KSTOSO(ks);
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	mutex_enter(&so->so_lock);
 
 	if (!KSOCKET_VALID(ks)) {
@@ -525,6 +564,9 @@
 {
 	struct sonode *so;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -542,6 +584,9 @@
 {
 	struct sonode *so;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -559,6 +604,9 @@
 {
 	struct sonode *so;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -579,6 +627,9 @@
 {
 	struct sonode *so;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -598,6 +649,9 @@
 {
 	struct sonode *so;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -633,6 +687,9 @@
 	struct sonode *so;
 	int rval;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -670,6 +727,9 @@
 	mblk_t		*mp = *mpp;
 	int		error;
 
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
 	if (!KSOCKET_VALID(ks))
 		return (ENOTSOCK);
 
@@ -677,7 +737,7 @@
 
 	if (flags & MSG_MBLK_QUICKRELE) {
 		error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID,
-		    &i_val, &val_len, 0, CRED());
+		    &i_val, &val_len, 0, cr);
 		if (error != 0)
 			return (error);
 
diff --git a/usr/src/uts/common/io/log.c b/usr/src/uts/common/io/log.c
index 9acd4c6..735283f 100644
--- a/usr/src/uts/common/io/log.c
+++ b/usr/src/uts/common/io/log.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,6 +32,7 @@
 #include <sys/param.h>
 #include <sys/errno.h>
 #include <sys/stropts.h>
+#include <sys/strsubr.h>
 #include <sys/stream.h>
 #include <sys/strsun.h>
 #include <sys/debug.h>
@@ -160,7 +161,7 @@
 	log_t *lp = (log_t *)q->q_ptr;
 	struct iocblk *iocp;
 	mblk_t *mp2;
-	cred_t *cr = DB_CRED(mp);
+	cred_t *cr = msg_getcred(mp, NULL);
 	zoneid_t zoneid;
 
 	/*
diff --git a/usr/src/uts/common/io/stream.c b/usr/src/uts/common/io/stream.c
index fb3941e..50dfbd3 100644
--- a/usr/src/uts/common/io/stream.c
+++ b/usr/src/uts/common/io/stream.c
@@ -447,43 +447,182 @@
 	return (mp);
 }
 
+/*
+ * Allocate an mblk taking db_credp and db_cpid from the template.
+ * Allow the cred to be NULL.
+ */
 mblk_t *
 allocb_tmpl(size_t size, const mblk_t *tmpl)
 {
 	mblk_t *mp = allocb(size, 0);
 
 	if (mp != NULL) {
-		cred_t *cr = DB_CRED(tmpl);
+		dblk_t *src = tmpl->b_datap;
+		dblk_t *dst = mp->b_datap;
+		cred_t *cr = src->db_credp;
+
 		if (cr != NULL)
-			crhold(mp->b_datap->db_credp = cr);
-		DB_CPID(mp) = DB_CPID(tmpl);
-		DB_TYPE(mp) = DB_TYPE(tmpl);
+			crhold(dst->db_credp = cr);
+		dst->db_cpid = src->db_cpid;
+		dst->db_type = src->db_type;
 	}
 	return (mp);
 }
 
 mblk_t *
-allocb_cred(size_t size, cred_t *cr)
+allocb_cred(size_t size, cred_t *cr, pid_t cpid)
 {
 	mblk_t *mp = allocb(size, 0);
 
-	if (mp != NULL && cr != NULL)
-		crhold(mp->b_datap->db_credp = cr);
+	ASSERT(cr != NULL);
+	if (mp != NULL) {
+		dblk_t *dbp = mp->b_datap;
 
+		crhold(dbp->db_credp = cr);
+		dbp->db_cpid = cpid;
+	}
 	return (mp);
 }
 
 mblk_t *
-allocb_cred_wait(size_t size, uint_t flags, int *error, cred_t *cr)
+allocb_cred_wait(size_t size, uint_t flags, int *error, cred_t *cr, pid_t cpid)
 {
 	mblk_t *mp = allocb_wait(size, 0, flags, error);
 
-	if (mp != NULL && cr != NULL)
-		crhold(mp->b_datap->db_credp = cr);
+	ASSERT(cr != NULL);
+	if (mp != NULL) {
+		dblk_t *dbp = mp->b_datap;
+
+		crhold(dbp->db_credp = cr);
+		dbp->db_cpid = cpid;
+	}
 
 	return (mp);
 }
 
+/*
+ * Extract the db_cred (and optionally db_cpid) from a message.
+ * We find the first mblk which has a non-NULL db_cred and use that.
+ * If none found we return NULL.
+ * Does NOT get a hold on the cred.
+ */
+cred_t *
+msg_getcred(const mblk_t *mp, pid_t *cpidp)
+{
+	cred_t *cr = NULL;
+	cred_t *cr2;
+
+	while (mp != NULL) {
+		dblk_t *dbp = mp->b_datap;
+
+		cr = dbp->db_credp;
+		if (cr == NULL) {
+			mp = mp->b_cont;
+			continue;
+		}
+		if (cpidp != NULL)
+			*cpidp = dbp->db_cpid;
+
+#ifdef DEBUG
+		/*
+		 * Normally there should at most one db_credp in a message.
+		 * But if there are multiple (as in the case of some M_IOC*
+		 * and some internal messages in TCP/IP bind logic) then
+		 * they must be identical in the normal case.
+		 * However, a socket can be shared between different uids
+		 * in which case data queued in TCP would be from different
+		 * creds. Thus we can only assert for the zoneid being the
+		 * same. Due to Multi-level Level Ports for TX, some
+		 * cred_t can have a NULL cr_zone, and we skip the comparison
+		 * in that case.
+		 */
+		cr2 = msg_getcred(mp->b_cont, NULL);
+		if (cr2 != NULL) {
+			DTRACE_PROBE2(msg__getcred,
+			    cred_t *, cr, cred_t *, cr2);
+			ASSERT(crgetzoneid(cr) == crgetzoneid(cr2) ||
+			    crgetzone(cr) == NULL ||
+			    crgetzone(cr2) == NULL);
+		}
+#endif
+		return (cr);
+	}
+	if (cpidp != NULL)
+		*cpidp = NOPID;
+	return (NULL);
+}
+
+/*
+ * Variant of msg_getcred which, when a cred is found
+ * 1. Returns with a hold on the cred
+ * 2. Clears the first cred in the mblk.
+ * This is more efficient to use than a msg_getcred() + crhold() when
+ * the message is freed after the cred has been extracted.
+ *
+ * The caller is responsible for ensuring that there is no other reference
+ * on the message since db_credp can not be cleared when there are other
+ * references.
+ */
+cred_t *
+msg_extractcred(mblk_t *mp, pid_t *cpidp)
+{
+	cred_t *cr = NULL;
+	cred_t *cr2;
+
+	while (mp != NULL) {
+		dblk_t *dbp = mp->b_datap;
+
+		cr = dbp->db_credp;
+		if (cr == NULL) {
+			mp = mp->b_cont;
+			continue;
+		}
+		ASSERT(dbp->db_ref == 1);
+		dbp->db_credp = NULL;
+		if (cpidp != NULL)
+			*cpidp = dbp->db_cpid;
+#ifdef DEBUG
+		/*
+		 * Normally there should at most one db_credp in a message.
+		 * But if there are multiple (as in the case of some M_IOC*
+		 * and some internal messages in TCP/IP bind logic) then
+		 * they must be identical in the normal case.
+		 * However, a socket can be shared between different uids
+		 * in which case data queued in TCP would be from different
+		 * creds. Thus we can only assert for the zoneid being the
+		 * same. Due to Multi-level Level Ports for TX, some
+		 * cred_t can have a NULL cr_zone, and we skip the comparison
+		 * in that case.
+		 */
+		cr2 = msg_getcred(mp->b_cont, NULL);
+		if (cr2 != NULL) {
+			DTRACE_PROBE2(msg__extractcred,
+			    cred_t *, cr, cred_t *, cr2);
+			ASSERT(crgetzoneid(cr) == crgetzoneid(cr2) ||
+			    crgetzone(cr) == NULL ||
+			    crgetzone(cr2) == NULL);
+		}
+#endif
+		return (cr);
+	}
+	return (NULL);
+}
+/*
+ * Get the label for a message. Uses the first mblk in the message
+ * which has a non-NULL db_credp.
+ * Returns NULL if there is no credp.
+ */
+extern struct ts_label_s *
+msg_getlabel(const mblk_t *mp)
+{
+	cred_t *cr = msg_getcred(mp, NULL);
+
+	if (cr == NULL)
+		return (NULL);
+
+	return (crgetlabel(cr));
+}
+
 void
 freeb(mblk_t *mp)
 {
diff --git a/usr/src/uts/common/io/strsun.c b/usr/src/uts/common/io/strsun.c
index 23389c0..db6e4aa 100644
--- a/usr/src/uts/common/io/strsun.c
+++ b/usr/src/uts/common/io/strsun.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Solaris DDI STREAMS utility routines (PSARC/2003/648).
  *
@@ -281,13 +278,12 @@
 		blocksize = MIN(iosize, maxblk);
 		ASSERT(blocksize >= 0);
 		if ((mp = allocb_cred(offset + blocksize + tail_len,
-		    CRED())) == NULL) {
+		    CRED(), curproc->p_pid)) == NULL) {
 			*errorp = ENOMEM;
 			return (head);
 		}
 		mp->b_rptr += offset;
 		mp->b_wptr = mp->b_rptr + blocksize;
-		DB_CPID(mp) = curproc->p_pid;
 
 		*tail = mp;
 		tail = &mp->b_cont;
diff --git a/usr/src/uts/common/io/timod.c b/usr/src/uts/common/io/timod.c
index 1f99017..4d9e4ea 100644
--- a/usr/src/uts/common/io/timod.c
+++ b/usr/src/uts/common/io/timod.c
@@ -20,15 +20,13 @@
  */
 /* ONC_PLUS EXTRACT START */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
 
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Transport Interface Library cooperating module - issue 2
  */
@@ -662,7 +660,7 @@
 
 	tp = (struct tim_tim *)q->q_ptr;
 	if (!tp)
-	    return;
+		return;
 
 	while ((mp = getq(q)) != NULL) {
 		if (timodrproc(q, mp)) {
@@ -852,9 +850,8 @@
 				if (ntp->tim_peercred != NULL)
 					crfree(ntp->tim_peercred);
 				ntp->tim_peercred =
-				    DB_CRED(tp->tim_iocsave->b_cont);
-				ntp->tim_cpid =
-				    DB_CPID(tp->tim_iocsave->b_cont);
+				    msg_getcred(tp->tim_iocsave->b_cont,
+				    &ntp->tim_cpid);
 				if (ntp->tim_peercred != NULL)
 					crhold(ntp->tim_peercred);
 
@@ -922,7 +919,7 @@
 
 			if (((tp->tim_flags & WAITIOCACK) == 0) ||
 			    ((tp->tim_saved_prim != O_T_BIND_REQ) &&
-				(tp->tim_saved_prim != T_BIND_REQ))) {
+			    (tp->tim_saved_prim != T_BIND_REQ))) {
 				putnext(q, mp);
 				break;
 			}
@@ -970,7 +967,7 @@
 		}
 
 /* ONC_PLUS EXTRACT END */
-	    case T_OPTMGMT_ACK:
+		case T_OPTMGMT_ACK:
 
 		tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0);
 
@@ -992,23 +989,23 @@
 		break;
 
 		case T_INFO_ACK: {
-		    struct T_info_ack *tia = (struct T_info_ack *)pptr;
+		struct T_info_ack *tia = (struct T_info_ack *)pptr;
 
-		    /* Restore db_type - recover() might have changed it */
-		    mp->b_datap->db_type = M_PCPROTO;
+		/* Restore db_type - recover() might have changed it */
+		mp->b_datap->db_type = M_PCPROTO;
 
-		    if (blen < sizeof (*tia)) {
+		if (blen < sizeof (*tia)) {
 			putnext(q, mp);
 			break;
-		    }
+		}
 
-		    tilog("timodrproc: Got T_INFO_ACK, flags = %x\n",
-			tp->tim_flags);
+		tilog("timodrproc: Got T_INFO_ACK, flags = %x\n",
+		    tp->tim_flags);
 
-		    timodprocessinfo(q, tp, tia);
+		timodprocessinfo(q, tp, tia);
 
-		    TILOG("timodrproc: flags = %x\n", tp->tim_flags);
-		    if ((tp->tim_flags & WAITIOCACK) != 0) {
+		TILOG("timodrproc: flags = %x\n", tp->tim_flags);
+		if ((tp->tim_flags & WAITIOCACK) != 0) {
 			size_t	expected_ack_size;
 			ssize_t	deficit;
 			int	ioc_cmd;
@@ -1100,7 +1097,7 @@
 			}
 
 			expected_ack_size =
-				sizeof (struct T_info_ack); /* TI_GETINFO */
+			    sizeof (struct T_info_ack); /* TI_GETINFO */
 			if (iocbp->ioc_cmd == TI_SYNC) {
 				expected_ack_size = 2 * sizeof (uint32_t) +
 				    sizeof (struct ti_sync_ack);
@@ -1110,8 +1107,8 @@
 			if (deficit != 0) {
 				if (mp->b_datap->db_lim - mp->b_wptr <
 				    deficit) {
-				    mblk_t *tmp = allocb(expected_ack_size,
-					BPRI_HI);
+					mblk_t *tmp = allocb(expected_ack_size,
+					    BPRI_HI);
 				    if (tmp == NULL) {
 					ASSERT(MBLKSIZE(mp) >=
 						sizeof (struct T_error_ack));
@@ -1121,7 +1118,7 @@
 
 					mp->b_rptr = mp->b_datap->db_base;
 					pptr = (union T_primitives *)
-						mp->b_rptr;
+					    mp->b_rptr;
 					pptr->error_ack.ERROR_prim = T_INFO_REQ;
 					pptr->error_ack.TLI_error = TSYSERR;
 					pptr->error_ack.UNIX_error = EAGAIN;
@@ -1190,7 +1187,7 @@
 			tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK |
 			    TI_CAP_RECVD | CAP_WANTS_INFO);
 			break;
-		    }
+		}
 	    }
 
 	    putnext(q, mp);
@@ -1233,10 +1230,9 @@
 		mutex_enter(&tp->tim_mutex);
 		if (tp->tim_peercred != NULL)
 			crfree(tp->tim_peercred);
-		tp->tim_peercred = DB_CRED(mp);
+		tp->tim_peercred = msg_getcred(mp, &tp->tim_cpid);
 		if (tp->tim_peercred != NULL)
 			crhold(tp->tim_peercred);
-		tp->tim_cpid = DB_CPID(mp);
 		mutex_exit(&tp->tim_mutex);
 
 		tilog("timodrproc: Got T_CONN_CON\n", 0);
@@ -1261,23 +1257,23 @@
 		disp = (struct T_discon_ind *)mp->b_rptr;
 
 		tilog("timodrproc: Got T_DISCON_IND Reason: %d\n",
-			disp->DISCON_reason);
+		    disp->DISCON_reason);
 
 		tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL);
 		tim_clear_peer(tp);
 		for (nbp = tp->tim_consave; nbp; nbp = nbp->b_next) {
-		    conp = (struct T_conn_ind *)nbp->b_rptr;
-		    if (conp->SEQ_number == disp->SEQ_number)
-			break;
-		    pbp = nbp;
+			conp = (struct T_conn_ind *)nbp->b_rptr;
+			if (conp->SEQ_number == disp->SEQ_number)
+				break;
+			pbp = nbp;
 		}
 		if (nbp) {
-		    if (pbp)
-			pbp->b_next = nbp->b_next;
-		    else
-			tp->tim_consave = nbp->b_next;
-		    nbp->b_next = NULL;
-		    freemsg(nbp);
+			if (pbp)
+				pbp->b_next = nbp->b_next;
+			else
+				tp->tim_consave = nbp->b_next;
+			nbp->b_next = NULL;
+			freemsg(nbp);
 		}
 		putnext(q, mp);
 		break;
@@ -1596,7 +1592,7 @@
 
 	ASSERT(q != NULL);
 	if (q->q_ptr == NULL)
-	    return;
+		return;
 
 	while ((mp = getq(q)) != NULL) {
 		if (timodwproc(q, mp)) {
@@ -1688,7 +1684,7 @@
 				if (cmp != NULL &&
 				    iocbp->ioc_flag == IOC_NATIVE &&
 				    (tp->tim_flags &
-					(CONNWAIT|LOCORDREL|REMORDREL)) == 0 &&
+				    (CONNWAIT|LOCORDREL|REMORDREL)) == 0 &&
 				    tp->tim_peercred != NULL &&
 				    DB_TYPE(cmp) == M_DATA &&
 				    MBLKL(cmp) == sizeof (k_peercred_t)) {
@@ -2675,9 +2671,9 @@
 			 */
 			if ((bp->b_datap->db_type == M_PROTO) &&
 			    ((bp->b_wptr - bp->b_rptr) >=
-				sizeof (struct T_exdata_ind)) &&
+			    sizeof (struct T_exdata_ind)) &&
 			    (((struct T_exdata_ind *)bp->b_rptr)->PRIM_type
-				== T_EXDATA_IND)) {
+			    == T_EXDATA_IND)) {
 				/* bp is T_EXDATA_IND */
 				mutex_exit(QLOCK(rq));
 				releasestr(q); /* decrement sd_refcnt  */
@@ -3012,6 +3008,8 @@
 	/* Verify credentials in STREAM */
 	ASSERT(iocb->ioc_cr == NULL || iocb->ioc_cr == DB_CRED(tmp));
 
+	ASSERT(DB_CRED(tmp) != NULL);
+
 	TILOG("timodwproc: sending down %d\n", tp->tim_saved_prim);
 	putnext(q, tmp);
 }
diff --git a/usr/src/uts/common/io/tl.c b/usr/src/uts/common/io/tl.c
index 97da83a..7ddb24c 100644
--- a/usr/src/uts/common/io/tl.c
+++ b/usr/src/uts/common/io/tl.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -674,8 +674,6 @@
 #define		IS_COTSORD(x)	(((x)->te_flag & TL_TICOTSORD) != 0)
 #define		IS_SOCKET(x)	(((x)->te_flag & TL_SOCKET) != 0)
 
-#define	TLPID(mp, tep)	(DB_CPID(mp) == -1 ? (tep)->te_cpid : DB_CPID(mp))
-
 /*
  * Certain operations are always used together. These macros reduce the chance
  * of missing a part of a combination.
@@ -2742,10 +2740,25 @@
 	tl_endpt_t *tep;
 	mblk_t *ackmp;
 	union T_primitives *prim;
+	cred_t *cr;
 
 	tep = (tl_endpt_t *)wq->q_ptr;
 	prim = (union T_primitives *)mp->b_rptr;
 
+	/*
+	 * All Solaris components should pass a db_credp
+	 * for this TPI message, hence we ASSERT.
+	 * But in case there is some other M_PROTO that looks
+	 * like a TPI message sent by some other kernel
+	 * component, we check and return an error.
+	 */
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		tl_error_ack(wq, mp, TSYSERR, EINVAL, prim->type);
+		return;
+	}
+
 	/*  all states OK for AF_UNIX options ? */
 	if (!IS_SOCKET(tep) && tep->te_state != TS_IDLE &&
 	    prim->type == T_SVR4_OPTMGMT_REQ) {
@@ -2776,11 +2789,11 @@
 	 * call common option management routine from drv/ip
 	 */
 	if (prim->type == T_SVR4_OPTMGMT_REQ) {
-		(void) svr4_optcom_req(wq, mp, tep->te_credp, &tl_opt_obj,
+		(void) svr4_optcom_req(wq, mp, cr, &tl_opt_obj,
 		    B_FALSE);
 	} else {
 		ASSERT(prim->type == T_OPTMGMT_REQ);
-		(void) tpi_optcom_req(wq, mp, tep->te_credp, &tl_opt_obj,
+		(void) tpi_optcom_req(wq, mp, cr, &tl_opt_obj,
 		    B_FALSE);
 	}
 }
@@ -3199,8 +3212,7 @@
 
 	if (peer_tep != NULL && peer_tep->te_credp != NULL &&
 	    confmp != NULL) {
-		mblk_setcred(confmp, peer_tep->te_credp);
-		DB_CPID(confmp) = peer_tep->te_cpid;
+		mblk_setcred(confmp, peer_tep->te_credp, peer_tep->te_cpid);
 	}
 
 	tl_ok_ack(wq, ackmp, T_CONN_REQ);
@@ -3238,12 +3250,16 @@
 	addr_startp = cimp->b_rptr + ci->SRC_offset;
 	bcopy(tep->te_abuf, addr_startp, tep->te_alen);
 	if (peer_tep->te_flag & (TL_SETCRED|TL_SETUCRED)) {
+		cred_t *cr;
+		pid_t cpid;
+
 		ci->OPT_offset = (t_scalar_t)T_ALIGN(ci->SRC_offset +
 		    ci->SRC_length);
 		ci->OPT_length = olen; /* because only 1 option */
+		cr = msg_getcred(cimp, &cpid);
+		ASSERT(cr != NULL);
 		tl_fill_option(cimp->b_rptr + ci->OPT_offset,
-		    DB_CREDDEF(cimp, tep->te_credp),
-		    TLPID(cimp, tep),
+		    cr, cpid,
 		    peer_tep->te_flag, peer_tep->te_credp);
 	} else if (ooff != 0) {
 		/* Copy option from T_CONN_REQ */
@@ -3735,8 +3751,7 @@
 		 * Forward the credential in the packet so it can be picked up
 		 * at the higher layers for more complete credential processing
 		 */
-		mblk_setcred(ccmp, acc_ep->te_credp);
-		DB_CPID(ccmp) = acc_ep->te_cpid;
+		mblk_setcred(ccmp, acc_ep->te_credp, acc_ep->te_cpid);
 	} else {
 		freemsg(respmp);
 		respmp = NULL;
@@ -5205,15 +5220,20 @@
 		    (t_scalar_t)T_ALIGN(udind->SRC_offset + udind->SRC_length);
 		udind->OPT_length = olen;
 		if (peer_tep->te_flag & (TL_SETCRED|TL_SETUCRED|TL_SOCKUCRED)) {
+			cred_t *cr;
+			pid_t cpid;
+
 			if (oldolen != 0) {
 				bcopy((void *)((uintptr_t)udreq + ooff),
 				    (void *)((uintptr_t)udind +
 				    udind->OPT_offset),
 				    oldolen);
 			}
+			cr = msg_getcred(mp, &cpid);
+			ASSERT(cr != NULL);
+
 			tl_fill_option(ui_mp->b_rptr + udind->OPT_offset +
-			    oldolen,
-			    DB_CREDDEF(mp, tep->te_credp), TLPID(mp, tep),
+			    oldolen, cr, cpid,
 			    peer_tep->te_flag, peer_tep->te_credp);
 		} else {
 			bcopy((void *)((uintptr_t)udreq + ooff),
@@ -5941,6 +5961,8 @@
 static void
 tl_fill_option(uchar_t *buf, cred_t *cr, pid_t cpid, int flag, cred_t *pcr)
 {
+	ASSERT(cr != NULL);
+
 	if (flag & TL_SETCRED) {
 		struct opthdr *opt = (struct opthdr *)buf;
 		tl_credopt_t *tlcred;
diff --git a/usr/src/uts/common/ipp/flowacct/flowacct.c b/usr/src/uts/common/ipp/flowacct/flowacct.c
index 7249c74..ad20861 100644
--- a/usr/src/uts/common/ipp/flowacct/flowacct.c
+++ b/usr/src/uts/common/ipp/flowacct/flowacct.c
@@ -20,12 +20,10 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/kmem.h>
 #include <sys/conf.h>
@@ -41,6 +39,7 @@
 #include <inet/ip6.h>
 #include <sys/ddi.h>
 #include <sys/strsun.h>
+#include <sys/strsubr.h>
 #include <ipp/flowacct/flowacct_impl.h>
 
 /*
@@ -212,10 +211,8 @@
 {
 	cred_t *cr;
 
-	while (DB_CRED(mp) == NULL && mp->b_cont != NULL)
-		mp = mp->b_cont;
-
-	if ((cr = DB_CRED(mp)) != NULL) {
+	cr = msg_getcred(mp, NULL);
+	if (cr != NULL) {
 		header->uid = crgetuid(cr);
 		header->projid = crgetprojid(cr);
 	} else {
diff --git a/usr/src/uts/common/ipp/ipgpc/classifier.c b/usr/src/uts/common/ipp/ipgpc/classifier.c
index 9137fcb..5d6906e 100644
--- a/usr/src/uts/common/ipp/ipgpc/classifier.c
+++ b/usr/src/uts/common/ipp/ipgpc/classifier.c
@@ -27,6 +27,7 @@
 #include <sys/kmem.h>
 #include <sys/systm.h>
 #include <sys/socket.h>
+#include <sys/strsubr.h>
 #include <sys/strsun.h>
 #include <netinet/in.h>
 #include <ipp/ipgpc/classifier.h>
@@ -588,10 +589,8 @@
 {
 	cred_t *cr;
 
-	while (DB_CRED(mp) == NULL && mp->b_cont != NULL)
-		mp = mp->b_cont;
-
-	if ((cr = DB_CRED(mp)) != NULL) {
+	cr = msg_getcred(mp, NULL);
+	if (cr != NULL) {
 		packet->uid = crgetuid(cr);
 		packet->projid = crgetprojid(cr);
 	} else {
diff --git a/usr/src/uts/common/ktli/t_kconnect.c b/usr/src/uts/common/ktli/t_kconnect.c
index cf8dbf4..af7fdaa 100644
--- a/usr/src/uts/common/ktli/t_kconnect.c
+++ b/usr/src/uts/common/ktli/t_kconnect.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,8 +36,6 @@
  * contributors.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Kernel TLI-like function to allow a trasnport endpoint to initiate a
  * connection to another transport endpoint.  This function will wait for
@@ -85,8 +83,20 @@
 
 	fp = tiptr->fp;
 	msgsz = (int)TCONNREQSZ;
-	while (!(bp = allocb(msgsz + sndcall->addr.len + sndcall->opt.len,
-	    BPRI_LO))) {
+	/*
+	 * Usually connect()s are performed with the credential of the caller;
+	 * in this particular case we specifically use the credential of
+	 * the opener as this call is typically done in the context of a user
+	 * process but on behalf of the kernel, e.g., a client connection
+	 * to a server which is later shared by different users.
+	 * At open time, we make sure to set fp->f_cred to kcred if such is
+	 * the case.
+	 *
+	 * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will
+	 * appear as -1.
+	 */
+	while (!(bp = allocb_cred(msgsz + sndcall->addr.len + sndcall->opt.len,
+	    fp->f_cred, NOPID))) {
 		if (strwaitbuf(msgsz + sndcall->addr.len + sndcall->opt.len,
 		    BPRI_LO))
 			return (ENOSR);
diff --git a/usr/src/uts/common/ktli/t_ksndudat.c b/usr/src/uts/common/ktli/t_ksndudat.c
index 24a258f..c5d4435 100644
--- a/usr/src/uts/common/ktli/t_ksndudat.c
+++ b/usr/src/uts/common/ktli/t_ksndudat.c
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -37,8 +36,6 @@
  * contributors.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * TLI-like function to send datagrams over a specified
  * transport endpoint.
@@ -131,8 +128,20 @@
 	 */
 gotdp:
 	msgsz = (int)TUNITDATAREQSZ;
-	while (!(bp = allocb(msgsz + unitdata->addr.len + unitdata->opt.len,
-	    BPRI_LO))) {
+	/*
+	 * Usually sendto()s are performed with the credential of the caller;
+	 * in this particular case we specifically use the credential of
+	 * the opener as this call is typically done in the context of a user
+	 * process but on behalf of the kernel, e.g., a client connection
+	 * to a server which is later shared by different users.
+	 * At open time, we make sure to set fp->f_cred to kcred if such is
+	 * the case.
+	 *
+	 * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will
+	 * appear as -1.
+	 */
+	while (!(bp = allocb_cred(msgsz + unitdata->addr.len +
+	    unitdata->opt.len, fp->f_cred, NOPID))) {
 		if (strwaitbuf(msgsz + unitdata->addr.len + unitdata->opt.len,
 		    BPRI_LO)) {
 			if (dbp && (dbp != unitdata->udata.udata_mp))
diff --git a/usr/src/uts/common/os/driver_lyr.c b/usr/src/uts/common/os/driver_lyr.c
index b08efe1..217e289 100644
--- a/usr/src/uts/common/os/driver_lyr.c
+++ b/usr/src/uts/common/os/driver_lyr.c
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Layered driver support.
  */
@@ -2170,6 +2168,13 @@
 		return (ENOTSUP);
 	}
 
+	/*
+	 * If we don't have db_credp, set it. Note that we can not be called
+	 * from interrupt context.
+	 */
+	if (msg_getcred(smp, NULL) == NULL)
+		mblk_setcred(smp, CRED(), curproc->p_pid);
+
 	/* Send message while honoring flow control */
 	ret = kstrputmsg(handlep->lh_vp, smp, NULL, 0, 0,
 	    MSG_BAND | MSG_HOLDSIG | MSG_IGNERROR, 0);
diff --git a/usr/src/uts/common/os/streamio.c b/usr/src/uts/common/os/streamio.c
index 2b7daaa..e4744da 100644
--- a/usr/src/uts/common/os/streamio.c
+++ b/usr/src/uts/common/os/streamio.c
@@ -2566,7 +2566,7 @@
 /*
  * Copyin and send data down a stream.
  * The caller will allocate and copyin any control part that precedes the
- * message and pass than in as mctl.
+ * message and pass that in as mctl.
  *
  * Caller should *not* hold sd_lock.
  * When EWOULDBLOCK is returned the caller has to redo the canputnext
@@ -2591,7 +2591,6 @@
 	queue_t *wqp = stp->sd_wrq;
 	int error = 0;
 	ssize_t count = *iosize;
-	cred_t *cr;
 
 	ASSERT(MUTEX_NOT_HELD(&stp->sd_lock));
 
@@ -2634,14 +2633,6 @@
 			else if (mp != NULL)
 				linkb(mctl, mp);
 			mp = mctl;
-			/*
-			 * Note that for interrupt thread, the CRED() is
-			 * NULL. Don't bother with the pid either.
-			 */
-			if ((cr = CRED()) != NULL) {
-				mblk_setcred(mp, cr);
-				DB_CPID(mp) = curproc->p_pid;
-			}
 		} else if (mp == NULL)
 			return (0);
 
@@ -2680,14 +2671,6 @@
 		else if (mp != NULL)
 			linkb(mctl, mp);
 		mp = mctl;
-		/*
-		 * Note that for interrupt thread, the CRED() is
-		 * NULL.  Don't bother with the pid either.
-		 */
-		if ((cr = CRED()) != NULL) {
-			mblk_setcred(mp, cr);
-			DB_CPID(mp) = curproc->p_pid;
-		}
 	} else if (mp == NULL) {
 		return (0);
 	}
@@ -5961,7 +5944,7 @@
 		return (EINVAL);
 
 	if ((bp = allocb_cred_wait(sizeof (union ioctypes), sigflag, &error,
-	    crp)) == NULL)
+	    crp, curproc->p_pid)) == NULL)
 			return (error);
 
 	bzero(bp->b_wptr, sizeof (union ioctypes));
@@ -5974,7 +5957,6 @@
 	crhold(crp);
 	iocbp->ioc_cr = crp;
 	DB_TYPE(bp) = M_IOCTL;
-	DB_CPID(bp) = curproc->p_pid;
 	bp->b_wptr += sizeof (struct iocblk);
 
 	if (flag & STR_NOERROR)
@@ -6320,8 +6302,7 @@
 		bp->b_wptr = bp->b_rptr + sizeof (struct copyresp);
 		bp->b_datap->db_type = M_IOCDATA;
 
-		mblk_setcred(bp, crp);
-		DB_CPID(bp) = curproc->p_pid;
+		mblk_setcred(bp, crp, curproc->p_pid);
 		resp = (struct copyresp *)bp->b_rptr;
 		resp->cp_rval = (caddr_t)(uintptr_t)error;
 		resp->cp_flag = (fflags & FMODELS);
@@ -6365,8 +6346,7 @@
 		bp->b_wptr = bp->b_rptr + sizeof (struct copyresp);
 		bp->b_datap->db_type = M_IOCDATA;
 
-		mblk_setcred(bp, crp);
-		DB_CPID(bp) = curproc->p_pid;
+		mblk_setcred(bp, crp, curproc->p_pid);
 		resp = (struct copyresp *)bp->b_rptr;
 		resp->cp_rval = (caddr_t)(uintptr_t)error;
 		resp->cp_flag = (fflags & FMODELS);
@@ -6421,7 +6401,8 @@
 	if (scp->sc_timeout > 0)
 		timeout = scp->sc_timeout * MILLISEC;
 
-	if ((mp = allocb_cred(sizeof (struct cmdblk), crp)) == NULL)
+	if ((mp = allocb_cred(sizeof (struct cmdblk), crp,
+	    curproc->p_pid)) == NULL)
 		return (ENOMEM);
 
 	crhold(crp);
@@ -6440,7 +6421,8 @@
 	 * Copy in the payload.
 	 */
 	if (cmdp->cb_len > 0) {
-		mp->b_cont = allocb_cred(sizeof (scp->sc_buf), crp);
+		mp->b_cont = allocb_cred(sizeof (scp->sc_buf), crp,
+		    curproc->p_pid);
 		if (mp->b_cont == NULL) {
 			error = ENOMEM;
 			goto out;
diff --git a/usr/src/uts/common/os/strsubr.c b/usr/src/uts/common/os/strsubr.c
index 0ae1dd9..61e8ca1 100644
--- a/usr/src/uts/common/os/strsubr.c
+++ b/usr/src/uts/common/os/strsubr.c
@@ -1464,8 +1464,8 @@
 	 */
 	ASSERT(count >= 0);
 
-	if ((tmp = allocb_cred_wait(count, (flag & STR_NOSIG), &error, cr)) ==
-	    NULL) {
+	if ((tmp = allocb_cred_wait(count, (flag & STR_NOSIG), &error, cr,
+	    curproc->p_pid)) == NULL) {
 		return (error);
 	}
 	error = strcopyin(arg, tmp->b_wptr, count, flag & (U_TO_K|K_TO_K));
@@ -2793,6 +2793,10 @@
 	mblk_t *bp = NULL;
 	unsigned char msgtype;
 	int error = 0;
+	cred_t *cr = CRED();
+
+	/* We do not support interrupt threads using the stream head to send */
+	ASSERT(cr != NULL);
 
 	*mpp = NULL;
 	/*
@@ -2821,7 +2825,8 @@
 		 * Range checking has already been done; simply try
 		 * to allocate a message block for the ctl part.
 		 */
-		while (!(bp = allocb(allocsz, BPRI_MED))) {
+		while ((bp = allocb_cred(allocsz, cr,
+		    curproc->p_pid)) == NULL) {
 			if (fflag & (FNDELAY|FNONBLOCK))
 				return (EAGAIN);
 			if (error = strwaitbuf(allocsz, BPRI_MED))
@@ -2864,12 +2869,16 @@
 	int error = 0;
 	ssize_t maxblk;
 	ssize_t count = *iosize;
-	cred_t *cr = CRED();
+	cred_t *cr;
 
 	*mpp = NULL;
 	if (count < 0)
 		return (0);
 
+	/* We do not support interrupt threads using the stream head to send */
+	cr = CRED();
+	ASSERT(cr != NULL);
+
 	maxblk = stp->sd_maxblk;
 	if (maxblk == INFPSZ)
 		maxblk = count;
@@ -2885,7 +2894,8 @@
 
 		size = MIN(count, maxblk);
 
-		while ((bp = allocb_cred(size + extra, cr)) == NULL) {
+		while ((bp = allocb_cred(size + extra, cr,
+		    curproc->p_pid)) == NULL) {
 			error = EAGAIN;
 			if ((uiop->uio_fmode & (FNDELAY|FNONBLOCK)) ||
 			    (error = strwaitbuf(size + extra, BPRI_MED)) != 0) {
@@ -8383,34 +8393,51 @@
 
 /*
  * Replace the cred currently in the mblk with a different one.
+ * Also update db_cpid.
  */
 void
-mblk_setcred(mblk_t *mp, cred_t *cr)
+mblk_setcred(mblk_t *mp, cred_t *cr, pid_t cpid)
 {
-	cred_t *ocr = DB_CRED(mp);
+	dblk_t *dbp = mp->b_datap;
+	cred_t *ocr = dbp->db_credp;
 
 	ASSERT(cr != NULL);
 
 	if (cr != ocr) {
-		crhold(mp->b_datap->db_credp = cr);
+		crhold(dbp->db_credp = cr);
 		if (ocr != NULL)
 			crfree(ocr);
 	}
+	/* Don't overwrite with NOPID */
+	if (cpid != NOPID)
+		dbp->db_cpid = cpid;
 }
 
 /*
- * Set the cred and pid for each mblk in the message. It is assumed that
- * the message passed in does not already have a cred.
+ * If the src message has a cred, then replace the cred currently in the mblk
+ * with it.
+ * Also update db_cpid.
  */
 void
-msg_setcredpid(mblk_t *mp, cred_t *cr, pid_t pid)
+mblk_copycred(mblk_t *mp, const mblk_t *src)
 {
-	while (mp != NULL) {
-		ASSERT(DB_CRED(mp) == NULL);
-		mblk_setcred(mp, cr);
-		DB_CPID(mp) = pid;
-		mp = mp->b_cont;
+	dblk_t *dbp = mp->b_datap;
+	cred_t *cr, *ocr;
+	pid_t cpid;
+
+	cr = msg_getcred(src, &cpid);
+	if (cr == NULL)
+		return;
+
+	ocr = dbp->db_credp;
+	if (cr != ocr) {
+		crhold(dbp->db_credp = cr);
+		if (ocr != NULL)
+			crfree(ocr);
 	}
+	/* Don't overwrite with NOPID */
+	if (cpid != NOPID)
+		dbp->db_cpid = cpid;
 }
 
 int
diff --git a/usr/src/uts/common/rpc/clnt_clts.c b/usr/src/uts/common/rpc/clnt_clts.c
index 70c16c6..e42d156 100644
--- a/usr/src/uts/common/rpc/clnt_clts.c
+++ b/usr/src/uts/common/rpc/clnt_clts.c
@@ -172,7 +172,7 @@
  * Request dipatching function.
  */
 static int clnt_clts_dispatch_send(queue_t *q, mblk_t *, struct netbuf *addr,
-					calllist_t *, uint_t);
+					calllist_t *, uint_t, cred_t *);
 
 /*
  * The size of the preserialized RPC header information.
@@ -582,7 +582,7 @@
 	round_trip = lbolt;
 
 	error = clnt_clts_dispatch_send(p->cku_endpnt->e_wq, mp,
-	    &p->cku_addr, call, p->cku_xid);
+	    &p->cku_addr, call, p->cku_xid, p->cku_cred);
 
 	if (error != 0) {
 		freemsg(mp);
@@ -2058,7 +2058,7 @@
  */
 static int
 clnt_clts_dispatch_send(queue_t *q, mblk_t *mp, struct netbuf *addr,
-			calllist_t *cp,	uint_t xid)
+    calllist_t *cp, uint_t xid, cred_t *cr)
 {
 	mblk_t *bp;
 	int msgsz;
@@ -2082,7 +2082,11 @@
 	 * Construct the datagram
 	 */
 	msgsz = (int)TUNITDATAREQSZ;
-	while (!(bp = allocb(msgsz + addr->len, BPRI_LO))) {
+	/*
+	 * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will
+	 * appear as -1.
+	 */
+	while (!(bp = allocb_cred(msgsz + addr->len, cr, NOPID))) {
 		if (strwaitbuf(msgsz + addr->len, BPRI_LO))
 			return (ENOSR);
 	}
diff --git a/usr/src/uts/common/rpc/clnt_cots.c b/usr/src/uts/common/rpc/clnt_cots.c
index 8cb5672..3bbf31e 100644
--- a/usr/src/uts/common/rpc/clnt_cots.c
+++ b/usr/src/uts/common/rpc/clnt_cots.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -375,13 +375,13 @@
 
 static struct cm_xprt *connmgr_wrapconnect(struct cm_xprt *,
 	const struct timeval *, struct netbuf *, int, struct netbuf *,
-	struct rpc_err *, bool_t, bool_t);
+	struct rpc_err *, bool_t, bool_t, cred_t *);
 
 static bool_t	connmgr_connect(struct cm_xprt *, queue_t *, struct netbuf *,
 				int, calllist_t *, int *, bool_t reconnect,
-				const struct timeval *, bool_t);
+				const struct timeval *, bool_t, cred_t *);
 
-static bool_t	connmgr_setopt(queue_t *, int, int, calllist_t *);
+static bool_t	connmgr_setopt(queue_t *, int, int, calllist_t *, cred_t *cr);
 static void	connmgr_sndrel(struct cm_xprt *);
 static void	connmgr_snddis(struct cm_xprt *);
 static void	connmgr_close(struct cm_xprt *);
@@ -391,7 +391,7 @@
 
 static struct cm_xprt *connmgr_get(struct netbuf *, const struct timeval *,
 	struct netbuf *, int, struct netbuf *, struct rpc_err *, dev_t,
-	bool_t, int);
+	bool_t, int, cred_t *);
 
 static void connmgr_cancelconn(struct cm_xprt *);
 static enum clnt_stat connmgr_cwait(struct cm_xprt *, const struct timeval *,
@@ -1708,7 +1708,7 @@
 
 	cm_entry = connmgr_get(retryaddr, waitp, &p->cku_addr, p->cku_addrfmly,
 	    &p->cku_srcaddr, &p->cku_err, p->cku_device,
-	    p->cku_client.cl_nosignal, p->cku_useresvport);
+	    p->cku_client.cl_nosignal, p->cku_useresvport, p->cku_cred);
 
 	if (cm_entry == NULL) {
 		/*
@@ -1745,7 +1745,8 @@
 	struct rpc_err	*rpcerr,
 	dev_t		device,
 	bool_t		nosignal,
-	int		useresvport)
+	int		useresvport,
+	cred_t		*cr)
 {
 	struct cm_xprt *cm_entry;
 	struct cm_xprt *lru_entry;
@@ -1840,7 +1841,7 @@
 					 */
 					return (connmgr_wrapconnect(cm_entry,
 					    waitp, destaddr, addrfmly, srcaddr,
-					    rpcerr, TRUE, nosignal));
+					    rpcerr, TRUE, nosignal, cr));
 				}
 				i++;
 				if (cm_entry->x_time - prev_time <= 0 ||
@@ -1941,7 +1942,7 @@
 			if (cm_entry->x_connected == FALSE) {
 				return (connmgr_wrapconnect(cm_entry,
 				    waitp, destaddr, addrfmly, NULL,
-				    rpcerr, TRUE, nosignal));
+				    rpcerr, TRUE, nosignal, cr));
 			} else {
 				CONN_HOLD(cm_entry);
 
@@ -2127,7 +2128,7 @@
 		 * This is a bound end-point so don't close it's stream.
 		 */
 		connected = connmgr_connect(cm_entry, wq, destaddr, addrfmly,
-		    &call, &tidu_size, FALSE, waitp, nosignal);
+		    &call, &tidu_size, FALSE, waitp, nosignal, cr);
 		*rpcerr = call.call_err;
 		cv_destroy(&call.call_cv);
 
@@ -2214,7 +2215,8 @@
 	struct netbuf	*srcaddr,
 	struct rpc_err	*rpcerr,
 	bool_t		reconnect,
-	bool_t		nosignal)
+	bool_t		nosignal,
+	cred_t		*cr)
 {
 	ASSERT(MUTEX_HELD(&connmgr_lock));
 	/*
@@ -2261,7 +2263,7 @@
 
 		connected = connmgr_connect(cm_entry, cm_entry->x_wq,
 		    destaddr, addrfmly, &call, &cm_entry->x_tidu_size,
-		    reconnect, waitp, nosignal);
+		    reconnect, waitp, nosignal, cr);
 
 		*rpcerr = call.call_err;
 		cv_destroy(&call.call_cv);
@@ -2484,7 +2486,8 @@
 	int 			*tidu_ptr,
 	bool_t 			reconnect,
 	const struct timeval 	*waitp,
-	bool_t 			nosignal)
+	bool_t 			nosignal,
+	cred_t			*cr)
 {
 	mblk_t *mp;
 	struct T_conn_req *tcr;
@@ -2496,7 +2499,11 @@
 	if (reconnect)
 		(void) putctl1(wq, M_FLUSH, FLUSHRW);
 
-	mp = allocb(sizeof (*tcr) + addr->len, BPRI_LO);
+	/*
+	 * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will
+	 * appear as -1.
+	 */
+	mp = allocb_cred(sizeof (*tcr) + addr->len, cr, NOPID);
 	if (mp == NULL) {
 		/*
 		 * This is unfortunate, but we need to look up the stats for
@@ -2625,7 +2632,7 @@
 	 * lots of retries and terrible performance.
 	 */
 	if (addrfmly == AF_INET || addrfmly == AF_INET6) {
-		(void) connmgr_setopt(wq, IPPROTO_TCP, TCP_NODELAY, e);
+		(void) connmgr_setopt(wq, IPPROTO_TCP, TCP_NODELAY, e, cr);
 		if (e->call_status == RPC_XPRTFAILED)
 			return (FALSE);
 	}
@@ -2673,7 +2680,7 @@
  * Called by connmgr_connect to set an option on the new stream.
  */
 static bool_t
-connmgr_setopt(queue_t *wq, int level, int name, calllist_t *e)
+connmgr_setopt(queue_t *wq, int level, int name, calllist_t *e, cred_t *cr)
 {
 	mblk_t *mp;
 	struct opthdr *opt;
@@ -2681,8 +2688,8 @@
 	struct timeval waitp;
 	int error;
 
-	mp = allocb(sizeof (struct T_optmgmt_req) + sizeof (struct opthdr) +
-	    sizeof (int), BPRI_LO);
+	mp = allocb_cred(sizeof (struct T_optmgmt_req) +
+	    sizeof (struct opthdr) + sizeof (int), cr, NOPID);
 	if (mp == NULL) {
 		RPCLOG0(1, "connmgr_setopt: cannot alloc mp for option "
 		    "request\n");
diff --git a/usr/src/uts/common/rpc/rpcmod.c b/usr/src/uts/common/rpc/rpcmod.c
index 69eac32..e3576c9 100644
--- a/usr/src/uts/common/rpc/rpcmod.c
+++ b/usr/src/uts/common/rpc/rpcmod.c
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/stropts.h>
+#include <sys/strsubr.h>
 #include <sys/tihdr.h>
 #include <sys/timod.h>
 #include <sys/tiuser.h>
@@ -482,8 +483,8 @@
 	/*
 	 * Allocate the required messages upfront.
 	 */
-	if ((bp = allocb(sizeof (struct T_info_req) +
-	    sizeof (struct T_info_ack), BPRI_LO)) == (mblk_t *)NULL) {
+	if ((bp = allocb_cred(sizeof (struct T_info_req) +
+	    sizeof (struct T_info_ack), crp, curproc->p_pid)) == NULL) {
 		return (ENOBUFS);
 	}
 
diff --git a/usr/src/uts/common/rpc/svc.c b/usr/src/uts/common/rpc/svc.c
index 4f8878d..e33b77b 100644
--- a/usr/src/uts/common/rpc/svc.c
+++ b/usr/src/uts/common/rpc/svc.c
@@ -1299,7 +1299,7 @@
 	    "svc_getreq_start:");
 
 	ASSERT(clone_xprt->xp_master != NULL);
-	ASSERT(!is_system_labeled() || DB_CRED(mp) != NULL ||
+	ASSERT(!is_system_labeled() || msg_getcred(mp, NULL) != NULL ||
 	    mp->b_datap->db_type != M_DATA);
 
 	/*
@@ -1327,17 +1327,13 @@
 	 * get the label from the raw mblk data now.
 	 */
 	if (is_system_labeled()) {
-		mblk_t *lmp;
+		cred_t *cr;
 
 		r.rq_label = kmem_alloc(sizeof (bslabel_t), KM_SLEEP);
-		if (DB_CRED(mp) != NULL)
-			lmp = mp;
-		else {
-			ASSERT(mp->b_cont != NULL);
-			lmp = mp->b_cont;
-			ASSERT(DB_CRED(lmp) != NULL);
-		}
-		bcopy(label2bslabel(crgetlabel(DB_CRED(lmp))), r.rq_label,
+		cr = msg_getcred(mp, NULL);
+		ASSERT(cr != NULL);
+
+		bcopy(label2bslabel(crgetlabel(cr)), r.rq_label,
 		    sizeof (bslabel_t));
 	} else {
 		r.rq_label = NULL;
@@ -2381,7 +2377,7 @@
 
 	TRACE_0(TR_FAC_KRPC, TR_SVC_QUEUEREQ_START, "svc_queuereq_start");
 
-	ASSERT(!is_system_labeled() || DB_CRED(mp) != NULL ||
+	ASSERT(!is_system_labeled() || msg_getcred(mp, NULL) != NULL ||
 	    mp->b_datap->db_type != M_DATA);
 
 	/*
diff --git a/usr/src/uts/common/rpc/svc_clts.c b/usr/src/uts/common/rpc/svc_clts.c
index 4929a3d..56355ea 100644
--- a/usr/src/uts/common/rpc/svc_clts.c
+++ b/usr/src/uts/common/rpc/svc_clts.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- *  Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ *  Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  *  Use is subject to license terms.
  */
 
@@ -244,6 +244,7 @@
 	struct rpc_clts_server *stats = CLONE2STATS(clone_xprt);
 	union T_primitives *pptr;
 	int hdrsz;
+	cred_t *cr;
 
 	TRACE_0(TR_FAC_KRPC, TR_SVC_CLTS_KRECV_START,
 	    "svc_clts_krecv_start:");
@@ -322,6 +323,9 @@
 	 * Save the first mblk which contains the T_unidata_ind in
 	 * ud_resp.  It will be used to generate the T_unitdata_req
 	 * during the reply.
+	 * We reuse any options in the T_unitdata_ind for the T_unitdata_req
+	 * since we must pass any SCM_UCRED across in order for TX to
+	 * work. We also make sure any cred_t is carried across.
 	 */
 	if (ud->ud_resp) {
 		if (ud->ud_resp->b_cont != NULL) {
@@ -331,6 +335,11 @@
 		}
 		freeb(ud->ud_resp);
 	}
+	/* Move any cred_t to the first mblk in the message */
+	cr = msg_getcred(mp, NULL);
+	if (cr != NULL)
+		mblk_setcred(mp, cr, NOPID);
+
 	ud->ud_resp = mp;
 	mp = mp->b_cont;
 	ud->ud_resp->b_cont = NULL;
@@ -479,10 +488,15 @@
 	 * Construct the T_unitdata_req.  We take advantage
 	 * of the fact that T_unitdata_ind looks just like
 	 * T_unitdata_req, except for the primitive type.
+	 * Reusing it means we preserve any options, and we must preserve
+	 * the SCM_UCRED option for TX to work.
+	 * This has the side effect of also passing certain receive-side
+	 * options like IP_RECVDSTADDR back down the send side. This
+	 * implies that we can not ASSERT on a non-NULL db_credp when
+	 * we have send-side options in UDP.
 	 */
 	udreq = (struct T_unitdata_req *)ud->ud_resp->b_rptr;
 	udreq->PRIM_type = T_UNITDATA_REQ;
-
 	put(clone_xprt->xp_wq, ud->ud_resp);
 	stat = TRUE;
 	ud->ud_resp = NULL;
diff --git a/usr/src/uts/common/sys/stream.h b/usr/src/uts/common/sys/stream.h
index 8d1ac45..1b5380f 100644
--- a/usr/src/uts/common/sys/stream.h
+++ b/usr/src/uts/common/sys/stream.h
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -356,16 +356,12 @@
  */
 #define	DB_CPID(mp)		((mp)->b_datap->db_cpid)
 #define	DB_CRED(mp)		((mp)->b_datap->db_credp)
-#define	DB_CREDDEF(mp, cr)	(DB_CRED(mp) != NULL ? DB_CRED(mp) : (cr))
 #define	DB_FTHDR(mp)		((mp)->b_datap->db_fthdr)
 /*
  * Used by GLDv2 to store the TCI information.
  */
 #define	DB_TCI(mp)		((mp)->b_datap->db_struioun.cksum.pad)
 
-#define	MBLK_GETLABEL(mp) \
-	(DB_CRED(mp) != NULL ? crgetlabel(DB_CRED(mp)) : NULL)
-
 /*
  * Message block descriptor
  */
diff --git a/usr/src/uts/common/sys/strsubr.h b/usr/src/uts/common/sys/strsubr.h
index a678650..f13f521 100644
--- a/usr/src/uts/common/sys/strsubr.h
+++ b/usr/src/uts/common/sys/strsubr.h
@@ -1215,12 +1215,15 @@
 extern queue_t *strvp2wq(vnode_t *);
 extern vnode_t *strq2vp(queue_t *);
 extern mblk_t *allocb_wait(size_t, uint_t, uint_t, int *);
-extern mblk_t *allocb_cred(size_t, cred_t *);
-extern mblk_t *allocb_cred_wait(size_t, uint_t, int *, cred_t *);
+extern mblk_t *allocb_cred(size_t, cred_t *, pid_t);
+extern mblk_t *allocb_cred_wait(size_t, uint_t, int *, cred_t *, pid_t);
 extern mblk_t *allocb_tmpl(size_t, const mblk_t *);
 extern mblk_t *allocb_tryhard(size_t);
-extern void mblk_setcred(mblk_t *, cred_t *);
-extern void msg_setcredpid(mblk_t *, cred_t *, pid_t);
+extern void mblk_copycred(mblk_t *, const mblk_t *);
+extern void mblk_setcred(mblk_t *, cred_t *, pid_t);
+extern cred_t *msg_getcred(const mblk_t *, pid_t *);
+extern struct ts_label_s *msg_getlabel(const mblk_t *);
+extern cred_t *msg_extractcred(mblk_t *, pid_t *);
 extern void strpollwakeup(vnode_t *, short);
 extern int putnextctl_wait(queue_t *, int);