PSARC 2008/208 Flexible Credentials and Result Limits for Kernel Door Upcalls
authorjwadams
Tue, 01 Jul 2008 17:10:40 -0700
changeset 6997 056043f166c6
parent 6996 f477c11879f1
child 6998 58787ea78303
PSARC 2008/208 Flexible Credentials and Result Limits for Kernel Door Upcalls 6687107 upcall clients should properly handle results
usr/src/uts/common/c2/audit_io.c
usr/src/uts/common/crypto/core/kcf.c
usr/src/uts/common/fs/autofs/auto_subr.c
usr/src/uts/common/fs/dev/sdev_comm.c
usr/src/uts/common/fs/doorfs/door_sys.c
usr/src/uts/common/fs/nfs/nfs4_idmap.c
usr/src/uts/common/fs/nfs/nfs_auth.c
usr/src/uts/common/fs/smbsrv/smb_kdoor_clnt.c
usr/src/uts/common/fs/smbsrv/smb_kshare.c
usr/src/uts/common/fs/smbsrv/smb_winpipe.c
usr/src/uts/common/idmap/idmap_kapi.c
usr/src/uts/common/io/dls/dls_mgmt.c
usr/src/uts/common/io/lvm/md/md_subr.c
usr/src/uts/common/io/net80211/net80211.c
usr/src/uts/common/io/vscan/vscan_door.c
usr/src/uts/common/os/evchannels.c
usr/src/uts/common/os/klpd.c
usr/src/uts/common/os/log_sysevent.c
usr/src/uts/common/os/zone.c
usr/src/uts/common/sys/door.h
usr/src/uts/common/sys/door_data.h
usr/src/uts/intel/ia32/ml/modstubs.s
usr/src/uts/sparc/ml/modstubs.s
usr/src/uts/sun4v/io/drctl_impl.c
--- a/usr/src/uts/common/c2/audit_io.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/c2/audit_io.c	Tue Jul 01 17:10:40 2008 -0700
@@ -537,7 +537,8 @@
 
 		retry = 0;
 		mutex_enter(&(kctx->auk_svc_lock));
-		rc = door_upcall(kctx->auk_current_vp, &darg, NULL);
+		rc = door_upcall(kctx->auk_current_vp, &darg, NULL,
+		    SIZE_MAX, 0);
 		if (rc != 0) {
 			mutex_exit(&(kctx->auk_svc_lock));
 			if (rc == EAGAIN)
--- a/usr/src/uts/common/crypto/core/kcf.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/crypto/core/kcf.c	Tue Jul 01 17:10:40 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -307,7 +307,7 @@
 	/*
 	 * Make door upcall. door_ki_upcall() checks for validity of the handle.
 	 */
-	rv = door_ki_upcall(ldh, &darg);
+	rv = door_ki_upcall_limited(ldh, &darg, NULL, SIZE_MAX, 0);
 
 	if (rv == 0) {
 		kcf_door_arg_t *rkda =  (kcf_door_arg_t *)darg.rbuf;
--- a/usr/src/uts/common/fs/autofs/auto_subr.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/autofs/auto_subr.c	Tue Jul 01 17:10:40 2008 -0700
@@ -449,7 +449,8 @@
 		door_args.rsize = orl;
 
 		sigintr(&smask, 1);
-		error = door_ki_upcall(dh, &door_args);
+		error =
+		    door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
 		sigunintr(&smask);
 
 		door_ki_rele(dh);
--- a/usr/src/uts/common/fs/dev/sdev_comm.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/dev/sdev_comm.c	Tue Jul 01 17:10:40 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -324,7 +324,8 @@
 	save_arg = darg;
 	for (retry = 0; ; retry++) {
 		sdcmn_err6(("call devfsadm: upcall lookup, retry %d\n", retry));
-		if ((error = door_ki_upcall(sdev_upcall_door, &darg)) == 0) {
+		if ((error = door_ki_upcall_limited(sdev_upcall_door, &darg,
+		    NULL, SIZE_MAX, 0)) == 0) {
 			sdcmn_err6(("call devfsadm: upcall lookup ok\n"));
 			break;
 		}
--- a/usr/src/uts/common/fs/doorfs/door_sys.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/doorfs/door_sys.c	Tue Jul 01 17:10:40 2008 -0700
@@ -1219,7 +1219,7 @@
 	 * to let unref notifications through, though.
 	 */
 	if (datap == DOOR_UNREF_DATA) {
-		if (ct->d_upcall)
+		if (ct->d_upcall != NULL)
 			datasize = 0;
 		else
 			datap = NULL;
@@ -1264,7 +1264,7 @@
 	if (layout->dl_datap != NULL) {
 		ASSERT(datasize != 0);
 		datap = layout->dl_datap;
-		if (ct->d_upcall || datasize <= door_max_arg) {
+		if (ct->d_upcall != NULL || datasize <= door_max_arg) {
 			if (door_stack_copyout(ct->d_buf, datap, datasize)) {
 				error = E2BIG;
 				goto fail;
@@ -1652,6 +1652,7 @@
 	kthread_t	*caller;
 	door_server_t	*st;
 	door_client_t	*ct;
+	door_upcall_t	*dup;
 	struct proc	*p;
 	struct ucred_s	*res;
 	int		err;
@@ -1676,12 +1677,10 @@
 	 * If the credentials are not specified by the client, get the one
 	 * associated with the calling process.
 	 */
-	if (ct->d_cred == NULL) {
-		res = pgetucred(p);
-	} else {
-		res = cred2ucred(ct->d_cred, ct->d_upcall ?
-		    p0.p_pid : p->p_pid, NULL, CRED());
-	}
+	if ((dup = ct->d_upcall) != NULL)
+		res = cred2ucred(dup->du_cred, p0.p_pid, NULL, CRED());
+	else
+		res = cred2ucred(caller->t_cred, p->p_pid, NULL, CRED());
 
 	mutex_enter(&door_knob);
 	DOOR_T_RELEASE(ct);
@@ -2153,7 +2152,13 @@
 		dp->door_flags |= DOOR_UNREF_ACTIVE;
 		mutex_exit(&door_knob);
 
-		(void) door_upcall(DTOV(dp), &unref_args, NULL);
+		(void) door_upcall(DTOV(dp), &unref_args, NULL, SIZE_MAX, 0);
+
+		if (unref_args.rbuf != 0) {
+			kmem_free(unref_args.rbuf, unref_args.rsize);
+			unref_args.rbuf = NULL;
+			unref_args.rsize = 0;
+		}
 
 		mutex_enter(&door_knob);
 		ASSERT(dp->door_flags & DOOR_UNREF_ACTIVE);
@@ -2711,6 +2716,7 @@
 		door_desc_t *desc_ptr, uint_t desc_num)
 {
 	door_client_t	*ct = DOOR_CLIENT(caller->t_door);
+	door_upcall_t	*dup = ct->d_upcall;
 	size_t		dsize;
 	size_t		rlen;
 	size_t		result_size;
@@ -2735,7 +2741,13 @@
 	if ((result_size = rlen + dsize) == 0)
 		return (0);
 
-	if (ct->d_upcall) {
+	if (dup != NULL) {
+		if (desc_num > dup->du_max_descs)
+			return (EMFILE);
+
+		if (data_size > dup->du_max_data)
+			return (E2BIG);
+
 		/*
 		 * Handle upcalls
 		 */
@@ -3050,9 +3062,11 @@
  *	for holding a reference to the cred passed in.
  */
 int
-door_upcall(vnode_t *vp, door_arg_t *param, struct cred *cred)
+door_upcall(vnode_t *vp, door_arg_t *param, struct cred *cred,
+    size_t max_data, uint_t max_descs)
 {
 	/* Locals */
+	door_upcall_t	*dup;
 	door_node_t	*dp;
 	kthread_t	*server_thread;
 	int		error = 0;
@@ -3072,6 +3086,11 @@
 	ct = door_my_client(1);
 	dp = VTOD(vp);	/* Convert to a door_node_t */
 
+	dup = kmem_zalloc(sizeof (*dup), KM_SLEEP);
+	dup->du_cred = (cred != NULL) ? cred : curthread->t_cred;
+	dup->du_max_data = max_data;
+	dup->du_max_descs = max_descs;
+
 	mutex_enter(&door_knob);
 	if (DOOR_INVALID(dp)) {
 		mutex_exit(&door_knob);
@@ -3137,8 +3156,7 @@
 		}
 	}
 
-	ct->d_upcall = 1;
-	ct->d_cred = cred;
+	ct->d_upcall = dup;
 	if (param->rsize == 0)
 		ct->d_noresults = 1;
 	else
@@ -3290,14 +3308,15 @@
 	*param = ct->d_args;		/* structure assignment */
 
 out:
+	kmem_free(dup, sizeof (*dup));
+
 	if (ct->d_fpp) {
 		kmem_free(ct->d_fpp, ct->d_fpp_size);
 		ct->d_fpp = NULL;
 		ct->d_fpp_size = 0;
 	}
 
-	ct->d_cred = NULL;
-	ct->d_upcall = 0;
+	ct->d_upcall = NULL;
 	ct->d_noresults = 0;
 	ct->d_buf = NULL;
 	ct->d_bufsize = 0;
@@ -3354,23 +3373,28 @@
 int
 door_ki_upcall(door_handle_t dh, door_arg_t *param)
 {
-	return (door_ki_upcall_cred(dh, param, NULL));
+	return (door_ki_upcall_limited(dh, param, NULL, SIZE_MAX, UINT_MAX));
 }
 
 /*
- * door_ki_upcall_cred invokes a user-level door server from the kernel with
- * the given credentials. If the "cred" argument is NULL, uses the credentials
- * associated with current thread.
+ * door_ki_upcall_limited invokes a user-level door server from the
+ * kernel with the given credentials and reply limits.  If the "cred"
+ * argument is NULL, uses the credentials associated with current
+ * thread.  max_data limits the maximum length of the returned data (the
+ * client will get E2BIG if they go over), and max_desc limits the
+ * number of returned descriptors (the client will get EMFILE if they
+ * go over).
  */
 int
-door_ki_upcall_cred(door_handle_t dh, door_arg_t *param, struct cred *cred)
+door_ki_upcall_limited(door_handle_t dh, door_arg_t *param, struct cred *cred,
+    size_t max_data, uint_t max_desc)
 {
 	file_t *fp = DHTOF(dh);
 	vnode_t *realvp;
 
 	if (VOP_REALVP(fp->f_vnode, &realvp, NULL))
 		realvp = fp->f_vnode;
-	return (door_upcall(realvp, param, cred));
+	return (door_upcall(realvp, param, cred, max_data, max_desc));
 }
 
 /*
--- a/usr/src/uts/common/fs/nfs/nfs4_idmap.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/nfs/nfs4_idmap.c	Tue Jul 01 17:10:40 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -405,7 +405,7 @@
 	door_args.rbuf = (char *)mapresp;
 	door_args.rsize = sizeof (struct mapid_res);
 
-	error = door_ki_upcall(dh, &door_args);
+	error = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
 	if (!error) {
 		resp = (struct mapid_res *)door_args.rbuf;
 
@@ -601,7 +601,7 @@
 	door_args.rbuf = (char *)mapresp;
 	door_args.rsize = sizeof (struct mapid_res);
 
-	error = door_ki_upcall(dh, &door_args);
+	error = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
 	if (!error) {
 		resp = (struct mapid_res *)door_args.rbuf;
 
@@ -784,7 +784,7 @@
 	door_args.rbuf = (char *)mapresp;
 	door_args.rsize = sizeof (struct mapid_res);
 
-	error = door_ki_upcall(dh, &door_args);
+	error = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
 	if (!error) {
 		resp = (struct mapid_res *)door_args.rbuf;
 
@@ -981,7 +981,7 @@
 	door_args.rbuf = (char *)mapresp;
 	door_args.rsize = sizeof (struct mapid_res);
 
-	error = door_ki_upcall(dh, &door_args);
+	error = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
 	if (!error) {
 		resp = (struct mapid_res *)door_args.rbuf;
 
--- a/usr/src/uts/common/fs/nfs/nfs_auth.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/nfs/nfs_auth.c	Tue Jul 01 17:10:40 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -341,7 +341,7 @@
 	da.rbuf = (char *)rbuf;
 	da.rsize = rbsz;
 
-	switch (door_ki_upcall(dh, &da)) {
+	switch (door_ki_upcall_limited(dh, &da, NULL, SIZE_MAX, 0)) {
 		case 0:				/* Success */
 			if (da.data_ptr != da.rbuf && da.data_size == 0) {
 				/*
--- a/usr/src/uts/common/fs/smbsrv/smb_kdoor_clnt.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_kdoor_clnt.c	Tue Jul 01 17:10:40 2008 -0700
@@ -125,7 +125,8 @@
 	door_arg.rbuf = argp;
 	door_arg.rsize = arg_size;
 
-	if ((err = door_ki_upcall(smb_kdoor_clnt_dh, &door_arg)) != 0) {
+	if ((err = door_ki_upcall_limited(smb_kdoor_clnt_dh, &door_arg, NULL,
+	    SIZE_MAX, 0)) != 0) {
 		cmn_err(CE_WARN, "smb_kdoor_clnt_upcall: failed(%d)", err);
 		kmem_free(argp, arg_size);
 		argp = NULL;
--- a/usr/src/uts/common/fs/smbsrv/smb_kshare.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c	Tue Jul 01 17:10:40 2008 -0700
@@ -98,7 +98,7 @@
 	arg.rbuf = buf;
 	arg.rsize = LMSHR_DOOR_SIZE;
 
-	if (door_ki_upcall(dhdl, &arg) != 0) {
+	if (door_ki_upcall_limited(dhdl, &arg, NULL, SIZE_MAX, 0) != 0) {
 		cmn_err(CE_WARN, "smb_kshare_getinfo: Door call failed");
 		kmem_free(buf, LMSHR_DOOR_SIZE);
 		return (NERR_InternalError);
@@ -159,7 +159,7 @@
 	arg.rbuf = door_buf;
 	arg.rsize = door_bufsz;
 
-	if (door_ki_upcall(dhdl, &arg) != 0) {
+	if (door_ki_upcall_limited(dhdl, &arg, NULL, SIZE_MAX, 0) != 0) {
 		cmn_err(CE_WARN, "smb_kshare_enum: Door call failed");
 		kmem_free(door_buf, door_bufsz);
 		return (NERR_InternalError);
@@ -253,7 +253,7 @@
 	doorarg.rbuf = buf;
 	doorarg.rsize = LMSHR_DOOR_SIZE;
 
-	error = door_ki_upcall(dhdl, &doorarg);
+	error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0);
 
 	if (error) {
 		kmem_free(buf, LMSHR_DOOR_SIZE);
--- a/usr/src/uts/common/fs/smbsrv/smb_winpipe.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_winpipe.c	Tue Jul 01 17:10:40 2008 -0700
@@ -286,7 +286,8 @@
 	da.rbuf = (char *)lbuf;
 	da.rsize = START_UPDOOR_SIZE;
 
-	if (door_ki_upcall(smb_winpipe_dh, &da) != 0) {
+	if (door_ki_upcall_limited(smb_winpipe_dh, &da, NULL,
+	    SIZE_MAX, 0) != 0) {
 		return (-1);
 	}
 	/* RPC_WRITE just queues the data and returns */
--- a/usr/src/uts/common/idmap/idmap_kapi.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/idmap/idmap_kapi.c	Tue Jul 01 17:10:40 2008 -0700
@@ -226,7 +226,7 @@
 		return (-1);
 	}
 
-	status = door_ki_upcall(dh, arg);
+	status = door_ki_upcall_limited(dh, arg, NULL, SIZE_MAX, 0);
 
 	switch (status) {
 	case 0:	/* Success */
--- a/usr/src/uts/common/io/dls/dls_mgmt.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/io/dls/dls_mgmt.c	Tue Jul 01 17:10:40 2008 -0700
@@ -234,7 +234,8 @@
 
 	for (;;) {
 		retry++;
-		if ((err = door_ki_upcall_cred(dh, &darg, kcred)) == 0)
+		if ((err = door_ki_upcall_limited(dh, &darg, kcred,
+		    SIZE_MAX, 0)) == 0)
 			break;
 
 		/*
--- a/usr/src/uts/common/io/lvm/md/md_subr.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/io/lvm/md/md_subr.c	Tue Jul 01 17:10:40 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -3898,7 +3898,8 @@
 	}
 	retry_cnt = 0;
 
-	while ((rval = door_ki_upcall(mdmn_door_handle, &da)) != 0) {
+	while ((rval = door_ki_upcall_limited(mdmn_door_handle, &da, NULL,
+	    SIZE_MAX, 0)) != 0) {
 		if (rval == EAGAIN)  {
 			if ((++retry_cnt % MD_MN_WARN_INTVL) == 0) {
 				cmn_err(CE_WARN, "door call failed. "
--- a/usr/src/uts/common/io/net80211/net80211.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/io/net80211/net80211.c	Tue Jul 01 17:10:40 2008 -0700
@@ -165,7 +165,7 @@
 	darg.rbuf = NULL;
 	darg.rsize = 0;
 
-	if (door_ki_upcall(event_door, &darg) != 0) {
+	if (door_ki_upcall_limited(event_door, &darg, NULL, SIZE_MAX, 0) != 0) {
 		ieee80211_err("ieee80211_event: door_ki_upcall() failed\n");
 	}
 
--- a/usr/src/uts/common/io/vscan/vscan_door.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/io/vscan/vscan_door.c	Tue Jul 01 17:10:40 2008 -0700
@@ -148,7 +148,8 @@
 	arg.rbuf = (char *)&result;
 	arg.rsize = sizeof (uint32_t);
 
-	if ((err = door_ki_upcall(vscan_door_handle, &arg)) != 0) {
+	if ((err = door_ki_upcall_limited(vscan_door_handle, &arg, NULL,
+	    SIZE_MAX, 0)) != 0) {
 		cmn_err(CE_WARN, "Internal communication error (%d)"
 		    "- failed to send scan request to vscand", err);
 		result = VS_STATUS_ERROR;
--- a/usr/src/uts/common/os/evchannels.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/os/evchannels.c	Tue Jul 01 17:10:40 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -864,7 +864,8 @@
 	darg.desc_num = 0;
 
 	for (;;) {
-		if ((error = door_ki_upcall(sdp->sd_door, &darg)) == 0) {
+		if ((error = door_ki_upcall_limited(sdp->sd_door, &darg,
+		    NULL, SIZE_MAX, 0)) == 0) {
 			break;
 		}
 		switch (error) {
--- a/usr/src/uts/common/os/klpd.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/os/klpd.c	Tue Jul 01 17:10:40 2008 -0700
@@ -306,7 +306,8 @@
 	da.rbuf = (char *)&res;
 	da.rsize = sizeof (res);
 
-	while ((dres = door_ki_upcall(p->klpd_door, &da)) != 0) {
+	while ((dres = door_ki_upcall_limited(p->klpd_door, &da, NULL,
+	    SIZE_MAX, 0)) != 0) {
 		switch (dres) {
 		case EAGAIN:
 			delay(1);
--- a/usr/src/uts/common/os/log_sysevent.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/os/log_sysevent.c	Tue Jul 01 17:10:40 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -250,7 +250,8 @@
 
 	save_arg = darg;
 	for (retry = 0; ; retry++) {
-		if ((error = door_ki_upcall(event_door, &darg)) == 0) {
+		if ((error = door_ki_upcall_limited(event_door, &darg, NULL,
+		    SIZE_MAX, 0)) == 0) {
 			break;
 		}
 		switch (error) {
--- a/usr/src/uts/common/os/zone.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/os/zone.c	Tue Jul 01 17:10:40 2008 -0700
@@ -5603,7 +5603,8 @@
 		}
 		ASSERT(door != NULL);
 
-		if ((error = door_ki_upcall(door, &darg)) == 0) {
+		if ((error = door_ki_upcall_limited(door, &darg, NULL,
+		    SIZE_MAX, 0)) == 0) {
 			break;
 		}
 		switch (error) {
--- a/usr/src/uts/common/sys/door.h	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/sys/door.h	Tue Jul 01 17:10:40 2008 -0700
@@ -274,7 +274,7 @@
 int	door_insert(struct file *, door_desc_t *);
 int	door_finish_dispatch(caddr_t);
 uintptr_t door_final_sp(uintptr_t, size_t, int);
-int	door_upcall(vnode_t *, door_arg_t *, struct cred *);
+int	door_upcall(vnode_t *, door_arg_t *, struct cred *, size_t, uint_t);
 void	door_slam(void);
 void	door_exit(void);
 void	door_revoke_all(void);
@@ -293,7 +293,8 @@
  * and may change incompatibly in a minor release of Solaris.
  */
 int	door_ki_upcall(door_handle_t, door_arg_t *);
-int	door_ki_upcall_cred(door_handle_t, door_arg_t *, struct cred *);
+int	door_ki_upcall_limited(door_handle_t, door_arg_t *, struct cred *,
+    size_t, uint_t);
 int	door_ki_create(void (*)(void *, door_arg_t *,
     void (**)(void *, void *), void **, int *), void *, door_attr_t,
     door_handle_t *);
--- a/usr/src/uts/common/sys/door_data.h	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/common/sys/door_data.h	Tue Jul 01 17:10:40 2008 -0700
@@ -50,6 +50,13 @@
 	caddr_t		dl_sp;		/* final stack pointer (non-biased) */
 } door_layout_t;
 
+/* upcall invocation information */
+typedef struct door_upcall_data {
+	cred_t		*du_cred;	/* Credential associated w/ upcall */
+	size_t		du_max_data;	/* Maximum amount of reply data */
+	uint_t		du_max_descs;	/* Maximum number of reply descs */
+} door_upcall_t;
+
 /*
  * Per-thread data associated with door invocations.  Each door invocation
  * effects the client structure of one thread and the server structure of
@@ -58,7 +65,7 @@
  */
 typedef struct door_client {
 	door_arg_t	d_args;		/* Door arg/results */
-	struct cred	*d_cred;	/* Cred overridden by the client */
+	door_upcall_t	*d_upcall;	/* upcall information */
 	caddr_t		d_buf;		/* Temp buffer for data transfer */
 	int		d_bufsize;	/* Size of temp buffer */
 	int		d_fpp_size;	/* Number of File ptrs */
@@ -67,7 +74,6 @@
 	kcondvar_t	d_cv;
 	uchar_t		d_args_done;	/* server has processed client's args */
 	uchar_t		d_hold;		/* Thread needs to stick around */
-	uchar_t		d_upcall;	/* Kernel level upcall */
 	uchar_t		d_noresults;	/* No results allowed */
 	uchar_t		d_overflow;	/* Result overflow occurred */
 	uchar_t		d_kernel;	/* Kernel door server */
--- a/usr/src/uts/intel/ia32/ml/modstubs.s	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/intel/ia32/ml/modstubs.s	Tue Jul 01 17:10:40 2008 -0700
@@ -894,7 +894,7 @@
 	NO_UNLOAD_STUB(doorfs, door_ki_open,		nomod_einval);
 	NO_UNLOAD_STUB(doorfs, door_ki_lookup,		nomod_zero);
 	WSTUB(doorfs, door_ki_upcall,			nomod_einval);
-	WSTUB(doorfs, door_ki_upcall_cred,		nomod_einval);
+	WSTUB(doorfs, door_ki_upcall_limited,		nomod_einval);
 	WSTUB(doorfs, door_ki_hold,			nomod_zero);
 	WSTUB(doorfs, door_ki_rele,			nomod_zero);
 	WSTUB(doorfs, door_ki_info,			nomod_einval);
--- a/usr/src/uts/sparc/ml/modstubs.s	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/sparc/ml/modstubs.s	Tue Jul 01 17:10:40 2008 -0700
@@ -815,7 +815,7 @@
 	NO_UNLOAD_STUB(doorfs, door_ki_open,		nomod_einval);
 	NO_UNLOAD_STUB(doorfs, door_ki_lookup,		nomod_zero);
 	WSTUB(doorfs, door_ki_upcall,			nomod_einval);
-	WSTUB(doorfs, door_ki_upcall_cred,		nomod_einval);
+	WSTUB(doorfs, door_ki_upcall_limited,		nomod_einval);
 	WSTUB(doorfs, door_ki_hold,			nomod_zero);
 	WSTUB(doorfs, door_ki_rele,			nomod_zero);
 	WSTUB(doorfs, door_ki_info,			nomod_einval);
--- a/usr/src/uts/sun4v/io/drctl_impl.c	Tue Jul 01 13:41:32 2008 -0700
+++ b/usr/src/uts/sun4v/io/drctl_impl.c	Tue Jul 01 17:10:40 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -98,7 +98,7 @@
 	DR_DBG_CTL("%s: msg %p size %ld obufp %p osize %p\n",
 	    me, msg, size, (void *)obufp, (void *)osize);
 
-	up_err = door_ki_upcall(dh, &door_args);
+	up_err = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
 	if (up_err == 0) {
 		if (door_args.rbuf == NULL)
 			goto done;