xref: /illumos-gate/usr/src/uts/common/fs/doorfs/door_sys.c (revision 61dfa5098dc8576d9a5e277deba6df647bb70c06)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2016 by Delphix. All rights reserved.
25  */
26 
27 /*
28  * System call I/F to doors (outside of vnodes I/F) and misc support
29  * routines
30  */
31 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/door.h>
34 #include <sys/door_data.h>
35 #include <sys/proc.h>
36 #include <sys/thread.h>
37 #include <sys/prsystm.h>
38 #include <sys/procfs.h>
39 #include <sys/class.h>
40 #include <sys/cred.h>
41 #include <sys/kmem.h>
42 #include <sys/cmn_err.h>
43 #include <sys/stack.h>
44 #include <sys/debug.h>
45 #include <sys/cpuvar.h>
46 #include <sys/file.h>
47 #include <sys/fcntl.h>
48 #include <sys/vnode.h>
49 #include <sys/vfs.h>
50 #include <sys/vfs_opreg.h>
51 #include <sys/sobject.h>
52 #include <sys/schedctl.h>
53 #include <sys/callb.h>
54 #include <sys/ucred.h>
55 
56 #include <sys/mman.h>
57 #include <sys/sysmacros.h>
58 #include <sys/vmsystm.h>
59 #include <vm/as.h>
60 #include <vm/hat.h>
61 #include <vm/page.h>
62 #include <vm/seg.h>
63 #include <vm/seg_vn.h>
64 #include <vm/seg_vn.h>
65 #include <vm/seg_kpm.h>
66 
67 #include <sys/modctl.h>
68 #include <sys/syscall.h>
69 #include <sys/pathname.h>
70 #include <sys/rctl.h>
71 
72 /*
73  * The maximum amount of data (in bytes) that will be transferred using
74  * an intermediate kernel buffer.  For sizes greater than this we map
75  * in the destination pages and perform a 1-copy transfer.
76  */
77 size_t	door_max_arg = 16 * 1024;
78 
79 /*
80  * Maximum amount of data that will be transferred in a reply to a
81  * door_upcall.  Need to guard against a process returning huge amounts
82  * of data and getting the kernel stuck in kmem_alloc.
83  */
84 size_t	door_max_upcall_reply = 4 * 1024 * 1024;
85 
86 /*
87  * Maximum number of descriptors allowed to be passed in a single
88  * door_call or door_return.  We need to allocate kernel memory
89  * for all of them at once, so we can't let it scale without limit.
90  */
91 uint_t door_max_desc = 1024;
92 
93 /*
94  * Definition of a door handle, used by other kernel subsystems when
95  * calling door functions.  This is really a file structure but we
96  * want to hide that fact.
97  */
98 struct __door_handle {
99 	file_t dh_file;
100 };
101 
102 #define	DHTOF(dh) ((file_t *)(dh))
103 #define	FTODH(fp) ((door_handle_t)(fp))
104 
105 static int doorfs(long, long, long, long, long, long);
106 
107 static struct sysent door_sysent = {
108 	6,
109 	SE_ARGC | SE_NOUNLOAD,
110 	(int (*)())doorfs,
111 };
112 
113 static struct modlsys modlsys = {
114 	&mod_syscallops, "doors", &door_sysent
115 };
116 
117 #ifdef _SYSCALL32_IMPL
118 
119 static int
120 doorfs32(int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4,
121     int32_t arg5, int32_t subcode);
122 
123 static struct sysent door_sysent32 = {
124 	6,
125 	SE_ARGC | SE_NOUNLOAD,
126 	(int (*)())doorfs32,
127 };
128 
129 static struct modlsys modlsys32 = {
130 	&mod_syscallops32,
131 	"32-bit door syscalls",
132 	&door_sysent32
133 };
134 #endif
135 
136 static struct modlinkage modlinkage = {
137 	MODREV_1,
138 	&modlsys,
139 #ifdef _SYSCALL32_IMPL
140 	&modlsys32,
141 #endif
142 	NULL
143 };
144 
145 dev_t	doordev;
146 
147 extern	struct vfs door_vfs;
148 extern	struct vnodeops *door_vnodeops;
149 
150 int
151 _init(void)
152 {
153 	static const fs_operation_def_t door_vfsops_template[] = {
154 		NULL, NULL
155 	};
156 	extern const fs_operation_def_t door_vnodeops_template[];
157 	vfsops_t *door_vfsops;
158 	major_t major;
159 	int error;
160 
161 	mutex_init(&door_knob, NULL, MUTEX_DEFAULT, NULL);
162 	if ((major = getudev()) == (major_t)-1)
163 		return (ENXIO);
164 	doordev = makedevice(major, 0);
165 
166 	/* Create a dummy vfs */
167 	error = vfs_makefsops(door_vfsops_template, &door_vfsops);
168 	if (error != 0) {
169 		cmn_err(CE_WARN, "door init: bad vfs ops");
170 		return (error);
171 	}
172 	VFS_INIT(&door_vfs, door_vfsops, NULL);
173 	door_vfs.vfs_flag = VFS_RDONLY;
174 	door_vfs.vfs_dev = doordev;
175 	vfs_make_fsid(&(door_vfs.vfs_fsid), doordev, 0);
176 
177 	error = vn_make_ops("doorfs", door_vnodeops_template, &door_vnodeops);
178 	if (error != 0) {
179 		vfs_freevfsops(door_vfsops);
180 		cmn_err(CE_WARN, "door init: bad vnode ops");
181 		return (error);
182 	}
183 	return (mod_install(&modlinkage));
184 }
185 
186 int
187 _info(struct modinfo *modinfop)
188 {
189 	return (mod_info(&modlinkage, modinfop));
190 }
191 
192 /* system call functions */
193 static int door_call(int, void *);
194 static int door_return(caddr_t, size_t, door_desc_t *, uint_t, caddr_t, size_t);
195 static int door_create(void (*pc_cookie)(void *, char *, size_t, door_desc_t *,
196     uint_t), void *data_cookie, uint_t);
197 static int door_revoke(int);
198 static int door_info(int, struct door_info *);
199 static int door_ucred(struct ucred_s *);
200 static int door_bind(int);
201 static int door_unbind(void);
202 static int door_unref(void);
203 static int door_getparam(int, int, size_t *);
204 static int door_setparam(int, int, size_t);
205 
206 #define	DOOR_RETURN_OLD	4		/* historic value, for s10 */
207 
208 /*
209  * System call wrapper for all door related system calls
210  */
211 static int
212 doorfs(long arg1, long arg2, long arg3, long arg4, long arg5, long subcode)
213 {
214 	switch (subcode) {
215 	case DOOR_CALL:
216 		return (door_call(arg1, (void *)arg2));
217 	case DOOR_RETURN: {
218 		door_return_desc_t *drdp = (door_return_desc_t *)arg3;
219 
220 		if (drdp != NULL) {
221 			door_return_desc_t drd;
222 			if (copyin(drdp, &drd, sizeof (drd)))
223 				return (EFAULT);
224 			return (door_return((caddr_t)arg1, arg2, drd.desc_ptr,
225 			    drd.desc_num, (caddr_t)arg4, arg5));
226 		}
227 		return (door_return((caddr_t)arg1, arg2, NULL,
228 		    0, (caddr_t)arg4, arg5));
229 	}
230 	case DOOR_RETURN_OLD:
231 		/*
232 		 * In order to support the S10 runtime environment, we
233 		 * still respond to the old syscall subcode for door_return.
234 		 * We treat it as having no stack limits.  This code should
235 		 * be removed when such support is no longer needed.
236 		 */
237 		return (door_return((caddr_t)arg1, arg2, (door_desc_t *)arg3,
238 		    arg4, (caddr_t)arg5, 0));
239 	case DOOR_CREATE:
240 		return (door_create((void (*)())arg1, (void *)arg2, arg3));
241 	case DOOR_REVOKE:
242 		return (door_revoke(arg1));
243 	case DOOR_INFO:
244 		return (door_info(arg1, (struct door_info *)arg2));
245 	case DOOR_BIND:
246 		return (door_bind(arg1));
247 	case DOOR_UNBIND:
248 		return (door_unbind());
249 	case DOOR_UNREFSYS:
250 		return (door_unref());
251 	case DOOR_UCRED:
252 		return (door_ucred((struct ucred_s *)arg1));
253 	case DOOR_GETPARAM:
254 		return (door_getparam(arg1, arg2, (size_t *)arg3));
255 	case DOOR_SETPARAM:
256 		return (door_setparam(arg1, arg2, arg3));
257 	default:
258 		return (set_errno(EINVAL));
259 	}
260 }
261 
262 #ifdef _SYSCALL32_IMPL
263 /*
264  * System call wrapper for all door related system calls from 32-bit programs.
265  * Needed at the moment because of the casts - they undo some damage
266  * that truss causes (sign-extending the stack pointer) when truss'ing
267  * a 32-bit program using doors.
268  */
269 static int
270 doorfs32(int32_t arg1, int32_t arg2, int32_t arg3,
271     int32_t arg4, int32_t arg5, int32_t subcode)
272 {
273 	switch (subcode) {
274 	case DOOR_CALL:
275 		return (door_call(arg1, (void *)(uintptr_t)(caddr32_t)arg2));
276 	case DOOR_RETURN: {
277 		door_return_desc32_t *drdp =
278 		    (door_return_desc32_t *)(uintptr_t)(caddr32_t)arg3;
279 		if (drdp != NULL) {
280 			door_return_desc32_t drd;
281 			if (copyin(drdp, &drd, sizeof (drd)))
282 				return (EFAULT);
283 			return (door_return(
284 			    (caddr_t)(uintptr_t)(caddr32_t)arg1, arg2,
285 			    (door_desc_t *)(uintptr_t)drd.desc_ptr,
286 			    drd.desc_num, (caddr_t)(uintptr_t)(caddr32_t)arg4,
287 			    (size_t)(uintptr_t)(size32_t)arg5));
288 		}
289 		return (door_return((caddr_t)(uintptr_t)(caddr32_t)arg1,
290 		    arg2, NULL, 0, (caddr_t)(uintptr_t)(caddr32_t)arg4,
291 		    (size_t)(uintptr_t)(size32_t)arg5));
292 	}
293 	case DOOR_RETURN_OLD:
294 		/*
295 		 * In order to support the S10 runtime environment, we
296 		 * still respond to the old syscall subcode for door_return.
297 		 * We treat it as having no stack limits.  This code should
298 		 * be removed when such support is no longer needed.
299 		 */
300 		return (door_return((caddr_t)(uintptr_t)(caddr32_t)arg1, arg2,
301 		    (door_desc_t *)(uintptr_t)(caddr32_t)arg3, arg4,
302 		    (caddr_t)(uintptr_t)(caddr32_t)arg5, 0));
303 	case DOOR_CREATE:
304 		return (door_create((void (*)())(uintptr_t)(caddr32_t)arg1,
305 		    (void *)(uintptr_t)(caddr32_t)arg2, arg3));
306 	case DOOR_REVOKE:
307 		return (door_revoke(arg1));
308 	case DOOR_INFO:
309 		return (door_info(arg1,
310 		    (struct door_info *)(uintptr_t)(caddr32_t)arg2));
311 	case DOOR_BIND:
312 		return (door_bind(arg1));
313 	case DOOR_UNBIND:
314 		return (door_unbind());
315 	case DOOR_UNREFSYS:
316 		return (door_unref());
317 	case DOOR_UCRED:
318 		return (door_ucred(
319 		    (struct ucred_s *)(uintptr_t)(caddr32_t)arg1));
320 	case DOOR_GETPARAM:
321 		return (door_getparam(arg1, arg2,
322 		    (size_t *)(uintptr_t)(caddr32_t)arg3));
323 	case DOOR_SETPARAM:
324 		return (door_setparam(arg1, arg2, (size_t)(size32_t)arg3));
325 
326 	default:
327 		return (set_errno(EINVAL));
328 	}
329 }
330 #endif
331 
332 void shuttle_resume(kthread_t *, kmutex_t *);
333 void shuttle_swtch(kmutex_t *);
334 void shuttle_sleep(kthread_t *);
335 
336 /*
337  * Support routines
338  */
339 static int door_create_common(void (*)(), void *, uint_t, int, int *,
340     file_t **);
341 static int door_overflow(kthread_t *, caddr_t, size_t, door_desc_t *, uint_t);
342 static int door_args(kthread_t *, int);
343 static int door_results(kthread_t *, caddr_t, size_t, door_desc_t *, uint_t);
344 static int door_copy(struct as *, caddr_t, caddr_t, uint_t);
345 static void	door_server_exit(proc_t *, kthread_t *);
346 static void	door_release_server(door_node_t *, kthread_t *);
347 static kthread_t	*door_get_server(door_node_t *);
348 static door_node_t	*door_lookup(int, file_t **);
349 static int	door_translate_in(void);
350 static int	door_translate_out(void);
351 static void	door_fd_rele(door_desc_t *, uint_t, int);
352 static void	door_list_insert(door_node_t *);
353 static void	door_info_common(door_node_t *, door_info_t *, file_t *);
354 static int	door_release_fds(door_desc_t *, uint_t);
355 static void	door_fd_close(door_desc_t *, uint_t);
356 static void	door_fp_close(struct file **, uint_t);
357 
358 static door_data_t *
359 door_my_data(int create_if_missing)
360 {
361 	door_data_t *ddp;
362 
363 	ddp = curthread->t_door;
364 	if (create_if_missing && ddp == NULL)
365 		ddp = curthread->t_door = kmem_zalloc(sizeof (*ddp), KM_SLEEP);
366 
367 	return (ddp);
368 }
369 
370 static door_server_t *
371 door_my_server(int create_if_missing)
372 {
373 	door_data_t *ddp = door_my_data(create_if_missing);
374 
375 	return ((ddp != NULL)? DOOR_SERVER(ddp) : NULL);
376 }
377 
378 static door_client_t *
379 door_my_client(int create_if_missing)
380 {
381 	door_data_t *ddp = door_my_data(create_if_missing);
382 
383 	return ((ddp != NULL)? DOOR_CLIENT(ddp) : NULL);
384 }
385 
386 /*
387  * System call to create a door
388  */
389 int
390 door_create(void (*pc_cookie)(), void *data_cookie, uint_t attributes)
391 {
392 	int fd;
393 	int err;
394 
395 	if ((attributes & ~DOOR_CREATE_MASK) ||
396 	    ((attributes & (DOOR_UNREF | DOOR_UNREF_MULTI)) ==
397 	    (DOOR_UNREF | DOOR_UNREF_MULTI)))
398 		return (set_errno(EINVAL));
399 
400 	if ((err = door_create_common(pc_cookie, data_cookie, attributes, 0,
401 	    &fd, NULL)) != 0)
402 		return (set_errno(err));
403 
404 	f_setfd(fd, FD_CLOEXEC);
405 	return (fd);
406 }
407 
408 /*
409  * Common code for creating user and kernel doors.  If a door was
410  * created, stores a file structure pointer in the location pointed
411  * to by fpp (if fpp is non-NULL) and returns 0.  Also, if a non-NULL
412  * pointer to a file descriptor is passed in as fdp, allocates a file
413  * descriptor representing the door.  If a door could not be created,
414  * returns an error.
415  */
416 static int
417 door_create_common(void (*pc_cookie)(), void *data_cookie, uint_t attributes,
418     int from_kernel, int *fdp, file_t **fpp)
419 {
420 	door_node_t	*dp;
421 	vnode_t		*vp;
422 	struct file	*fp;
423 	static door_id_t index = 0;
424 	proc_t		*p = (from_kernel)? &p0 : curproc;
425 
426 	dp = kmem_zalloc(sizeof (door_node_t), KM_SLEEP);
427 
428 	dp->door_vnode = vn_alloc(KM_SLEEP);
429 	dp->door_target = p;
430 	dp->door_data = data_cookie;
431 	dp->door_pc = pc_cookie;
432 	dp->door_flags = attributes;
433 #ifdef _SYSCALL32_IMPL
434 	if (!from_kernel && get_udatamodel() != DATAMODEL_NATIVE)
435 		dp->door_data_max = UINT32_MAX;
436 	else
437 #endif
438 		dp->door_data_max = SIZE_MAX;
439 	dp->door_data_min = 0UL;
440 	dp->door_desc_max = (attributes & DOOR_REFUSE_DESC)? 0 : INT_MAX;
441 
442 	vp = DTOV(dp);
443 	vn_setops(vp, door_vnodeops);
444 	vp->v_type = VDOOR;
445 	vp->v_vfsp = &door_vfs;
446 	vp->v_data = (caddr_t)dp;
447 	mutex_enter(&door_knob);
448 	dp->door_index = index++;
449 	/* add to per-process door list */
450 	door_list_insert(dp);
451 	mutex_exit(&door_knob);
452 
453 	if (falloc(vp, FREAD | FWRITE, &fp, fdp)) {
454 		/*
455 		 * If the file table is full, remove the door from the
456 		 * per-process list, free the door, and return NULL.
457 		 */
458 		mutex_enter(&door_knob);
459 		door_list_delete(dp);
460 		mutex_exit(&door_knob);
461 		vn_free(vp);
462 		kmem_free(dp, sizeof (door_node_t));
463 		return (EMFILE);
464 	}
465 	vn_exists(vp);
466 	if (fdp != NULL)
467 		setf(*fdp, fp);
468 	mutex_exit(&fp->f_tlock);
469 
470 	if (fpp != NULL)
471 		*fpp = fp;
472 	return (0);
473 }
474 
475 static int
476 door_check_limits(door_node_t *dp, door_arg_t *da, int upcall)
477 {
478 	ASSERT(MUTEX_HELD(&door_knob));
479 
480 	/* we allow unref upcalls through, despite any minimum */
481 	if (da->data_size < dp->door_data_min &&
482 	    !(upcall && da->data_ptr == DOOR_UNREF_DATA))
483 		return (ENOBUFS);
484 
485 	if (da->data_size > dp->door_data_max)
486 		return (ENOBUFS);
487 
488 	if (da->desc_num > 0 && (dp->door_flags & DOOR_REFUSE_DESC))
489 		return (ENOTSUP);
490 
491 	if (da->desc_num > dp->door_desc_max)
492 		return (ENFILE);
493 
494 	return (0);
495 }
496 
497 /*
498  * Door invocation.
499  */
500 int
501 door_call(int did, void *args)
502 {
503 	/* Locals */
504 	door_node_t	*dp;
505 	kthread_t	*server_thread;
506 	int		error = 0;
507 	klwp_t		*lwp;
508 	door_client_t	*ct;		/* curthread door_data */
509 	door_server_t	*st;		/* server thread door_data */
510 	door_desc_t	*start = NULL;
511 	uint_t		ncopied = 0;
512 	size_t		dsize;
513 	/* destructor for data returned by a kernel server */
514 	void		(*destfn)() = NULL;
515 	void		*destarg;
516 	model_t		datamodel;
517 	int		gotresults = 0;
518 	int		needcleanup = 0;
519 	int		cancel_pending;
520 
521 	lwp = ttolwp(curthread);
522 	datamodel = lwp_getdatamodel(lwp);
523 
524 	ct = door_my_client(1);
525 
526 	/*
527 	 * Get the arguments
528 	 */
529 	if (args) {
530 		if (datamodel == DATAMODEL_NATIVE) {
531 			if (copyin(args, &ct->d_args, sizeof (door_arg_t)) != 0)
532 				return (set_errno(EFAULT));
533 		} else {
534 			door_arg32_t    da32;
535 
536 			if (copyin(args, &da32, sizeof (door_arg32_t)) != 0)
537 				return (set_errno(EFAULT));
538 			ct->d_args.data_ptr =
539 			    (char *)(uintptr_t)da32.data_ptr;
540 			ct->d_args.data_size = da32.data_size;
541 			ct->d_args.desc_ptr =
542 			    (door_desc_t *)(uintptr_t)da32.desc_ptr;
543 			ct->d_args.desc_num = da32.desc_num;
544 			ct->d_args.rbuf =
545 			    (char *)(uintptr_t)da32.rbuf;
546 			ct->d_args.rsize = da32.rsize;
547 		}
548 	} else {
549 		/* No arguments, and no results allowed */
550 		ct->d_noresults = 1;
551 		ct->d_args.data_size = 0;
552 		ct->d_args.desc_num = 0;
553 		ct->d_args.rsize = 0;
554 	}
555 
556 	if ((dp = door_lookup(did, NULL)) == NULL)
557 		return (set_errno(EBADF));
558 
559 	/*
560 	 * We don't want to hold the door FD over the entire operation;
561 	 * instead, we put a hold on the door vnode and release the FD
562 	 * immediately
563 	 */
564 	VN_HOLD(DTOV(dp));
565 	releasef(did);
566 
567 	/*
568 	 * This should be done in shuttle_resume(), just before going to
569 	 * sleep, but we want to avoid overhead while holding door_knob.
570 	 * prstop() is just a no-op if we don't really go to sleep.
571 	 * We test not-kernel-address-space for the sake of clustering code.
572 	 */
573 	if (lwp && lwp->lwp_nostop == 0 && curproc->p_as != &kas)
574 		prstop(PR_REQUESTED, 0);
575 
576 	mutex_enter(&door_knob);
577 	if (DOOR_INVALID(dp)) {
578 		mutex_exit(&door_knob);
579 		error = EBADF;
580 		goto out;
581 	}
582 
583 	/*
584 	 * before we do anything, check that we are not overflowing the
585 	 * required limits.
586 	 */
587 	error = door_check_limits(dp, &ct->d_args, 0);
588 	if (error != 0) {
589 		mutex_exit(&door_knob);
590 		goto out;
591 	}
592 
593 	/*
594 	 * Check for in-kernel door server.
595 	 */
596 	if (dp->door_target == &p0) {
597 		caddr_t rbuf = ct->d_args.rbuf;
598 		size_t rsize = ct->d_args.rsize;
599 
600 		dp->door_active++;
601 		ct->d_kernel = 1;
602 		ct->d_error = DOOR_WAIT;
603 		mutex_exit(&door_knob);
604 		/* translate file descriptors to vnodes */
605 		if (ct->d_args.desc_num) {
606 			error = door_translate_in();
607 			if (error)
608 				goto out;
609 		}
610 		/*
611 		 * Call kernel door server.  Arguments are passed and
612 		 * returned as a door_arg pointer.  When called, data_ptr
613 		 * points to user data and desc_ptr points to a kernel list
614 		 * of door descriptors that have been converted to file
615 		 * structure pointers.  It's the server function's
616 		 * responsibility to copyin the data pointed to by data_ptr
617 		 * (this avoids extra copying in some cases).  On return,
618 		 * data_ptr points to a user buffer of data, and desc_ptr
619 		 * points to a kernel list of door descriptors representing
620 		 * files.  When a reference is passed to a kernel server,
621 		 * it is the server's responsibility to release the reference
622 		 * (by calling closef).  When the server includes a
623 		 * reference in its reply, it is released as part of the
624 		 * the call (the server must duplicate the reference if
625 		 * it wants to retain a copy).  The destfn, if set to
626 		 * non-NULL, is a destructor to be called when the returned
627 		 * kernel data (if any) is no longer needed (has all been
628 		 * translated and copied to user level).
629 		 */
630 		(*(dp->door_pc))(dp->door_data, &ct->d_args,
631 		    &destfn, &destarg, &error);
632 		mutex_enter(&door_knob);
633 		/* not implemented yet */
634 		if (--dp->door_active == 0 && (dp->door_flags & DOOR_DELAY))
635 			door_deliver_unref(dp);
636 		mutex_exit(&door_knob);
637 		if (error)
638 			goto out;
639 
640 		/* translate vnodes to files */
641 		if (ct->d_args.desc_num) {
642 			error = door_translate_out();
643 			if (error)
644 				goto out;
645 		}
646 		ct->d_buf = ct->d_args.rbuf;
647 		ct->d_bufsize = ct->d_args.rsize;
648 		if (rsize < (ct->d_args.data_size +
649 		    (ct->d_args.desc_num * sizeof (door_desc_t)))) {
650 			/* handle overflow */
651 			error = door_overflow(curthread, ct->d_args.data_ptr,
652 			    ct->d_args.data_size, ct->d_args.desc_ptr,
653 			    ct->d_args.desc_num);
654 			if (error)
655 				goto out;
656 			/* door_overflow sets d_args rbuf and rsize */
657 		} else {
658 			ct->d_args.rbuf = rbuf;
659 			ct->d_args.rsize = rsize;
660 		}
661 		goto results;
662 	}
663 
664 	/*
665 	 * Get a server thread from the target domain
666 	 */
667 	if ((server_thread = door_get_server(dp)) == NULL) {
668 		if (DOOR_INVALID(dp))
669 			error = EBADF;
670 		else
671 			error = EAGAIN;
672 		mutex_exit(&door_knob);
673 		goto out;
674 	}
675 
676 	st = DOOR_SERVER(server_thread->t_door);
677 	if (ct->d_args.desc_num || ct->d_args.data_size) {
678 		int is_private = (dp->door_flags & DOOR_PRIVATE);
679 		/*
680 		 * Move data from client to server
681 		 */
682 		DOOR_T_HOLD(st);
683 		mutex_exit(&door_knob);
684 		error = door_args(server_thread, is_private);
685 		mutex_enter(&door_knob);
686 		DOOR_T_RELEASE(st);
687 		if (error) {
688 			/*
689 			 * We're not going to resume this thread after all
690 			 */
691 			door_release_server(dp, server_thread);
692 			shuttle_sleep(server_thread);
693 			mutex_exit(&door_knob);
694 			goto out;
695 		}
696 	}
697 
698 	dp->door_active++;
699 	ct->d_error = DOOR_WAIT;
700 	ct->d_args_done = 0;
701 	st->d_caller = curthread;
702 	st->d_active = dp;
703 
704 	shuttle_resume(server_thread, &door_knob);
705 
706 	mutex_enter(&door_knob);
707 shuttle_return:
708 	if ((error = ct->d_error) < 0) {	/* DOOR_WAIT or DOOR_EXIT */
709 		/*
710 		 * Premature wakeup. Find out why (stop, forkall, sig, exit ...)
711 		 */
712 		mutex_exit(&door_knob);		/* May block in ISSIG */
713 		cancel_pending = 0;
714 		if (ISSIG(curthread, FORREAL) || lwp->lwp_sysabort ||
715 		    MUSTRETURN(curproc, curthread) ||
716 		    (cancel_pending = schedctl_cancel_pending()) != 0) {
717 			/* Signal, forkall, ... */
718 			lwp->lwp_sysabort = 0;
719 			if (cancel_pending)
720 				schedctl_cancel_eintr();
721 			mutex_enter(&door_knob);
722 			error = EINTR;
723 			/*
724 			 * If the server has finished processing our call,
725 			 * or exited (calling door_slam()), then d_error
726 			 * will have changed.  If the server hasn't finished
727 			 * yet, d_error will still be DOOR_WAIT, and we
728 			 * let it know we are not interested in any
729 			 * results by sending a SIGCANCEL, unless the door
730 			 * is marked with DOOR_NO_CANCEL.
731 			 */
732 			if (ct->d_error == DOOR_WAIT &&
733 			    st->d_caller == curthread) {
734 				proc_t	*p = ttoproc(server_thread);
735 
736 				st->d_active = NULL;
737 				st->d_caller = NULL;
738 
739 				if (!(dp->door_flags & DOOR_NO_CANCEL)) {
740 					DOOR_T_HOLD(st);
741 					mutex_exit(&door_knob);
742 
743 					mutex_enter(&p->p_lock);
744 					sigtoproc(p, server_thread, SIGCANCEL);
745 					mutex_exit(&p->p_lock);
746 
747 					mutex_enter(&door_knob);
748 					DOOR_T_RELEASE(st);
749 				}
750 			}
751 		} else {
752 			/*
753 			 * Return from stop(), server exit...
754 			 *
755 			 * Note that the server could have done a
756 			 * door_return while the client was in stop state
757 			 * (ISSIG), in which case the error condition
758 			 * is updated by the server.
759 			 */
760 			mutex_enter(&door_knob);
761 			if (ct->d_error == DOOR_WAIT) {
762 				/* Still waiting for a reply */
763 				shuttle_swtch(&door_knob);
764 				mutex_enter(&door_knob);
765 				lwp->lwp_asleep = 0;
766 				goto	shuttle_return;
767 			} else if (ct->d_error == DOOR_EXIT) {
768 				/* Server exit */
769 				error = EINTR;
770 			} else {
771 				/* Server did a door_return during ISSIG */
772 				error = ct->d_error;
773 			}
774 		}
775 		/*
776 		 * Can't exit if the server is currently copying
777 		 * results for me.
778 		 */
779 		while (DOOR_T_HELD(ct))
780 			cv_wait(&ct->d_cv, &door_knob);
781 
782 		/*
783 		 * If the server has not processed our message, free the
784 		 * descriptors.
785 		 */
786 		if (!ct->d_args_done) {
787 			needcleanup = 1;
788 			ct->d_args_done = 1;
789 		}
790 
791 		/*
792 		 * Find out if results were successfully copied.
793 		 */
794 		if (ct->d_error == 0)
795 			gotresults = 1;
796 	}
797 	ASSERT(ct->d_args_done);
798 	lwp->lwp_asleep = 0;		/* /proc */
799 	lwp->lwp_sysabort = 0;		/* /proc */
800 	if (--dp->door_active == 0 && (dp->door_flags & DOOR_DELAY))
801 		door_deliver_unref(dp);
802 	mutex_exit(&door_knob);
803 
804 	if (needcleanup)
805 		door_fp_close(ct->d_fpp, ct->d_args.desc_num);
806 
807 results:
808 	/*
809 	 * Move the results to userland (if any)
810 	 */
811 
812 	if (ct->d_noresults)
813 		goto out;
814 
815 	if (error) {
816 		/*
817 		 * If server returned results successfully, then we've
818 		 * been interrupted and may need to clean up.
819 		 */
820 		if (gotresults) {
821 			ASSERT(error == EINTR);
822 			door_fp_close(ct->d_fpp, ct->d_args.desc_num);
823 		}
824 		goto out;
825 	}
826 
827 	/*
828 	 * Copy back data if we haven't caused an overflow (already
829 	 * handled) and we are using a 2 copy transfer, or we are
830 	 * returning data from a kernel server.
831 	 */
832 	if (ct->d_args.data_size) {
833 		ct->d_args.data_ptr = ct->d_args.rbuf;
834 		if (ct->d_kernel || (!ct->d_overflow &&
835 		    ct->d_args.data_size <= door_max_arg)) {
836 			if (copyout_nowatch(ct->d_buf, ct->d_args.rbuf,
837 			    ct->d_args.data_size)) {
838 				door_fp_close(ct->d_fpp, ct->d_args.desc_num);
839 				error = EFAULT;
840 				goto out;
841 			}
842 		}
843 	}
844 
845 	/*
846 	 * stuff returned doors into our proc, copyout the descriptors
847 	 */
848 	if (ct->d_args.desc_num) {
849 		struct file	**fpp;
850 		door_desc_t	*didpp;
851 		uint_t		n = ct->d_args.desc_num;
852 
853 		dsize = n * sizeof (door_desc_t);
854 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
855 		fpp = ct->d_fpp;
856 
857 		while (n--) {
858 			if (door_insert(*fpp, didpp) == -1) {
859 				/* Close remaining files */
860 				door_fp_close(fpp, n + 1);
861 				error = EMFILE;
862 				goto out;
863 			}
864 			fpp++; didpp++; ncopied++;
865 		}
866 
867 		ct->d_args.desc_ptr = (door_desc_t *)(ct->d_args.rbuf +
868 		    roundup(ct->d_args.data_size, sizeof (door_desc_t)));
869 
870 		if (copyout_nowatch(start, ct->d_args.desc_ptr, dsize)) {
871 			error = EFAULT;
872 			goto out;
873 		}
874 	}
875 
876 	/*
877 	 * Return the results
878 	 */
879 	if (datamodel == DATAMODEL_NATIVE) {
880 		if (copyout_nowatch(&ct->d_args, args,
881 		    sizeof (door_arg_t)) != 0)
882 			error = EFAULT;
883 	} else {
884 		door_arg32_t    da32;
885 
886 		da32.data_ptr = (caddr32_t)(uintptr_t)ct->d_args.data_ptr;
887 		da32.data_size = ct->d_args.data_size;
888 		da32.desc_ptr = (caddr32_t)(uintptr_t)ct->d_args.desc_ptr;
889 		da32.desc_num = ct->d_args.desc_num;
890 		da32.rbuf = (caddr32_t)(uintptr_t)ct->d_args.rbuf;
891 		da32.rsize = ct->d_args.rsize;
892 		if (copyout_nowatch(&da32, args, sizeof (door_arg32_t)) != 0) {
893 			error = EFAULT;
894 		}
895 	}
896 
897 out:
898 	ct->d_noresults = 0;
899 
900 	/* clean up the overflow buffer if an error occurred */
901 	if (error != 0 && ct->d_overflow) {
902 		(void) as_unmap(curproc->p_as, ct->d_args.rbuf,
903 		    ct->d_args.rsize);
904 	}
905 	ct->d_overflow = 0;
906 
907 	/* call destructor */
908 	if (destfn) {
909 		ASSERT(ct->d_kernel);
910 		(*destfn)(dp->door_data, destarg);
911 		ct->d_buf = NULL;
912 		ct->d_bufsize = 0;
913 	}
914 
915 	if (dp)
916 		VN_RELE(DTOV(dp));
917 
918 	if (ct->d_buf) {
919 		ASSERT(!ct->d_kernel);
920 		kmem_free(ct->d_buf, ct->d_bufsize);
921 		ct->d_buf = NULL;
922 		ct->d_bufsize = 0;
923 	}
924 	ct->d_kernel = 0;
925 
926 	/* clean up the descriptor copyout buffer */
927 	if (start != NULL) {
928 		if (error != 0)
929 			door_fd_close(start, ncopied);
930 		kmem_free(start, dsize);
931 	}
932 
933 	if (ct->d_fpp) {
934 		kmem_free(ct->d_fpp, ct->d_fpp_size);
935 		ct->d_fpp = NULL;
936 		ct->d_fpp_size = 0;
937 	}
938 
939 	if (error)
940 		return (set_errno(error));
941 
942 	return (0);
943 }
944 
945 static int
946 door_setparam_common(door_node_t *dp, int from_kernel, int type, size_t val)
947 {
948 	int error = 0;
949 
950 	mutex_enter(&door_knob);
951 
952 	if (DOOR_INVALID(dp)) {
953 		mutex_exit(&door_knob);
954 		return (EBADF);
955 	}
956 
957 	/*
958 	 * door_ki_setparam() can only affect kernel doors.
959 	 * door_setparam() can only affect doors attached to the current
960 	 * process.
961 	 */
962 	if ((from_kernel && dp->door_target != &p0) ||
963 	    (!from_kernel && dp->door_target != curproc)) {
964 		mutex_exit(&door_knob);
965 		return (EPERM);
966 	}
967 
968 	switch (type) {
969 	case DOOR_PARAM_DESC_MAX:
970 		if (val > INT_MAX)
971 			error = ERANGE;
972 		else if ((dp->door_flags & DOOR_REFUSE_DESC) && val != 0)
973 			error = ENOTSUP;
974 		else
975 			dp->door_desc_max = (uint_t)val;
976 		break;
977 
978 	case DOOR_PARAM_DATA_MIN:
979 		if (val > dp->door_data_max)
980 			error = EINVAL;
981 		else
982 			dp->door_data_min = val;
983 		break;
984 
985 	case DOOR_PARAM_DATA_MAX:
986 		if (val < dp->door_data_min)
987 			error = EINVAL;
988 		else
989 			dp->door_data_max = val;
990 		break;
991 
992 	default:
993 		error = EINVAL;
994 		break;
995 	}
996 
997 	mutex_exit(&door_knob);
998 	return (error);
999 }
1000 
1001 static int
1002 door_getparam_common(door_node_t *dp, int type, size_t *out)
1003 {
1004 	int error = 0;
1005 
1006 	mutex_enter(&door_knob);
1007 	switch (type) {
1008 	case DOOR_PARAM_DESC_MAX:
1009 		*out = (size_t)dp->door_desc_max;
1010 		break;
1011 	case DOOR_PARAM_DATA_MIN:
1012 		*out = dp->door_data_min;
1013 		break;
1014 	case DOOR_PARAM_DATA_MAX:
1015 		*out = dp->door_data_max;
1016 		break;
1017 	default:
1018 		error = EINVAL;
1019 		break;
1020 	}
1021 	mutex_exit(&door_knob);
1022 	return (error);
1023 }
1024 
1025 int
1026 door_setparam(int did, int type, size_t val)
1027 {
1028 	door_node_t *dp;
1029 	int error = 0;
1030 
1031 	if ((dp = door_lookup(did, NULL)) == NULL)
1032 		return (set_errno(EBADF));
1033 
1034 	error = door_setparam_common(dp, 0, type, val);
1035 
1036 	releasef(did);
1037 
1038 	if (error)
1039 		return (set_errno(error));
1040 
1041 	return (0);
1042 }
1043 
1044 int
1045 door_getparam(int did, int type, size_t *out)
1046 {
1047 	door_node_t *dp;
1048 	size_t val = 0;
1049 	int error = 0;
1050 
1051 	if ((dp = door_lookup(did, NULL)) == NULL)
1052 		return (set_errno(EBADF));
1053 
1054 	error = door_getparam_common(dp, type, &val);
1055 
1056 	releasef(did);
1057 
1058 	if (error)
1059 		return (set_errno(error));
1060 
1061 	if (get_udatamodel() == DATAMODEL_NATIVE) {
1062 		if (copyout(&val, out, sizeof (val)))
1063 			return (set_errno(EFAULT));
1064 #ifdef _SYSCALL32_IMPL
1065 	} else {
1066 		size32_t val32 = (size32_t)val;
1067 
1068 		if (val != val32)
1069 			return (set_errno(EOVERFLOW));
1070 
1071 		if (copyout(&val32, out, sizeof (val32)))
1072 			return (set_errno(EFAULT));
1073 #endif /* _SYSCALL32_IMPL */
1074 	}
1075 
1076 	return (0);
1077 }
1078 
1079 /*
1080  * A copyout() which proceeds from high addresses to low addresses.  This way,
1081  * stack guard pages are effective.
1082  *
1083  * Note that we use copyout_nowatch();  this is called while the client is
1084  * held.
1085  */
1086 static int
1087 door_stack_copyout(const void *kaddr, void *uaddr, size_t count)
1088 {
1089 	const char *kbase = (const char *)kaddr;
1090 	uintptr_t ubase = (uintptr_t)uaddr;
1091 	size_t pgsize = PAGESIZE;
1092 
1093 	if (count <= pgsize)
1094 		return (copyout_nowatch(kaddr, uaddr, count));
1095 
1096 	while (count > 0) {
1097 		uintptr_t start, end, offset, amount;
1098 
1099 		end = ubase + count;
1100 		start = P2ALIGN(end - 1, pgsize);
1101 		if (P2ALIGN(ubase, pgsize) == start)
1102 			start = ubase;
1103 
1104 		offset = start - ubase;
1105 		amount = end - start;
1106 
1107 		ASSERT(amount > 0 && amount <= count && amount <= pgsize);
1108 
1109 		if (copyout_nowatch(kbase + offset, (void *)start, amount))
1110 			return (1);
1111 		count -= amount;
1112 	}
1113 	return (0);
1114 }
1115 
1116 /*
1117  * Writes the stack layout for door_return() into the door_server_t of the
1118  * server thread.
1119  */
1120 static int
1121 door_layout(kthread_t *tp, size_t data_size, uint_t ndesc, int info_needed)
1122 {
1123 	door_server_t *st = DOOR_SERVER(tp->t_door);
1124 	door_layout_t *out = &st->d_layout;
1125 	uintptr_t base_sp = (uintptr_t)st->d_sp;
1126 	size_t ssize = st->d_ssize;
1127 	size_t descsz;
1128 	uintptr_t descp, datap, infop, resultsp, finalsp;
1129 	size_t align = STACK_ALIGN;
1130 	size_t results_sz = sizeof (struct door_results);
1131 	model_t datamodel = lwp_getdatamodel(ttolwp(tp));
1132 
1133 	ASSERT(!st->d_layout_done);
1134 
1135 #ifndef _STACK_GROWS_DOWNWARD
1136 #error stack does not grow downward, door_layout() must change
1137 #endif
1138 
1139 #ifdef _SYSCALL32_IMPL
1140 	if (datamodel != DATAMODEL_NATIVE) {
1141 		align = STACK_ALIGN32;
1142 		results_sz = sizeof (struct door_results32);
1143 	}
1144 #endif
1145 
1146 	descsz = ndesc * sizeof (door_desc_t);
1147 
1148 	/*
1149 	 * To speed up the overflow checking, we do an initial check
1150 	 * that the passed in data size won't cause us to wrap past
1151 	 * base_sp.  Since door_max_desc limits descsz, we can
1152 	 * safely use it here.  65535 is an arbitrary 'bigger than
1153 	 * we need, small enough to not cause trouble' constant;
1154 	 * the only constraint is that it must be > than:
1155 	 *
1156 	 *	5 * STACK_ALIGN +
1157 	 *	    sizeof (door_info_t) +
1158 	 *	    sizeof (door_results_t) +
1159 	 *	    (max adjustment from door_final_sp())
1160 	 *
1161 	 * After we compute the layout, we can safely do a "did we wrap
1162 	 * around" check, followed by a check against the recorded
1163 	 * stack size.
1164 	 */
1165 	if (data_size >= SIZE_MAX - (size_t)65535UL - descsz)
1166 		return (E2BIG);		/* overflow */
1167 
1168 	descp = P2ALIGN(base_sp - descsz, align);
1169 	datap = P2ALIGN(descp - data_size, align);
1170 
1171 	if (info_needed)
1172 		infop = P2ALIGN(datap - sizeof (door_info_t), align);
1173 	else
1174 		infop = datap;
1175 
1176 	resultsp = P2ALIGN(infop - results_sz, align);
1177 	finalsp = door_final_sp(resultsp, align, datamodel);
1178 
1179 	if (finalsp > base_sp)
1180 		return (E2BIG);		/* overflow */
1181 
1182 	if (ssize != 0 && (base_sp - finalsp) > ssize)
1183 		return (E2BIG);		/* doesn't fit in stack */
1184 
1185 	out->dl_descp = (ndesc != 0)? (caddr_t)descp : 0;
1186 	out->dl_datap = (data_size != 0)? (caddr_t)datap : 0;
1187 	out->dl_infop = info_needed? (caddr_t)infop : 0;
1188 	out->dl_resultsp = (caddr_t)resultsp;
1189 	out->dl_sp = (caddr_t)finalsp;
1190 
1191 	st->d_layout_done = 1;
1192 	return (0);
1193 }
1194 
1195 static int
1196 door_server_dispatch(door_client_t *ct, door_node_t *dp)
1197 {
1198 	door_server_t *st = DOOR_SERVER(curthread->t_door);
1199 	door_layout_t *layout = &st->d_layout;
1200 	int error = 0;
1201 
1202 	int is_private = (dp->door_flags & DOOR_PRIVATE);
1203 
1204 	door_pool_t *pool = (is_private)? &dp->door_servers :
1205 	    &curproc->p_server_threads;
1206 
1207 	int empty_pool = (pool->dp_threads == NULL);
1208 
1209 	caddr_t infop = NULL;
1210 	char *datap = NULL;
1211 	size_t datasize = 0;
1212 	size_t descsize;
1213 
1214 	file_t **fpp = ct->d_fpp;
1215 	door_desc_t *start = NULL;
1216 	uint_t ndesc = 0;
1217 	uint_t ncopied = 0;
1218 
1219 	if (ct != NULL) {
1220 		datap = ct->d_args.data_ptr;
1221 		datasize = ct->d_args.data_size;
1222 		ndesc = ct->d_args.desc_num;
1223 	}
1224 
1225 	descsize = ndesc * sizeof (door_desc_t);
1226 
1227 	/*
1228 	 * Reset datap to NULL if we aren't passing any data.  Be careful
1229 	 * to let unref notifications through, though.
1230 	 */
1231 	if (datap == DOOR_UNREF_DATA) {
1232 		if (ct->d_upcall != NULL)
1233 			datasize = 0;
1234 		else
1235 			datap = NULL;
1236 	} else if (datasize == 0) {
1237 		datap = NULL;
1238 	}
1239 
1240 	/*
1241 	 * Get the stack layout, if it hasn't already been done.
1242 	 */
1243 	if (!st->d_layout_done) {
1244 		error = door_layout(curthread, datasize, ndesc,
1245 		    (is_private && empty_pool));
1246 		if (error != 0)
1247 			goto fail;
1248 	}
1249 
1250 	/*
1251 	 * fill out the stack, starting from the top.  Layout was already
1252 	 * filled in by door_args() or door_translate_out().
1253 	 */
1254 	if (layout->dl_descp != NULL) {
1255 		ASSERT(ndesc != 0);
1256 		start = kmem_alloc(descsize, KM_SLEEP);
1257 
1258 		while (ndesc > 0) {
1259 			if (door_insert(*fpp, &start[ncopied]) == -1) {
1260 				error = EMFILE;
1261 				goto fail;
1262 			}
1263 			ndesc--;
1264 			ncopied++;
1265 			fpp++;
1266 		}
1267 		if (door_stack_copyout(start, layout->dl_descp, descsize)) {
1268 			error = E2BIG;
1269 			goto fail;
1270 		}
1271 	}
1272 	fpp = NULL;			/* finished processing */
1273 
1274 	if (layout->dl_datap != NULL) {
1275 		ASSERT(datasize != 0);
1276 		datap = layout->dl_datap;
1277 		if (ct->d_upcall != NULL || datasize <= door_max_arg) {
1278 			if (door_stack_copyout(ct->d_buf, datap, datasize)) {
1279 				error = E2BIG;
1280 				goto fail;
1281 			}
1282 		}
1283 	}
1284 
1285 	if (is_private && empty_pool) {
1286 		door_info_t di;
1287 
1288 		infop = layout->dl_infop;
1289 		ASSERT(infop != NULL);
1290 
1291 		di.di_target = curproc->p_pid;
1292 		di.di_proc = (door_ptr_t)(uintptr_t)dp->door_pc;
1293 		di.di_data = (door_ptr_t)(uintptr_t)dp->door_data;
1294 		di.di_uniquifier = dp->door_index;
1295 		di.di_attributes = (dp->door_flags & DOOR_ATTR_MASK) |
1296 		    DOOR_LOCAL;
1297 
1298 		if (door_stack_copyout(&di, infop, sizeof (di))) {
1299 			error = E2BIG;
1300 			goto fail;
1301 		}
1302 	}
1303 
1304 	if (get_udatamodel() == DATAMODEL_NATIVE) {
1305 		struct door_results dr;
1306 
1307 		dr.cookie = dp->door_data;
1308 		dr.data_ptr = datap;
1309 		dr.data_size = datasize;
1310 		dr.desc_ptr = (door_desc_t *)layout->dl_descp;
1311 		dr.desc_num = ncopied;
1312 		dr.pc = dp->door_pc;
1313 		dr.nservers = !empty_pool;
1314 		dr.door_info = (door_info_t *)infop;
1315 
1316 		if (door_stack_copyout(&dr, layout->dl_resultsp, sizeof (dr))) {
1317 			error = E2BIG;
1318 			goto fail;
1319 		}
1320 #ifdef _SYSCALL32_IMPL
1321 	} else {
1322 		struct door_results32 dr32;
1323 
1324 		dr32.cookie = (caddr32_t)(uintptr_t)dp->door_data;
1325 		dr32.data_ptr = (caddr32_t)(uintptr_t)datap;
1326 		dr32.data_size = (size32_t)datasize;
1327 		dr32.desc_ptr = (caddr32_t)(uintptr_t)layout->dl_descp;
1328 		dr32.desc_num = ncopied;
1329 		dr32.pc = (caddr32_t)(uintptr_t)dp->door_pc;
1330 		dr32.nservers = !empty_pool;
1331 		dr32.door_info = (caddr32_t)(uintptr_t)infop;
1332 
1333 		if (door_stack_copyout(&dr32, layout->dl_resultsp,
1334 		    sizeof (dr32))) {
1335 			error = E2BIG;
1336 			goto fail;
1337 		}
1338 #endif
1339 	}
1340 
1341 	error = door_finish_dispatch(layout->dl_sp);
1342 fail:
1343 	if (start != NULL) {
1344 		if (error != 0)
1345 			door_fd_close(start, ncopied);
1346 		kmem_free(start, descsize);
1347 	}
1348 	if (fpp != NULL)
1349 		door_fp_close(fpp, ndesc);
1350 
1351 	return (error);
1352 }
1353 
1354 /*
1355  * Return the results (if any) to the caller (if any) and wait for the
1356  * next invocation on a door.
1357  */
1358 int
1359 door_return(caddr_t data_ptr, size_t data_size,
1360     door_desc_t *desc_ptr, uint_t desc_num, caddr_t sp, size_t ssize)
1361 {
1362 	kthread_t	*caller;
1363 	klwp_t		*lwp;
1364 	int		error = 0;
1365 	door_node_t	*dp;
1366 	door_server_t	*st;		/* curthread door_data */
1367 	door_client_t	*ct;		/* caller door_data */
1368 	int		cancel_pending;
1369 
1370 	st = door_my_server(1);
1371 
1372 	/*
1373 	 * If thread was bound to a door that no longer exists, return
1374 	 * an error.  This can happen if a thread is bound to a door
1375 	 * before the process calls forkall(); in the child, the door
1376 	 * doesn't exist and door_fork() sets the d_invbound flag.
1377 	 */
1378 	if (st->d_invbound)
1379 		return (set_errno(EINVAL));
1380 
1381 	st->d_sp = sp;			/* Save base of stack. */
1382 	st->d_ssize = ssize;		/* and its size */
1383 
1384 	/*
1385 	 * This should be done in shuttle_resume(), just before going to
1386 	 * sleep, but we want to avoid overhead while holding door_knob.
1387 	 * prstop() is just a no-op if we don't really go to sleep.
1388 	 * We test not-kernel-address-space for the sake of clustering code.
1389 	 */
1390 	lwp = ttolwp(curthread);
1391 	if (lwp && lwp->lwp_nostop == 0 && curproc->p_as != &kas)
1392 		prstop(PR_REQUESTED, 0);
1393 
1394 	/* Make sure the caller hasn't gone away */
1395 	mutex_enter(&door_knob);
1396 	if ((caller = st->d_caller) == NULL || caller->t_door == NULL) {
1397 		if (desc_num != 0) {
1398 			/* close any DOOR_RELEASE descriptors */
1399 			mutex_exit(&door_knob);
1400 			error = door_release_fds(desc_ptr, desc_num);
1401 			if (error)
1402 				return (set_errno(error));
1403 			mutex_enter(&door_knob);
1404 		}
1405 		goto out;
1406 	}
1407 	ct = DOOR_CLIENT(caller->t_door);
1408 
1409 	ct->d_args.data_size = data_size;
1410 	ct->d_args.desc_num = desc_num;
1411 	/*
1412 	 * Transfer results, if any, to the client
1413 	 */
1414 	if (data_size != 0 || desc_num != 0) {
1415 		/*
1416 		 * Prevent the client from exiting until we have finished
1417 		 * moving results.
1418 		 */
1419 		DOOR_T_HOLD(ct);
1420 		mutex_exit(&door_knob);
1421 		error = door_results(caller, data_ptr, data_size,
1422 		    desc_ptr, desc_num);
1423 		mutex_enter(&door_knob);
1424 		DOOR_T_RELEASE(ct);
1425 		/*
1426 		 * Pass EOVERFLOW errors back to the client
1427 		 */
1428 		if (error && error != EOVERFLOW) {
1429 			mutex_exit(&door_knob);
1430 			return (set_errno(error));
1431 		}
1432 	}
1433 out:
1434 	/* Put ourselves on the available server thread list */
1435 	door_release_server(st->d_pool, curthread);
1436 
1437 	/*
1438 	 * Make sure the caller is still waiting to be resumed
1439 	 */
1440 	if (caller) {
1441 		disp_lock_t *tlp;
1442 
1443 		thread_lock(caller);
1444 		ct->d_error = error;		/* Return any errors */
1445 		if (caller->t_state == TS_SLEEP &&
1446 		    SOBJ_TYPE(caller->t_sobj_ops) == SOBJ_SHUTTLE) {
1447 			cpu_t *cp = CPU;
1448 
1449 			tlp = caller->t_lockp;
1450 			/*
1451 			 * Setting t_disp_queue prevents erroneous preemptions
1452 			 * if this thread is still in execution on another
1453 			 * processor
1454 			 */
1455 			caller->t_disp_queue = cp->cpu_disp;
1456 			CL_ACTIVE(caller);
1457 			/*
1458 			 * We are calling thread_onproc() instead of
1459 			 * THREAD_ONPROC() because compiler can reorder
1460 			 * the two stores of t_state and t_lockp in
1461 			 * THREAD_ONPROC().
1462 			 */
1463 			thread_onproc(caller, cp);
1464 			disp_lock_exit_high(tlp);
1465 			shuttle_resume(caller, &door_knob);
1466 		} else {
1467 			/* May have been setrun or in stop state */
1468 			thread_unlock(caller);
1469 			shuttle_swtch(&door_knob);
1470 		}
1471 	} else {
1472 		shuttle_swtch(&door_knob);
1473 	}
1474 
1475 	/*
1476 	 * We've sprung to life. Determine if we are part of a door
1477 	 * invocation, or just interrupted
1478 	 */
1479 	mutex_enter(&door_knob);
1480 	if ((dp = st->d_active) != NULL) {
1481 		/*
1482 		 * Normal door invocation. Return any error condition
1483 		 * encountered while trying to pass args to the server
1484 		 * thread.
1485 		 */
1486 		lwp->lwp_asleep = 0;
1487 		/*
1488 		 * Prevent the caller from leaving us while we
1489 		 * are copying out the arguments from it's buffer.
1490 		 */
1491 		ASSERT(st->d_caller != NULL);
1492 		ct = DOOR_CLIENT(st->d_caller->t_door);
1493 
1494 		DOOR_T_HOLD(ct);
1495 		mutex_exit(&door_knob);
1496 		error = door_server_dispatch(ct, dp);
1497 		mutex_enter(&door_knob);
1498 		DOOR_T_RELEASE(ct);
1499 
1500 		/* let the client know we have processed its message */
1501 		ct->d_args_done = 1;
1502 
1503 		if (error) {
1504 			caller = st->d_caller;
1505 			if (caller)
1506 				ct = DOOR_CLIENT(caller->t_door);
1507 			else
1508 				ct = NULL;
1509 			goto out;
1510 		}
1511 		mutex_exit(&door_knob);
1512 		return (0);
1513 	} else {
1514 		/*
1515 		 * We are not involved in a door_invocation.
1516 		 * Check for /proc related activity...
1517 		 */
1518 		st->d_caller = NULL;
1519 		door_server_exit(curproc, curthread);
1520 		mutex_exit(&door_knob);
1521 		cancel_pending = 0;
1522 		if (ISSIG(curthread, FORREAL) || lwp->lwp_sysabort ||
1523 		    MUSTRETURN(curproc, curthread) ||
1524 		    (cancel_pending = schedctl_cancel_pending()) != 0) {
1525 			if (cancel_pending)
1526 				schedctl_cancel_eintr();
1527 			lwp->lwp_asleep = 0;
1528 			lwp->lwp_sysabort = 0;
1529 			return (set_errno(EINTR));
1530 		}
1531 		/* Go back and wait for another request */
1532 		lwp->lwp_asleep = 0;
1533 		mutex_enter(&door_knob);
1534 		caller = NULL;
1535 		goto out;
1536 	}
1537 }
1538 
1539 /*
1540  * Revoke any future invocations on this door
1541  */
1542 int
1543 door_revoke(int did)
1544 {
1545 	door_node_t	*d;
1546 	int		error;
1547 
1548 	if ((d = door_lookup(did, NULL)) == NULL)
1549 		return (set_errno(EBADF));
1550 
1551 	mutex_enter(&door_knob);
1552 	if (d->door_target != curproc) {
1553 		mutex_exit(&door_knob);
1554 		releasef(did);
1555 		return (set_errno(EPERM));
1556 	}
1557 	d->door_flags |= DOOR_REVOKED;
1558 	if (d->door_flags & DOOR_PRIVATE)
1559 		cv_broadcast(&d->door_servers.dp_cv);
1560 	else
1561 		cv_broadcast(&curproc->p_server_threads.dp_cv);
1562 	mutex_exit(&door_knob);
1563 	releasef(did);
1564 	/* Invalidate the descriptor */
1565 	if ((error = closeandsetf(did, NULL)) != 0)
1566 		return (set_errno(error));
1567 	return (0);
1568 }
1569 
1570 int
1571 door_info(int did, struct door_info *d_info)
1572 {
1573 	door_node_t	*dp;
1574 	door_info_t	di;
1575 	door_server_t	*st;
1576 	file_t		*fp = NULL;
1577 
1578 	if (did == DOOR_QUERY) {
1579 		/* Get information on door current thread is bound to */
1580 		if ((st = door_my_server(0)) == NULL ||
1581 		    (dp = st->d_pool) == NULL)
1582 			/* Thread isn't bound to a door */
1583 			return (set_errno(EBADF));
1584 	} else if ((dp = door_lookup(did, &fp)) == NULL) {
1585 		/* Not a door */
1586 		return (set_errno(EBADF));
1587 	}
1588 
1589 	door_info_common(dp, &di, fp);
1590 
1591 	if (did != DOOR_QUERY)
1592 		releasef(did);
1593 
1594 	if (copyout(&di, d_info, sizeof (struct door_info)))
1595 		return (set_errno(EFAULT));
1596 	return (0);
1597 }
1598 
1599 /*
1600  * Common code for getting information about a door either via the
1601  * door_info system call or the door_ki_info kernel call.
1602  */
1603 void
1604 door_info_common(door_node_t *dp, struct door_info *dip, file_t *fp)
1605 {
1606 	int unref_count;
1607 
1608 	bzero(dip, sizeof (door_info_t));
1609 
1610 	mutex_enter(&door_knob);
1611 	if (dp->door_target == NULL)
1612 		dip->di_target = -1;
1613 	else
1614 		dip->di_target = dp->door_target->p_pid;
1615 
1616 	dip->di_attributes = dp->door_flags & DOOR_ATTR_MASK;
1617 	if (dp->door_target == curproc)
1618 		dip->di_attributes |= DOOR_LOCAL;
1619 	dip->di_proc = (door_ptr_t)(uintptr_t)dp->door_pc;
1620 	dip->di_data = (door_ptr_t)(uintptr_t)dp->door_data;
1621 	dip->di_uniquifier = dp->door_index;
1622 	/*
1623 	 * If this door is in the middle of having an unreferenced
1624 	 * notification delivered, don't count the VN_HOLD by
1625 	 * door_deliver_unref in determining if it is unreferenced.
1626 	 * This handles the case where door_info is called from the
1627 	 * thread delivering the unref notification.
1628 	 */
1629 	if (dp->door_flags & DOOR_UNREF_ACTIVE)
1630 		unref_count = 2;
1631 	else
1632 		unref_count = 1;
1633 	mutex_exit(&door_knob);
1634 
1635 	if (fp == NULL) {
1636 		/*
1637 		 * If this thread is bound to the door, then we can just
1638 		 * check the vnode; a ref count of 1 (or 2 if this is
1639 		 * handling an unref notification) means that the hold
1640 		 * from the door_bind is the only reference to the door
1641 		 * (no file descriptor refers to it).
1642 		 */
1643 		if (DTOV(dp)->v_count == unref_count)
1644 			dip->di_attributes |= DOOR_IS_UNREF;
1645 	} else {
1646 		/*
1647 		 * If we're working from a file descriptor or door handle
1648 		 * we need to look at the file structure count.  We don't
1649 		 * need to hold the vnode lock since this is just a snapshot.
1650 		 */
1651 		mutex_enter(&fp->f_tlock);
1652 		if (fp->f_count == 1 && DTOV(dp)->v_count == unref_count)
1653 			dip->di_attributes |= DOOR_IS_UNREF;
1654 		mutex_exit(&fp->f_tlock);
1655 	}
1656 }
1657 
1658 /*
1659  * Return credentials of the door caller (if any) for this invocation
1660  */
1661 int
1662 door_ucred(struct ucred_s *uch)
1663 {
1664 	kthread_t	*caller;
1665 	door_server_t	*st;
1666 	door_client_t	*ct;
1667 	door_upcall_t	*dup;
1668 	struct proc	*p;
1669 	struct ucred_s	*res;
1670 	int		err;
1671 
1672 	mutex_enter(&door_knob);
1673 	if ((st = door_my_server(0)) == NULL ||
1674 	    (caller = st->d_caller) == NULL) {
1675 		mutex_exit(&door_knob);
1676 		return (set_errno(EINVAL));
1677 	}
1678 
1679 	ASSERT(caller->t_door != NULL);
1680 	ct = DOOR_CLIENT(caller->t_door);
1681 
1682 	/* Prevent caller from exiting while we examine the cred */
1683 	DOOR_T_HOLD(ct);
1684 	mutex_exit(&door_knob);
1685 
1686 	p = ttoproc(caller);
1687 
1688 	/*
1689 	 * If the credentials are not specified by the client, get the one
1690 	 * associated with the calling process.
1691 	 */
1692 	if ((dup = ct->d_upcall) != NULL)
1693 		res = cred2ucred(dup->du_cred, p0.p_pid, NULL, CRED());
1694 	else
1695 		res = cred2ucred(caller->t_cred, p->p_pid, NULL, CRED());
1696 
1697 	mutex_enter(&door_knob);
1698 	DOOR_T_RELEASE(ct);
1699 	mutex_exit(&door_knob);
1700 
1701 	err = copyout(res, uch, res->uc_size);
1702 
1703 	kmem_free(res, res->uc_size);
1704 
1705 	if (err != 0)
1706 		return (set_errno(EFAULT));
1707 
1708 	return (0);
1709 }
1710 
1711 /*
1712  * Bind the current lwp to the server thread pool associated with 'did'
1713  */
1714 int
1715 door_bind(int did)
1716 {
1717 	door_node_t	*dp;
1718 	door_server_t	*st;
1719 
1720 	if ((dp = door_lookup(did, NULL)) == NULL) {
1721 		/* Not a door */
1722 		return (set_errno(EBADF));
1723 	}
1724 
1725 	/*
1726 	 * Can't bind to a non-private door, and can't bind to a door
1727 	 * served by another process.
1728 	 */
1729 	if ((dp->door_flags & DOOR_PRIVATE) == 0 ||
1730 	    dp->door_target != curproc) {
1731 		releasef(did);
1732 		return (set_errno(EINVAL));
1733 	}
1734 
1735 	st = door_my_server(1);
1736 	if (st->d_pool)
1737 		door_unbind_thread(st->d_pool);
1738 	st->d_pool = dp;
1739 	st->d_invbound = 0;
1740 	door_bind_thread(dp);
1741 	releasef(did);
1742 
1743 	return (0);
1744 }
1745 
1746 /*
1747  * Unbind the current lwp from it's server thread pool
1748  */
1749 int
1750 door_unbind(void)
1751 {
1752 	door_server_t *st;
1753 
1754 	if ((st = door_my_server(0)) == NULL)
1755 		return (set_errno(EBADF));
1756 
1757 	if (st->d_invbound) {
1758 		ASSERT(st->d_pool == NULL);
1759 		st->d_invbound = 0;
1760 		return (0);
1761 	}
1762 	if (st->d_pool == NULL)
1763 		return (set_errno(EBADF));
1764 	door_unbind_thread(st->d_pool);
1765 	st->d_pool = NULL;
1766 	return (0);
1767 }
1768 
1769 /*
1770  * Create a descriptor for the associated file and fill in the
1771  * attributes associated with it.
1772  *
1773  * Return 0 for success, -1 otherwise;
1774  */
1775 int
1776 door_insert(struct file *fp, door_desc_t *dp)
1777 {
1778 	struct vnode *vp;
1779 	int	fd;
1780 	door_attr_t attributes = DOOR_DESCRIPTOR;
1781 
1782 	ASSERT(MUTEX_NOT_HELD(&door_knob));
1783 	if ((fd = ufalloc(0)) == -1)
1784 		return (-1);
1785 	setf(fd, fp);
1786 	dp->d_data.d_desc.d_descriptor = fd;
1787 
1788 	/* Fill in the attributes */
1789 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
1790 		vp = fp->f_vnode;
1791 	if (vp && vp->v_type == VDOOR) {
1792 		if (VTOD(vp)->door_target == curproc)
1793 			attributes |= DOOR_LOCAL;
1794 		attributes |= VTOD(vp)->door_flags & DOOR_ATTR_MASK;
1795 		dp->d_data.d_desc.d_id = VTOD(vp)->door_index;
1796 	}
1797 	dp->d_attributes = attributes;
1798 	return (0);
1799 }
1800 
1801 /*
1802  * Return an available thread for this server.  A NULL return value indicates
1803  * that either:
1804  *	The door has been revoked, or
1805  *	a signal was received.
1806  * The two conditions can be differentiated using DOOR_INVALID(dp).
1807  */
1808 static kthread_t *
1809 door_get_server(door_node_t *dp)
1810 {
1811 	kthread_t **ktp;
1812 	kthread_t *server_t;
1813 	door_pool_t *pool;
1814 	door_server_t *st;
1815 	int signalled;
1816 
1817 	disp_lock_t *tlp;
1818 	cpu_t *cp;
1819 
1820 	ASSERT(MUTEX_HELD(&door_knob));
1821 
1822 	if (dp->door_flags & DOOR_PRIVATE)
1823 		pool = &dp->door_servers;
1824 	else
1825 		pool = &dp->door_target->p_server_threads;
1826 
1827 	for (;;) {
1828 		/*
1829 		 * We search the thread pool, looking for a server thread
1830 		 * ready to take an invocation (i.e. one which is still
1831 		 * sleeping on a shuttle object).  If none are available,
1832 		 * we sleep on the pool's CV, and will be signaled when a
1833 		 * thread is added to the pool.
1834 		 *
1835 		 * This relies on the fact that once a thread in the thread
1836 		 * pool wakes up, it *must* remove and add itself to the pool
1837 		 * before it can receive door calls.
1838 		 */
1839 		if (DOOR_INVALID(dp))
1840 			return (NULL);	/* Target has become invalid */
1841 
1842 		for (ktp = &pool->dp_threads;
1843 		    (server_t = *ktp) != NULL;
1844 		    ktp = &st->d_servers) {
1845 			st = DOOR_SERVER(server_t->t_door);
1846 
1847 			thread_lock(server_t);
1848 			if (server_t->t_state == TS_SLEEP &&
1849 			    SOBJ_TYPE(server_t->t_sobj_ops) == SOBJ_SHUTTLE)
1850 				break;
1851 			thread_unlock(server_t);
1852 		}
1853 		if (server_t != NULL)
1854 			break;		/* we've got a live one! */
1855 
1856 		if (!cv_wait_sig_swap_core(&pool->dp_cv, &door_knob,
1857 		    &signalled)) {
1858 			/*
1859 			 * If we were signaled and the door is still
1860 			 * valid, pass the signal on to another waiter.
1861 			 */
1862 			if (signalled && !DOOR_INVALID(dp))
1863 				cv_signal(&pool->dp_cv);
1864 			return (NULL);	/* Got a signal */
1865 		}
1866 	}
1867 
1868 	/*
1869 	 * We've got a thread_lock()ed thread which is still on the
1870 	 * shuttle.  Take it off the list of available server threads
1871 	 * and mark it as ONPROC.  We are committed to resuming this
1872 	 * thread now.
1873 	 */
1874 	tlp = server_t->t_lockp;
1875 	cp = CPU;
1876 
1877 	*ktp = st->d_servers;
1878 	st->d_servers = NULL;
1879 	/*
1880 	 * Setting t_disp_queue prevents erroneous preemptions
1881 	 * if this thread is still in execution on another processor
1882 	 */
1883 	server_t->t_disp_queue = cp->cpu_disp;
1884 	CL_ACTIVE(server_t);
1885 	/*
1886 	 * We are calling thread_onproc() instead of
1887 	 * THREAD_ONPROC() because compiler can reorder
1888 	 * the two stores of t_state and t_lockp in
1889 	 * THREAD_ONPROC().
1890 	 */
1891 	thread_onproc(server_t, cp);
1892 	disp_lock_exit(tlp);
1893 	return (server_t);
1894 }
1895 
1896 /*
1897  * Put a server thread back in the pool.
1898  */
1899 static void
1900 door_release_server(door_node_t *dp, kthread_t *t)
1901 {
1902 	door_server_t *st = DOOR_SERVER(t->t_door);
1903 	door_pool_t *pool;
1904 
1905 	ASSERT(MUTEX_HELD(&door_knob));
1906 	st->d_active = NULL;
1907 	st->d_caller = NULL;
1908 	st->d_layout_done = 0;
1909 	if (dp && (dp->door_flags & DOOR_PRIVATE)) {
1910 		ASSERT(dp->door_target == NULL ||
1911 		    dp->door_target == ttoproc(t));
1912 		pool = &dp->door_servers;
1913 	} else {
1914 		pool = &ttoproc(t)->p_server_threads;
1915 	}
1916 
1917 	st->d_servers = pool->dp_threads;
1918 	pool->dp_threads = t;
1919 
1920 	/* If someone is waiting for a server thread, wake him up */
1921 	cv_signal(&pool->dp_cv);
1922 }
1923 
1924 /*
1925  * Remove a server thread from the pool if present.
1926  */
1927 static void
1928 door_server_exit(proc_t *p, kthread_t *t)
1929 {
1930 	door_pool_t *pool;
1931 	kthread_t **next;
1932 	door_server_t *st = DOOR_SERVER(t->t_door);
1933 
1934 	ASSERT(MUTEX_HELD(&door_knob));
1935 	if (st->d_pool != NULL) {
1936 		ASSERT(st->d_pool->door_flags & DOOR_PRIVATE);
1937 		pool = &st->d_pool->door_servers;
1938 	} else {
1939 		pool = &p->p_server_threads;
1940 	}
1941 
1942 	next = &pool->dp_threads;
1943 	while (*next != NULL) {
1944 		if (*next == t) {
1945 			*next = DOOR_SERVER(t->t_door)->d_servers;
1946 			return;
1947 		}
1948 		next = &(DOOR_SERVER((*next)->t_door)->d_servers);
1949 	}
1950 }
1951 
1952 /*
1953  * Lookup the door descriptor. Caller must call releasef when finished
1954  * with associated door.
1955  */
1956 static door_node_t *
1957 door_lookup(int did, file_t **fpp)
1958 {
1959 	vnode_t	*vp;
1960 	file_t *fp;
1961 
1962 	ASSERT(MUTEX_NOT_HELD(&door_knob));
1963 	if ((fp = getf(did)) == NULL)
1964 		return (NULL);
1965 	/*
1966 	 * Use the underlying vnode (we may be namefs mounted)
1967 	 */
1968 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
1969 		vp = fp->f_vnode;
1970 
1971 	if (vp == NULL || vp->v_type != VDOOR) {
1972 		releasef(did);
1973 		return (NULL);
1974 	}
1975 
1976 	if (fpp)
1977 		*fpp = fp;
1978 
1979 	return (VTOD(vp));
1980 }
1981 
1982 /*
1983  * The current thread is exiting, so clean up any pending
1984  * invocation details
1985  */
1986 void
1987 door_slam(void)
1988 {
1989 	door_node_t *dp;
1990 	door_data_t *dt;
1991 	door_client_t *ct;
1992 	door_server_t *st;
1993 
1994 	/*
1995 	 * If we are an active door server, notify our
1996 	 * client that we are exiting and revoke our door.
1997 	 */
1998 	if ((dt = door_my_data(0)) == NULL)
1999 		return;
2000 	ct = DOOR_CLIENT(dt);
2001 	st = DOOR_SERVER(dt);
2002 
2003 	mutex_enter(&door_knob);
2004 	for (;;) {
2005 		if (DOOR_T_HELD(ct))
2006 			cv_wait(&ct->d_cv, &door_knob);
2007 		else if (DOOR_T_HELD(st))
2008 			cv_wait(&st->d_cv, &door_knob);
2009 		else
2010 			break;			/* neither flag is set */
2011 	}
2012 	curthread->t_door = NULL;
2013 	if ((dp = st->d_active) != NULL) {
2014 		kthread_t *t = st->d_caller;
2015 		proc_t *p = curproc;
2016 
2017 		/* Revoke our door if the process is exiting */
2018 		if (dp->door_target == p && (p->p_flag & SEXITING)) {
2019 			door_list_delete(dp);
2020 			dp->door_target = NULL;
2021 			dp->door_flags |= DOOR_REVOKED;
2022 			if (dp->door_flags & DOOR_PRIVATE)
2023 				cv_broadcast(&dp->door_servers.dp_cv);
2024 			else
2025 				cv_broadcast(&p->p_server_threads.dp_cv);
2026 		}
2027 
2028 		if (t != NULL) {
2029 			/*
2030 			 * Let the caller know we are gone
2031 			 */
2032 			DOOR_CLIENT(t->t_door)->d_error = DOOR_EXIT;
2033 			thread_lock(t);
2034 			if (t->t_state == TS_SLEEP &&
2035 			    SOBJ_TYPE(t->t_sobj_ops) == SOBJ_SHUTTLE)
2036 				setrun_locked(t);
2037 			thread_unlock(t);
2038 		}
2039 	}
2040 	mutex_exit(&door_knob);
2041 	if (st->d_pool)
2042 		door_unbind_thread(st->d_pool);	/* Implicit door_unbind */
2043 	kmem_free(dt, sizeof (door_data_t));
2044 }
2045 
2046 /*
2047  * Set DOOR_REVOKED for all doors of the current process. This is called
2048  * on exit before all lwp's are being terminated so that door calls will
2049  * return with an error.
2050  */
2051 void
2052 door_revoke_all()
2053 {
2054 	door_node_t *dp;
2055 	proc_t *p = ttoproc(curthread);
2056 
2057 	mutex_enter(&door_knob);
2058 	for (dp = p->p_door_list; dp != NULL; dp = dp->door_list) {
2059 		ASSERT(dp->door_target == p);
2060 		dp->door_flags |= DOOR_REVOKED;
2061 		if (dp->door_flags & DOOR_PRIVATE)
2062 			cv_broadcast(&dp->door_servers.dp_cv);
2063 	}
2064 	cv_broadcast(&p->p_server_threads.dp_cv);
2065 	mutex_exit(&door_knob);
2066 }
2067 
2068 /*
2069  * The process is exiting, and all doors it created need to be revoked.
2070  */
2071 void
2072 door_exit(void)
2073 {
2074 	door_node_t *dp;
2075 	proc_t *p = ttoproc(curthread);
2076 
2077 	ASSERT(p->p_lwpcnt == 1);
2078 	/*
2079 	 * Walk the list of active doors created by this process and
2080 	 * revoke them all.
2081 	 */
2082 	mutex_enter(&door_knob);
2083 	for (dp = p->p_door_list; dp != NULL; dp = dp->door_list) {
2084 		dp->door_target = NULL;
2085 		dp->door_flags |= DOOR_REVOKED;
2086 		if (dp->door_flags & DOOR_PRIVATE)
2087 			cv_broadcast(&dp->door_servers.dp_cv);
2088 	}
2089 	cv_broadcast(&p->p_server_threads.dp_cv);
2090 	/* Clear the list */
2091 	p->p_door_list = NULL;
2092 
2093 	/* Clean up the unref list */
2094 	while ((dp = p->p_unref_list) != NULL) {
2095 		p->p_unref_list = dp->door_ulist;
2096 		dp->door_ulist = NULL;
2097 		mutex_exit(&door_knob);
2098 		VN_RELE(DTOV(dp));
2099 		mutex_enter(&door_knob);
2100 	}
2101 	mutex_exit(&door_knob);
2102 }
2103 
2104 
2105 /*
2106  * The process is executing forkall(), and we need to flag threads that
2107  * are bound to a door in the child.  This will make the child threads
2108  * return an error to door_return unless they call door_unbind first.
2109  */
2110 void
2111 door_fork(kthread_t *parent, kthread_t *child)
2112 {
2113 	door_data_t *pt = parent->t_door;
2114 	door_server_t *st = DOOR_SERVER(pt);
2115 	door_data_t *dt;
2116 
2117 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2118 	if (pt != NULL && (st->d_pool != NULL || st->d_invbound)) {
2119 		/* parent thread is bound to a door */
2120 		dt = child->t_door =
2121 		    kmem_zalloc(sizeof (door_data_t), KM_SLEEP);
2122 		DOOR_SERVER(dt)->d_invbound = 1;
2123 	}
2124 }
2125 
2126 /*
2127  * Deliver queued unrefs to appropriate door server.
2128  */
2129 static int
2130 door_unref(void)
2131 {
2132 	door_node_t	*dp;
2133 	static door_arg_t unref_args = { DOOR_UNREF_DATA, 0, 0, 0, 0, 0 };
2134 	proc_t *p = ttoproc(curthread);
2135 
2136 	/* make sure there's only one unref thread per process */
2137 	mutex_enter(&door_knob);
2138 	if (p->p_unref_thread) {
2139 		mutex_exit(&door_knob);
2140 		return (set_errno(EALREADY));
2141 	}
2142 	p->p_unref_thread = 1;
2143 	mutex_exit(&door_knob);
2144 
2145 	(void) door_my_data(1);			/* create info, if necessary */
2146 
2147 	for (;;) {
2148 		mutex_enter(&door_knob);
2149 
2150 		/* Grab a queued request */
2151 		while ((dp = p->p_unref_list) == NULL) {
2152 			if (!cv_wait_sig(&p->p_unref_cv, &door_knob)) {
2153 				/*
2154 				 * Interrupted.
2155 				 * Return so we can finish forkall() or exit().
2156 				 */
2157 				p->p_unref_thread = 0;
2158 				mutex_exit(&door_knob);
2159 				return (set_errno(EINTR));
2160 			}
2161 		}
2162 		p->p_unref_list = dp->door_ulist;
2163 		dp->door_ulist = NULL;
2164 		dp->door_flags |= DOOR_UNREF_ACTIVE;
2165 		mutex_exit(&door_knob);
2166 
2167 		(void) door_upcall(DTOV(dp), &unref_args, NULL, SIZE_MAX, 0);
2168 
2169 		if (unref_args.rbuf != 0) {
2170 			kmem_free(unref_args.rbuf, unref_args.rsize);
2171 			unref_args.rbuf = NULL;
2172 			unref_args.rsize = 0;
2173 		}
2174 
2175 		mutex_enter(&door_knob);
2176 		ASSERT(dp->door_flags & DOOR_UNREF_ACTIVE);
2177 		dp->door_flags &= ~DOOR_UNREF_ACTIVE;
2178 		mutex_exit(&door_knob);
2179 		VN_RELE(DTOV(dp));
2180 	}
2181 }
2182 
2183 
2184 /*
2185  * Deliver queued unrefs to kernel door server.
2186  */
2187 /* ARGSUSED */
2188 static void
2189 door_unref_kernel(caddr_t arg)
2190 {
2191 	door_node_t	*dp;
2192 	static door_arg_t unref_args = { DOOR_UNREF_DATA, 0, 0, 0, 0, 0 };
2193 	proc_t *p = ttoproc(curthread);
2194 	callb_cpr_t cprinfo;
2195 
2196 	/* should only be one of these */
2197 	mutex_enter(&door_knob);
2198 	if (p->p_unref_thread) {
2199 		mutex_exit(&door_knob);
2200 		return;
2201 	}
2202 	p->p_unref_thread = 1;
2203 	mutex_exit(&door_knob);
2204 
2205 	(void) door_my_data(1);		/* make sure we have a door_data_t */
2206 
2207 	CALLB_CPR_INIT(&cprinfo, &door_knob, callb_generic_cpr, "door_unref");
2208 	for (;;) {
2209 		mutex_enter(&door_knob);
2210 		/* Grab a queued request */
2211 		while ((dp = p->p_unref_list) == NULL) {
2212 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
2213 			cv_wait(&p->p_unref_cv, &door_knob);
2214 			CALLB_CPR_SAFE_END(&cprinfo, &door_knob);
2215 		}
2216 		p->p_unref_list = dp->door_ulist;
2217 		dp->door_ulist = NULL;
2218 		dp->door_flags |= DOOR_UNREF_ACTIVE;
2219 		mutex_exit(&door_knob);
2220 
2221 		(*(dp->door_pc))(dp->door_data, &unref_args, NULL, NULL, NULL);
2222 
2223 		mutex_enter(&door_knob);
2224 		ASSERT(dp->door_flags & DOOR_UNREF_ACTIVE);
2225 		dp->door_flags &= ~DOOR_UNREF_ACTIVE;
2226 		mutex_exit(&door_knob);
2227 		VN_RELE(DTOV(dp));
2228 	}
2229 }
2230 
2231 
2232 /*
2233  * Queue an unref invocation for processing for the current process
2234  * The door may or may not be revoked at this point.
2235  */
2236 void
2237 door_deliver_unref(door_node_t *d)
2238 {
2239 	struct proc *server = d->door_target;
2240 
2241 	ASSERT(MUTEX_HELD(&door_knob));
2242 	ASSERT(d->door_active == 0);
2243 
2244 	if (server == NULL)
2245 		return;
2246 	/*
2247 	 * Create a lwp to deliver unref calls if one isn't already running.
2248 	 *
2249 	 * A separate thread is used to deliver unrefs since the current
2250 	 * thread may be holding resources (e.g. locks) in user land that
2251 	 * may be needed by the unref processing. This would cause a
2252 	 * deadlock.
2253 	 */
2254 	if (d->door_flags & DOOR_UNREF_MULTI) {
2255 		/* multiple unrefs */
2256 		d->door_flags &= ~DOOR_DELAY;
2257 	} else {
2258 		/* Only 1 unref per door */
2259 		d->door_flags &= ~(DOOR_UNREF|DOOR_DELAY);
2260 	}
2261 	mutex_exit(&door_knob);
2262 
2263 	/*
2264 	 * Need to bump the vnode count before putting the door on the
2265 	 * list so it doesn't get prematurely released by door_unref.
2266 	 */
2267 	VN_HOLD(DTOV(d));
2268 
2269 	mutex_enter(&door_knob);
2270 	/* is this door already on the unref list? */
2271 	if (d->door_flags & DOOR_UNREF_MULTI) {
2272 		door_node_t *dp;
2273 		for (dp = server->p_unref_list; dp != NULL;
2274 		    dp = dp->door_ulist) {
2275 			if (d == dp) {
2276 				/* already there, don't need to add another */
2277 				mutex_exit(&door_knob);
2278 				VN_RELE(DTOV(d));
2279 				mutex_enter(&door_knob);
2280 				return;
2281 			}
2282 		}
2283 	}
2284 	ASSERT(d->door_ulist == NULL);
2285 	d->door_ulist = server->p_unref_list;
2286 	server->p_unref_list = d;
2287 	cv_broadcast(&server->p_unref_cv);
2288 }
2289 
2290 /*
2291  * The callers buffer isn't big enough for all of the data/fd's. Allocate
2292  * space in the callers address space for the results and copy the data
2293  * there.
2294  *
2295  * For EOVERFLOW, we must clean up the server's door descriptors.
2296  */
2297 static int
2298 door_overflow(
2299 	kthread_t	*caller,
2300 	caddr_t		data_ptr,	/* data location */
2301 	size_t		data_size,	/* data size */
2302 	door_desc_t	*desc_ptr,	/* descriptor location */
2303 	uint_t		desc_num)	/* descriptor size */
2304 {
2305 	proc_t *callerp = ttoproc(caller);
2306 	struct as *as = callerp->p_as;
2307 	door_client_t *ct = DOOR_CLIENT(caller->t_door);
2308 	caddr_t	addr;			/* Resulting address in target */
2309 	size_t	rlen;			/* Rounded len */
2310 	size_t	len;
2311 	uint_t	i;
2312 	size_t	ds = desc_num * sizeof (door_desc_t);
2313 
2314 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2315 	ASSERT(DOOR_T_HELD(ct) || ct->d_kernel);
2316 
2317 	/* Do initial overflow check */
2318 	if (!ufcanalloc(callerp, desc_num))
2319 		return (EMFILE);
2320 
2321 	/*
2322 	 * Allocate space for this stuff in the callers address space
2323 	 */
2324 	rlen = roundup(data_size + ds, PAGESIZE);
2325 	as_rangelock(as);
2326 	map_addr_proc(&addr, rlen, 0, 1, as->a_userlimit, ttoproc(caller), 0);
2327 	if (addr == NULL ||
2328 	    as_map(as, addr, rlen, segvn_create, zfod_argsp) != 0) {
2329 		/* No virtual memory available, or anon mapping failed */
2330 		as_rangeunlock(as);
2331 		if (!ct->d_kernel && desc_num > 0) {
2332 			int error = door_release_fds(desc_ptr, desc_num);
2333 			if (error)
2334 				return (error);
2335 		}
2336 		return (EOVERFLOW);
2337 	}
2338 	as_rangeunlock(as);
2339 
2340 	if (ct->d_kernel)
2341 		goto out;
2342 
2343 	if (data_size != 0) {
2344 		caddr_t	src = data_ptr;
2345 		caddr_t saddr = addr;
2346 
2347 		/* Copy any data */
2348 		len = data_size;
2349 		while (len != 0) {
2350 			int	amount;
2351 			int	error;
2352 
2353 			amount = len > PAGESIZE ? PAGESIZE : len;
2354 			if ((error = door_copy(as, src, saddr, amount)) != 0) {
2355 				(void) as_unmap(as, addr, rlen);
2356 				return (error);
2357 			}
2358 			saddr += amount;
2359 			src += amount;
2360 			len -= amount;
2361 		}
2362 	}
2363 	/* Copy any fd's */
2364 	if (desc_num != 0) {
2365 		door_desc_t	*didpp, *start;
2366 		struct file	**fpp;
2367 		int		fpp_size;
2368 
2369 		start = didpp = kmem_alloc(ds, KM_SLEEP);
2370 		if (copyin_nowatch(desc_ptr, didpp, ds)) {
2371 			kmem_free(start, ds);
2372 			(void) as_unmap(as, addr, rlen);
2373 			return (EFAULT);
2374 		}
2375 
2376 		fpp_size = desc_num * sizeof (struct file *);
2377 		if (fpp_size > ct->d_fpp_size) {
2378 			/* make more space */
2379 			if (ct->d_fpp_size)
2380 				kmem_free(ct->d_fpp, ct->d_fpp_size);
2381 			ct->d_fpp_size = fpp_size;
2382 			ct->d_fpp = kmem_alloc(ct->d_fpp_size, KM_SLEEP);
2383 		}
2384 		fpp = ct->d_fpp;
2385 
2386 		for (i = 0; i < desc_num; i++) {
2387 			struct file *fp;
2388 			int fd = didpp->d_data.d_desc.d_descriptor;
2389 
2390 			if (!(didpp->d_attributes & DOOR_DESCRIPTOR) ||
2391 			    (fp = getf(fd)) == NULL) {
2392 				/* close translated references */
2393 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
2394 				/* close untranslated references */
2395 				door_fd_rele(didpp, desc_num - i, 0);
2396 				kmem_free(start, ds);
2397 				(void) as_unmap(as, addr, rlen);
2398 				return (EINVAL);
2399 			}
2400 			mutex_enter(&fp->f_tlock);
2401 			fp->f_count++;
2402 			mutex_exit(&fp->f_tlock);
2403 
2404 			*fpp = fp;
2405 			releasef(fd);
2406 
2407 			if (didpp->d_attributes & DOOR_RELEASE) {
2408 				/* release passed reference */
2409 				(void) closeandsetf(fd, NULL);
2410 			}
2411 
2412 			fpp++; didpp++;
2413 		}
2414 		kmem_free(start, ds);
2415 	}
2416 
2417 out:
2418 	ct->d_overflow = 1;
2419 	ct->d_args.rbuf = addr;
2420 	ct->d_args.rsize = rlen;
2421 	return (0);
2422 }
2423 
2424 /*
2425  * Transfer arguments from the client to the server.
2426  */
2427 static int
2428 door_args(kthread_t *server, int is_private)
2429 {
2430 	door_server_t *st = DOOR_SERVER(server->t_door);
2431 	door_client_t *ct = DOOR_CLIENT(curthread->t_door);
2432 	uint_t	ndid;
2433 	size_t	dsize;
2434 	int	error;
2435 
2436 	ASSERT(DOOR_T_HELD(st));
2437 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2438 
2439 	ndid = ct->d_args.desc_num;
2440 	if (ndid > door_max_desc)
2441 		return (E2BIG);
2442 
2443 	/*
2444 	 * Get the stack layout, and fail now if it won't fit.
2445 	 */
2446 	error = door_layout(server, ct->d_args.data_size, ndid, is_private);
2447 	if (error != 0)
2448 		return (error);
2449 
2450 	dsize = ndid * sizeof (door_desc_t);
2451 	if (ct->d_args.data_size != 0) {
2452 		if (ct->d_args.data_size <= door_max_arg) {
2453 			/*
2454 			 * Use a 2 copy method for small amounts of data
2455 			 *
2456 			 * Allocate a little more than we need for the
2457 			 * args, in the hope that the results will fit
2458 			 * without having to reallocate a buffer
2459 			 */
2460 			ASSERT(ct->d_buf == NULL);
2461 			ct->d_bufsize = roundup(ct->d_args.data_size,
2462 			    DOOR_ROUND);
2463 			ct->d_buf = kmem_alloc(ct->d_bufsize, KM_SLEEP);
2464 			if (copyin_nowatch(ct->d_args.data_ptr,
2465 			    ct->d_buf, ct->d_args.data_size) != 0) {
2466 				kmem_free(ct->d_buf, ct->d_bufsize);
2467 				ct->d_buf = NULL;
2468 				ct->d_bufsize = 0;
2469 				return (EFAULT);
2470 			}
2471 		} else {
2472 			struct as	*as;
2473 			caddr_t		src;
2474 			caddr_t		dest;
2475 			size_t		len = ct->d_args.data_size;
2476 			uintptr_t	base;
2477 
2478 			/*
2479 			 * Use a 1 copy method
2480 			 */
2481 			as = ttoproc(server)->p_as;
2482 			src = ct->d_args.data_ptr;
2483 
2484 			dest = st->d_layout.dl_datap;
2485 			base = (uintptr_t)dest;
2486 
2487 			/*
2488 			 * Copy data directly into server.  We proceed
2489 			 * downward from the top of the stack, to mimic
2490 			 * normal stack usage. This allows the guard page
2491 			 * to stop us before we corrupt anything.
2492 			 */
2493 			while (len != 0) {
2494 				uintptr_t start;
2495 				uintptr_t end;
2496 				uintptr_t offset;
2497 				size_t	amount;
2498 
2499 				/*
2500 				 * Locate the next part to copy.
2501 				 */
2502 				end = base + len;
2503 				start = P2ALIGN(end - 1, PAGESIZE);
2504 
2505 				/*
2506 				 * if we are on the final (first) page, fix
2507 				 * up the start position.
2508 				 */
2509 				if (P2ALIGN(base, PAGESIZE) == start)
2510 					start = base;
2511 
2512 				offset = start - base;	/* the copy offset */
2513 				amount = end - start;	/* # bytes to copy */
2514 
2515 				ASSERT(amount > 0 && amount <= len &&
2516 				    amount <= PAGESIZE);
2517 
2518 				error = door_copy(as, src + offset,
2519 				    dest + offset, amount);
2520 				if (error != 0)
2521 					return (error);
2522 				len -= amount;
2523 			}
2524 		}
2525 	}
2526 	/*
2527 	 * Copyin the door args and translate them into files
2528 	 */
2529 	if (ndid != 0) {
2530 		door_desc_t	*didpp;
2531 		door_desc_t	*start;
2532 		struct file	**fpp;
2533 
2534 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
2535 
2536 		if (copyin_nowatch(ct->d_args.desc_ptr, didpp, dsize)) {
2537 			kmem_free(start, dsize);
2538 			return (EFAULT);
2539 		}
2540 		ct->d_fpp_size = ndid * sizeof (struct file *);
2541 		ct->d_fpp = kmem_alloc(ct->d_fpp_size, KM_SLEEP);
2542 		fpp = ct->d_fpp;
2543 		while (ndid--) {
2544 			struct file *fp;
2545 			int fd = didpp->d_data.d_desc.d_descriptor;
2546 
2547 			/* We only understand file descriptors as passed objs */
2548 			if (!(didpp->d_attributes & DOOR_DESCRIPTOR) ||
2549 			    (fp = getf(fd)) == NULL) {
2550 				/* close translated references */
2551 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
2552 				/* close untranslated references */
2553 				door_fd_rele(didpp, ndid + 1, 0);
2554 				kmem_free(start, dsize);
2555 				kmem_free(ct->d_fpp, ct->d_fpp_size);
2556 				ct->d_fpp = NULL;
2557 				ct->d_fpp_size = 0;
2558 				return (EINVAL);
2559 			}
2560 			/* Hold the fp */
2561 			mutex_enter(&fp->f_tlock);
2562 			fp->f_count++;
2563 			mutex_exit(&fp->f_tlock);
2564 
2565 			*fpp = fp;
2566 			releasef(fd);
2567 
2568 			if (didpp->d_attributes & DOOR_RELEASE) {
2569 				/* release passed reference */
2570 				(void) closeandsetf(fd, NULL);
2571 			}
2572 
2573 			fpp++; didpp++;
2574 		}
2575 		kmem_free(start, dsize);
2576 	}
2577 	return (0);
2578 }
2579 
2580 /*
2581  * Transfer arguments from a user client to a kernel server.  This copies in
2582  * descriptors and translates them into door handles.  It doesn't touch the
2583  * other data, letting the kernel server deal with that (to avoid needing
2584  * to copy the data twice).
2585  */
2586 static int
2587 door_translate_in(void)
2588 {
2589 	door_client_t *ct = DOOR_CLIENT(curthread->t_door);
2590 	uint_t	ndid;
2591 
2592 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2593 	ndid = ct->d_args.desc_num;
2594 	if (ndid > door_max_desc)
2595 		return (E2BIG);
2596 	/*
2597 	 * Copyin the door args and translate them into door handles.
2598 	 */
2599 	if (ndid != 0) {
2600 		door_desc_t	*didpp;
2601 		door_desc_t	*start;
2602 		size_t		dsize = ndid * sizeof (door_desc_t);
2603 		struct file	*fp;
2604 
2605 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
2606 
2607 		if (copyin_nowatch(ct->d_args.desc_ptr, didpp, dsize)) {
2608 			kmem_free(start, dsize);
2609 			return (EFAULT);
2610 		}
2611 		while (ndid--) {
2612 			vnode_t	*vp;
2613 			int fd = didpp->d_data.d_desc.d_descriptor;
2614 
2615 			/*
2616 			 * We only understand file descriptors as passed objs
2617 			 */
2618 			if ((didpp->d_attributes & DOOR_DESCRIPTOR) &&
2619 			    (fp = getf(fd)) != NULL) {
2620 				didpp->d_data.d_handle = FTODH(fp);
2621 				/* Hold the door */
2622 				door_ki_hold(didpp->d_data.d_handle);
2623 
2624 				releasef(fd);
2625 
2626 				if (didpp->d_attributes & DOOR_RELEASE) {
2627 					/* release passed reference */
2628 					(void) closeandsetf(fd, NULL);
2629 				}
2630 
2631 				if (VOP_REALVP(fp->f_vnode, &vp, NULL))
2632 					vp = fp->f_vnode;
2633 
2634 				/* Set attributes */
2635 				didpp->d_attributes = DOOR_HANDLE |
2636 				    (VTOD(vp)->door_flags & DOOR_ATTR_MASK);
2637 			} else {
2638 				/* close translated references */
2639 				door_fd_close(start, didpp - start);
2640 				/* close untranslated references */
2641 				door_fd_rele(didpp, ndid + 1, 0);
2642 				kmem_free(start, dsize);
2643 				return (EINVAL);
2644 			}
2645 			didpp++;
2646 		}
2647 		ct->d_args.desc_ptr = start;
2648 	}
2649 	return (0);
2650 }
2651 
2652 /*
2653  * Translate door arguments from kernel to user.  This copies the passed
2654  * door handles.  It doesn't touch other data.  It is used by door_upcall,
2655  * and for data returned by a door_call to a kernel server.
2656  */
2657 static int
2658 door_translate_out(void)
2659 {
2660 	door_client_t *ct = DOOR_CLIENT(curthread->t_door);
2661 	uint_t	ndid;
2662 
2663 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2664 	ndid = ct->d_args.desc_num;
2665 	if (ndid > door_max_desc) {
2666 		door_fd_rele(ct->d_args.desc_ptr, ndid, 1);
2667 		return (E2BIG);
2668 	}
2669 	/*
2670 	 * Translate the door args into files
2671 	 */
2672 	if (ndid != 0) {
2673 		door_desc_t	*didpp = ct->d_args.desc_ptr;
2674 		struct file	**fpp;
2675 
2676 		ct->d_fpp_size = ndid * sizeof (struct file *);
2677 		fpp = ct->d_fpp = kmem_alloc(ct->d_fpp_size, KM_SLEEP);
2678 		while (ndid--) {
2679 			struct file *fp = NULL;
2680 			int fd = -1;
2681 
2682 			/*
2683 			 * We understand file descriptors and door
2684 			 * handles as passed objs.
2685 			 */
2686 			if (didpp->d_attributes & DOOR_DESCRIPTOR) {
2687 				fd = didpp->d_data.d_desc.d_descriptor;
2688 				fp = getf(fd);
2689 			} else if (didpp->d_attributes & DOOR_HANDLE)
2690 				fp = DHTOF(didpp->d_data.d_handle);
2691 			if (fp != NULL) {
2692 				/* Hold the fp */
2693 				mutex_enter(&fp->f_tlock);
2694 				fp->f_count++;
2695 				mutex_exit(&fp->f_tlock);
2696 
2697 				*fpp = fp;
2698 				if (didpp->d_attributes & DOOR_DESCRIPTOR)
2699 					releasef(fd);
2700 				if (didpp->d_attributes & DOOR_RELEASE) {
2701 					/* release passed reference */
2702 					if (fd >= 0)
2703 						(void) closeandsetf(fd, NULL);
2704 					else
2705 						(void) closef(fp);
2706 				}
2707 			} else {
2708 				/* close translated references */
2709 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
2710 				/* close untranslated references */
2711 				door_fd_rele(didpp, ndid + 1, 1);
2712 				kmem_free(ct->d_fpp, ct->d_fpp_size);
2713 				ct->d_fpp = NULL;
2714 				ct->d_fpp_size = 0;
2715 				return (EINVAL);
2716 			}
2717 			fpp++; didpp++;
2718 		}
2719 	}
2720 	return (0);
2721 }
2722 
2723 /*
2724  * Move the results from the server to the client
2725  */
2726 static int
2727 door_results(kthread_t *caller, caddr_t data_ptr, size_t data_size,
2728     door_desc_t *desc_ptr, uint_t desc_num)
2729 {
2730 	door_client_t	*ct = DOOR_CLIENT(caller->t_door);
2731 	door_upcall_t	*dup = ct->d_upcall;
2732 	size_t		dsize;
2733 	size_t		rlen;
2734 	size_t		result_size;
2735 
2736 	ASSERT(DOOR_T_HELD(ct));
2737 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2738 
2739 	if (ct->d_noresults)
2740 		return (E2BIG);		/* No results expected */
2741 
2742 	if (desc_num > door_max_desc)
2743 		return (E2BIG);		/* Too many descriptors */
2744 
2745 	dsize = desc_num * sizeof (door_desc_t);
2746 	/*
2747 	 * Check if the results are bigger than the clients buffer
2748 	 */
2749 	if (dsize)
2750 		rlen = roundup(data_size, sizeof (door_desc_t));
2751 	else
2752 		rlen = data_size;
2753 	if ((result_size = rlen + dsize) == 0)
2754 		return (0);
2755 
2756 	if (dup != NULL) {
2757 		if (desc_num > dup->du_max_descs)
2758 			return (EMFILE);
2759 
2760 		if (data_size > dup->du_max_data)
2761 			return (E2BIG);
2762 
2763 		/*
2764 		 * Handle upcalls
2765 		 */
2766 		if (ct->d_args.rbuf == NULL || ct->d_args.rsize < result_size) {
2767 			/*
2768 			 * If there's no return buffer or the buffer is too
2769 			 * small, allocate a new one.  The old buffer (if it
2770 			 * exists) will be freed by the upcall client.
2771 			 */
2772 			if (result_size > door_max_upcall_reply)
2773 				return (E2BIG);
2774 			ct->d_args.rsize = result_size;
2775 			ct->d_args.rbuf = kmem_alloc(result_size, KM_SLEEP);
2776 		}
2777 		ct->d_args.data_ptr = ct->d_args.rbuf;
2778 		if (data_size != 0 &&
2779 		    copyin_nowatch(data_ptr, ct->d_args.data_ptr,
2780 		    data_size) != 0)
2781 			return (EFAULT);
2782 	} else if (result_size > ct->d_args.rsize) {
2783 		return (door_overflow(caller, data_ptr, data_size,
2784 		    desc_ptr, desc_num));
2785 	} else if (data_size != 0) {
2786 		if (data_size <= door_max_arg) {
2787 			/*
2788 			 * Use a 2 copy method for small amounts of data
2789 			 */
2790 			if (ct->d_buf == NULL) {
2791 				ct->d_bufsize = data_size;
2792 				ct->d_buf = kmem_alloc(ct->d_bufsize, KM_SLEEP);
2793 			} else if (ct->d_bufsize < data_size) {
2794 				kmem_free(ct->d_buf, ct->d_bufsize);
2795 				ct->d_bufsize = data_size;
2796 				ct->d_buf = kmem_alloc(ct->d_bufsize, KM_SLEEP);
2797 			}
2798 			if (copyin_nowatch(data_ptr, ct->d_buf, data_size) != 0)
2799 				return (EFAULT);
2800 		} else {
2801 			struct as *as = ttoproc(caller)->p_as;
2802 			caddr_t	dest = ct->d_args.rbuf;
2803 			caddr_t	src = data_ptr;
2804 			size_t	len = data_size;
2805 
2806 			/* Copy data directly into client */
2807 			while (len != 0) {
2808 				uint_t	amount;
2809 				uint_t	max;
2810 				uint_t	off;
2811 				int	error;
2812 
2813 				off = (uintptr_t)dest & PAGEOFFSET;
2814 				if (off)
2815 					max = PAGESIZE - off;
2816 				else
2817 					max = PAGESIZE;
2818 				amount = len > max ? max : len;
2819 				error = door_copy(as, src, dest, amount);
2820 				if (error != 0)
2821 					return (error);
2822 				dest += amount;
2823 				src += amount;
2824 				len -= amount;
2825 			}
2826 		}
2827 	}
2828 
2829 	/*
2830 	 * Copyin the returned door ids and translate them into door_node_t
2831 	 */
2832 	if (desc_num != 0) {
2833 		door_desc_t *start;
2834 		door_desc_t *didpp;
2835 		struct file **fpp;
2836 		size_t	fpp_size;
2837 		uint_t	i;
2838 
2839 		/* First, check if we would overflow client */
2840 		if (!ufcanalloc(ttoproc(caller), desc_num))
2841 			return (EMFILE);
2842 
2843 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
2844 		if (copyin_nowatch(desc_ptr, didpp, dsize)) {
2845 			kmem_free(start, dsize);
2846 			return (EFAULT);
2847 		}
2848 		fpp_size = desc_num * sizeof (struct file *);
2849 		if (fpp_size > ct->d_fpp_size) {
2850 			/* make more space */
2851 			if (ct->d_fpp_size)
2852 				kmem_free(ct->d_fpp, ct->d_fpp_size);
2853 			ct->d_fpp_size = fpp_size;
2854 			ct->d_fpp = kmem_alloc(fpp_size, KM_SLEEP);
2855 		}
2856 		fpp = ct->d_fpp;
2857 
2858 		for (i = 0; i < desc_num; i++) {
2859 			struct file *fp;
2860 			int fd = didpp->d_data.d_desc.d_descriptor;
2861 
2862 			/* Only understand file descriptor results */
2863 			if (!(didpp->d_attributes & DOOR_DESCRIPTOR) ||
2864 			    (fp = getf(fd)) == NULL) {
2865 				/* close translated references */
2866 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
2867 				/* close untranslated references */
2868 				door_fd_rele(didpp, desc_num - i, 0);
2869 				kmem_free(start, dsize);
2870 				return (EINVAL);
2871 			}
2872 
2873 			mutex_enter(&fp->f_tlock);
2874 			fp->f_count++;
2875 			mutex_exit(&fp->f_tlock);
2876 
2877 			*fpp = fp;
2878 			releasef(fd);
2879 
2880 			if (didpp->d_attributes & DOOR_RELEASE) {
2881 				/* release passed reference */
2882 				(void) closeandsetf(fd, NULL);
2883 			}
2884 
2885 			fpp++; didpp++;
2886 		}
2887 		kmem_free(start, dsize);
2888 	}
2889 	return (0);
2890 }
2891 
2892 /*
2893  * Close all the descriptors.
2894  */
2895 static void
2896 door_fd_close(door_desc_t *d, uint_t n)
2897 {
2898 	uint_t	i;
2899 
2900 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2901 	for (i = 0; i < n; i++) {
2902 		if (d->d_attributes & DOOR_DESCRIPTOR) {
2903 			(void) closeandsetf(
2904 			    d->d_data.d_desc.d_descriptor, NULL);
2905 		} else if (d->d_attributes & DOOR_HANDLE) {
2906 			door_ki_rele(d->d_data.d_handle);
2907 		}
2908 		d++;
2909 	}
2910 }
2911 
2912 /*
2913  * Close descriptors that have the DOOR_RELEASE attribute set.
2914  */
2915 void
2916 door_fd_rele(door_desc_t *d, uint_t n, int from_kernel)
2917 {
2918 	uint_t	i;
2919 
2920 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2921 	for (i = 0; i < n; i++) {
2922 		if (d->d_attributes & DOOR_RELEASE) {
2923 			if (d->d_attributes & DOOR_DESCRIPTOR) {
2924 				(void) closeandsetf(
2925 				    d->d_data.d_desc.d_descriptor, NULL);
2926 			} else if (from_kernel &&
2927 			    (d->d_attributes & DOOR_HANDLE)) {
2928 				door_ki_rele(d->d_data.d_handle);
2929 			}
2930 		}
2931 		d++;
2932 	}
2933 }
2934 
2935 /*
2936  * Copy descriptors into the kernel so we can release any marked
2937  * DOOR_RELEASE.
2938  */
2939 int
2940 door_release_fds(door_desc_t *desc_ptr, uint_t ndesc)
2941 {
2942 	size_t dsize;
2943 	door_desc_t *didpp;
2944 	uint_t desc_num;
2945 
2946 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2947 	ASSERT(ndesc != 0);
2948 
2949 	desc_num = MIN(ndesc, door_max_desc);
2950 
2951 	dsize = desc_num * sizeof (door_desc_t);
2952 	didpp = kmem_alloc(dsize, KM_SLEEP);
2953 
2954 	while (ndesc > 0) {
2955 		uint_t count = MIN(ndesc, desc_num);
2956 
2957 		if (copyin_nowatch(desc_ptr, didpp,
2958 		    count * sizeof (door_desc_t))) {
2959 			kmem_free(didpp, dsize);
2960 			return (EFAULT);
2961 		}
2962 		door_fd_rele(didpp, count, 0);
2963 
2964 		ndesc -= count;
2965 		desc_ptr += count;
2966 	}
2967 	kmem_free(didpp, dsize);
2968 	return (0);
2969 }
2970 
2971 /*
2972  * Decrement ref count on all the files passed
2973  */
2974 static void
2975 door_fp_close(struct file **fp, uint_t n)
2976 {
2977 	uint_t	i;
2978 
2979 	ASSERT(MUTEX_NOT_HELD(&door_knob));
2980 
2981 	for (i = 0; i < n; i++)
2982 		(void) closef(fp[i]);
2983 }
2984 
2985 /*
2986  * Copy data from 'src' in current address space to 'dest' in 'as' for 'len'
2987  * bytes.
2988  *
2989  * Performs this using 1 mapin and 1 copy operation.
2990  *
2991  * We really should do more than 1 page at a time to improve
2992  * performance, but for now this is treated as an anomalous condition.
2993  */
2994 static int
2995 door_copy(struct as *as, caddr_t src, caddr_t dest, uint_t len)
2996 {
2997 	caddr_t	kaddr;
2998 	caddr_t	rdest;
2999 	uint_t	off;
3000 	page_t	**pplist;
3001 	page_t	*pp = NULL;
3002 	int	error = 0;
3003 
3004 	ASSERT(len <= PAGESIZE);
3005 	off = (uintptr_t)dest & PAGEOFFSET;	/* offset within the page */
3006 	rdest = (caddr_t)((uintptr_t)dest &
3007 	    (uintptr_t)PAGEMASK);	/* Page boundary */
3008 	ASSERT(off + len <= PAGESIZE);
3009 
3010 	/*
3011 	 * Lock down destination page.
3012 	 */
3013 	if (as_pagelock(as, &pplist, rdest, PAGESIZE, S_WRITE))
3014 		return (E2BIG);
3015 	/*
3016 	 * Check if we have a shadow page list from as_pagelock. If not,
3017 	 * we took the slow path and have to find our page struct the hard
3018 	 * way.
3019 	 */
3020 	if (pplist == NULL) {
3021 		pfn_t	pfnum;
3022 
3023 		/* MMU mapping is already locked down */
3024 		AS_LOCK_ENTER(as, RW_READER);
3025 		pfnum = hat_getpfnum(as->a_hat, rdest);
3026 		AS_LOCK_EXIT(as);
3027 
3028 		/*
3029 		 * TODO: The pfn step should not be necessary - need
3030 		 * a hat_getpp() function.
3031 		 */
3032 		if (pf_is_memory(pfnum)) {
3033 			pp = page_numtopp_nolock(pfnum);
3034 			ASSERT(pp == NULL || PAGE_LOCKED(pp));
3035 		} else
3036 			pp = NULL;
3037 		if (pp == NULL) {
3038 			as_pageunlock(as, pplist, rdest, PAGESIZE, S_WRITE);
3039 			return (E2BIG);
3040 		}
3041 	} else {
3042 		pp = *pplist;
3043 	}
3044 	/*
3045 	 * Map destination page into kernel address
3046 	 */
3047 	if (kpm_enable)
3048 		kaddr = (caddr_t)hat_kpm_mapin(pp, (struct kpme *)NULL);
3049 	else
3050 		kaddr = (caddr_t)ppmapin(pp, PROT_READ | PROT_WRITE,
3051 		    (caddr_t)-1);
3052 
3053 	/*
3054 	 * Copy from src to dest
3055 	 */
3056 	if (copyin_nowatch(src, kaddr + off, len) != 0)
3057 		error = EFAULT;
3058 	/*
3059 	 * Unmap destination page from kernel
3060 	 */
3061 	if (kpm_enable)
3062 		hat_kpm_mapout(pp, (struct kpme *)NULL, kaddr);
3063 	else
3064 		ppmapout(kaddr);
3065 	/*
3066 	 * Unlock destination page
3067 	 */
3068 	as_pageunlock(as, pplist, rdest, PAGESIZE, S_WRITE);
3069 	return (error);
3070 }
3071 
3072 /*
3073  * General kernel upcall using doors
3074  *	Returns 0 on success, errno for failures.
3075  *	Caller must have a hold on the door based vnode, and on any
3076  *	references passed in desc_ptr.  The references are released
3077  *	in the event of an error, and passed without duplication
3078  *	otherwise.  Note that param->rbuf must be 64-bit aligned in
3079  *	a 64-bit kernel, since it may be used to store door descriptors
3080  *	if they are returned by the server.  The caller is responsible
3081  *	for holding a reference to the cred passed in.
3082  */
3083 int
3084 door_upcall(vnode_t *vp, door_arg_t *param, struct cred *cred,
3085     size_t max_data, uint_t max_descs)
3086 {
3087 	/* Locals */
3088 	door_upcall_t	*dup;
3089 	door_node_t	*dp;
3090 	kthread_t	*server_thread;
3091 	int		error = 0;
3092 	klwp_t		*lwp;
3093 	door_client_t	*ct;		/* curthread door_data */
3094 	door_server_t	*st;		/* server thread door_data */
3095 	int		gotresults = 0;
3096 	int		cancel_pending;
3097 
3098 	if (vp->v_type != VDOOR) {
3099 		if (param->desc_num)
3100 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
3101 		return (EINVAL);
3102 	}
3103 
3104 	lwp = ttolwp(curthread);
3105 	ct = door_my_client(1);
3106 	dp = VTOD(vp);	/* Convert to a door_node_t */
3107 
3108 	dup = kmem_zalloc(sizeof (*dup), KM_SLEEP);
3109 	dup->du_cred = (cred != NULL) ? cred : curthread->t_cred;
3110 	dup->du_max_data = max_data;
3111 	dup->du_max_descs = max_descs;
3112 
3113 	/*
3114 	 * This should be done in shuttle_resume(), just before going to
3115 	 * sleep, but we want to avoid overhead while holding door_knob.
3116 	 * prstop() is just a no-op if we don't really go to sleep.
3117 	 * We test not-kernel-address-space for the sake of clustering code.
3118 	 */
3119 	if (lwp && lwp->lwp_nostop == 0 && curproc->p_as != &kas)
3120 		prstop(PR_REQUESTED, 0);
3121 
3122 	mutex_enter(&door_knob);
3123 	if (DOOR_INVALID(dp)) {
3124 		mutex_exit(&door_knob);
3125 		if (param->desc_num)
3126 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
3127 		error = EBADF;
3128 		goto out;
3129 	}
3130 
3131 	if (dp->door_target == &p0) {
3132 		/* Can't do an upcall to a kernel server */
3133 		mutex_exit(&door_knob);
3134 		if (param->desc_num)
3135 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
3136 		error = EINVAL;
3137 		goto out;
3138 	}
3139 
3140 	error = door_check_limits(dp, param, 1);
3141 	if (error != 0) {
3142 		mutex_exit(&door_knob);
3143 		if (param->desc_num)
3144 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
3145 		goto out;
3146 	}
3147 
3148 	/*
3149 	 * Get a server thread from the target domain
3150 	 */
3151 	if ((server_thread = door_get_server(dp)) == NULL) {
3152 		if (DOOR_INVALID(dp))
3153 			error = EBADF;
3154 		else
3155 			error = EAGAIN;
3156 		mutex_exit(&door_knob);
3157 		if (param->desc_num)
3158 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
3159 		goto out;
3160 	}
3161 
3162 	st = DOOR_SERVER(server_thread->t_door);
3163 	ct->d_buf = param->data_ptr;
3164 	ct->d_bufsize = param->data_size;
3165 	ct->d_args = *param;	/* structure assignment */
3166 
3167 	if (ct->d_args.desc_num) {
3168 		/*
3169 		 * Move data from client to server
3170 		 */
3171 		DOOR_T_HOLD(st);
3172 		mutex_exit(&door_knob);
3173 		error = door_translate_out();
3174 		mutex_enter(&door_knob);
3175 		DOOR_T_RELEASE(st);
3176 		if (error) {
3177 			/*
3178 			 * We're not going to resume this thread after all
3179 			 */
3180 			door_release_server(dp, server_thread);
3181 			shuttle_sleep(server_thread);
3182 			mutex_exit(&door_knob);
3183 			goto out;
3184 		}
3185 	}
3186 
3187 	ct->d_upcall = dup;
3188 	if (param->rsize == 0)
3189 		ct->d_noresults = 1;
3190 	else
3191 		ct->d_noresults = 0;
3192 
3193 	dp->door_active++;
3194 
3195 	ct->d_error = DOOR_WAIT;
3196 	st->d_caller = curthread;
3197 	st->d_active = dp;
3198 
3199 	shuttle_resume(server_thread, &door_knob);
3200 
3201 	mutex_enter(&door_knob);
3202 shuttle_return:
3203 	if ((error = ct->d_error) < 0) {	/* DOOR_WAIT or DOOR_EXIT */
3204 		/*
3205 		 * Premature wakeup. Find out why (stop, forkall, sig, exit ...)
3206 		 */
3207 		mutex_exit(&door_knob);		/* May block in ISSIG */
3208 		cancel_pending = 0;
3209 		if (lwp && (ISSIG(curthread, FORREAL) || lwp->lwp_sysabort ||
3210 		    MUSTRETURN(curproc, curthread) ||
3211 		    (cancel_pending = schedctl_cancel_pending()) != 0)) {
3212 			/* Signal, forkall, ... */
3213 			if (cancel_pending)
3214 				schedctl_cancel_eintr();
3215 			lwp->lwp_sysabort = 0;
3216 			mutex_enter(&door_knob);
3217 			error = EINTR;
3218 			/*
3219 			 * If the server has finished processing our call,
3220 			 * or exited (calling door_slam()), then d_error
3221 			 * will have changed.  If the server hasn't finished
3222 			 * yet, d_error will still be DOOR_WAIT, and we
3223 			 * let it know we are not interested in any
3224 			 * results by sending a SIGCANCEL, unless the door
3225 			 * is marked with DOOR_NO_CANCEL.
3226 			 */
3227 			if (ct->d_error == DOOR_WAIT &&
3228 			    st->d_caller == curthread) {
3229 				proc_t	*p = ttoproc(server_thread);
3230 
3231 				st->d_active = NULL;
3232 				st->d_caller = NULL;
3233 				if (!(dp->door_flags & DOOR_NO_CANCEL)) {
3234 					DOOR_T_HOLD(st);
3235 					mutex_exit(&door_knob);
3236 
3237 					mutex_enter(&p->p_lock);
3238 					sigtoproc(p, server_thread, SIGCANCEL);
3239 					mutex_exit(&p->p_lock);
3240 
3241 					mutex_enter(&door_knob);
3242 					DOOR_T_RELEASE(st);
3243 				}
3244 			}
3245 		} else {
3246 			/*
3247 			 * Return from stop(), server exit...
3248 			 *
3249 			 * Note that the server could have done a
3250 			 * door_return while the client was in stop state
3251 			 * (ISSIG), in which case the error condition
3252 			 * is updated by the server.
3253 			 */
3254 			mutex_enter(&door_knob);
3255 			if (ct->d_error == DOOR_WAIT) {
3256 				/* Still waiting for a reply */
3257 				shuttle_swtch(&door_knob);
3258 				mutex_enter(&door_knob);
3259 				if (lwp)
3260 					lwp->lwp_asleep = 0;
3261 				goto	shuttle_return;
3262 			} else if (ct->d_error == DOOR_EXIT) {
3263 				/* Server exit */
3264 				error = EINTR;
3265 			} else {
3266 				/* Server did a door_return during ISSIG */
3267 				error = ct->d_error;
3268 			}
3269 		}
3270 		/*
3271 		 * Can't exit if the server is currently copying
3272 		 * results for me
3273 		 */
3274 		while (DOOR_T_HELD(ct))
3275 			cv_wait(&ct->d_cv, &door_knob);
3276 
3277 		/*
3278 		 * Find out if results were successfully copied.
3279 		 */
3280 		if (ct->d_error == 0)
3281 			gotresults = 1;
3282 	}
3283 	if (lwp) {
3284 		lwp->lwp_asleep = 0;		/* /proc */
3285 		lwp->lwp_sysabort = 0;		/* /proc */
3286 	}
3287 	if (--dp->door_active == 0 && (dp->door_flags & DOOR_DELAY))
3288 		door_deliver_unref(dp);
3289 	mutex_exit(&door_knob);
3290 
3291 	/*
3292 	 * Translate returned doors (if any)
3293 	 */
3294 
3295 	if (ct->d_noresults)
3296 		goto out;
3297 
3298 	if (error) {
3299 		/*
3300 		 * If server returned results successfully, then we've
3301 		 * been interrupted and may need to clean up.
3302 		 */
3303 		if (gotresults) {
3304 			ASSERT(error == EINTR);
3305 			door_fp_close(ct->d_fpp, ct->d_args.desc_num);
3306 		}
3307 		goto out;
3308 	}
3309 
3310 	if (ct->d_args.desc_num) {
3311 		struct file	**fpp;
3312 		door_desc_t	*didpp;
3313 		vnode_t		*vp;
3314 		uint_t		n = ct->d_args.desc_num;
3315 
3316 		didpp = ct->d_args.desc_ptr = (door_desc_t *)(ct->d_args.rbuf +
3317 		    roundup(ct->d_args.data_size, sizeof (door_desc_t)));
3318 		fpp = ct->d_fpp;
3319 
3320 		while (n--) {
3321 			struct file *fp;
3322 
3323 			fp = *fpp;
3324 			if (VOP_REALVP(fp->f_vnode, &vp, NULL))
3325 				vp = fp->f_vnode;
3326 
3327 			didpp->d_attributes = DOOR_HANDLE |
3328 			    (VTOD(vp)->door_flags & DOOR_ATTR_MASK);
3329 			didpp->d_data.d_handle = FTODH(fp);
3330 
3331 			fpp++; didpp++;
3332 		}
3333 	}
3334 
3335 	/* on return data is in rbuf */
3336 	*param = ct->d_args;		/* structure assignment */
3337 
3338 out:
3339 	kmem_free(dup, sizeof (*dup));
3340 
3341 	if (ct->d_fpp) {
3342 		kmem_free(ct->d_fpp, ct->d_fpp_size);
3343 		ct->d_fpp = NULL;
3344 		ct->d_fpp_size = 0;
3345 	}
3346 
3347 	ct->d_upcall = NULL;
3348 	ct->d_noresults = 0;
3349 	ct->d_buf = NULL;
3350 	ct->d_bufsize = 0;
3351 	return (error);
3352 }
3353 
3354 /*
3355  * Add a door to the per-process list of active doors for which the
3356  * process is a server.
3357  */
3358 static void
3359 door_list_insert(door_node_t *dp)
3360 {
3361 	proc_t *p = dp->door_target;
3362 
3363 	ASSERT(MUTEX_HELD(&door_knob));
3364 	dp->door_list = p->p_door_list;
3365 	p->p_door_list = dp;
3366 }
3367 
3368 /*
3369  * Remove a door from the per-process list of active doors.
3370  */
3371 void
3372 door_list_delete(door_node_t *dp)
3373 {
3374 	door_node_t **pp;
3375 
3376 	ASSERT(MUTEX_HELD(&door_knob));
3377 	/*
3378 	 * Find the door in the list.  If the door belongs to another process,
3379 	 * it's OK to use p_door_list since that process can't exit until all
3380 	 * doors have been taken off the list (see door_exit).
3381 	 */
3382 	pp = &(dp->door_target->p_door_list);
3383 	while (*pp != dp)
3384 		pp = &((*pp)->door_list);
3385 
3386 	/* found it, take it off the list */
3387 	*pp = dp->door_list;
3388 }
3389 
3390 
3391 /*
3392  * External kernel interfaces for doors.  These functions are available
3393  * outside the doorfs module for use in creating and using doors from
3394  * within the kernel.
3395  */
3396 
3397 /*
3398  * door_ki_upcall invokes a user-level door server from the kernel, with
3399  * the credentials associated with curthread.
3400  */
3401 int
3402 door_ki_upcall(door_handle_t dh, door_arg_t *param)
3403 {
3404 	return (door_ki_upcall_limited(dh, param, NULL, SIZE_MAX, UINT_MAX));
3405 }
3406 
3407 /*
3408  * door_ki_upcall_limited invokes a user-level door server from the
3409  * kernel with the given credentials and reply limits.  If the "cred"
3410  * argument is NULL, uses the credentials associated with current
3411  * thread.  max_data limits the maximum length of the returned data (the
3412  * client will get E2BIG if they go over), and max_desc limits the
3413  * number of returned descriptors (the client will get EMFILE if they
3414  * go over).
3415  */
3416 int
3417 door_ki_upcall_limited(door_handle_t dh, door_arg_t *param, struct cred *cred,
3418     size_t max_data, uint_t max_desc)
3419 {
3420 	file_t *fp = DHTOF(dh);
3421 	vnode_t *realvp;
3422 
3423 	if (VOP_REALVP(fp->f_vnode, &realvp, NULL))
3424 		realvp = fp->f_vnode;
3425 	return (door_upcall(realvp, param, cred, max_data, max_desc));
3426 }
3427 
3428 /*
3429  * Function call to create a "kernel" door server.  A kernel door
3430  * server provides a way for a user-level process to invoke a function
3431  * in the kernel through a door_call.  From the caller's point of
3432  * view, a kernel door server looks the same as a user-level one
3433  * (except the server pid is 0).  Unlike normal door calls, the
3434  * kernel door function is invoked via a normal function call in the
3435  * same thread and context as the caller.
3436  */
3437 int
3438 door_ki_create(void (*pc_cookie)(), void *data_cookie, uint_t attributes,
3439     door_handle_t *dhp)
3440 {
3441 	int err;
3442 	file_t *fp;
3443 
3444 	/* no DOOR_PRIVATE */
3445 	if ((attributes & ~DOOR_KI_CREATE_MASK) ||
3446 	    (attributes & (DOOR_UNREF | DOOR_UNREF_MULTI)) ==
3447 	    (DOOR_UNREF | DOOR_UNREF_MULTI))
3448 		return (EINVAL);
3449 
3450 	err = door_create_common(pc_cookie, data_cookie, attributes,
3451 	    1, NULL, &fp);
3452 	if (err == 0 && (attributes & (DOOR_UNREF | DOOR_UNREF_MULTI)) &&
3453 	    p0.p_unref_thread == 0) {
3454 		/* need to create unref thread for process 0 */
3455 		(void) thread_create(NULL, 0, door_unref_kernel, NULL, 0, &p0,
3456 		    TS_RUN, minclsyspri);
3457 	}
3458 	if (err == 0) {
3459 		*dhp = FTODH(fp);
3460 	}
3461 	return (err);
3462 }
3463 
3464 void
3465 door_ki_hold(door_handle_t dh)
3466 {
3467 	file_t *fp = DHTOF(dh);
3468 
3469 	mutex_enter(&fp->f_tlock);
3470 	fp->f_count++;
3471 	mutex_exit(&fp->f_tlock);
3472 }
3473 
3474 void
3475 door_ki_rele(door_handle_t dh)
3476 {
3477 	file_t *fp = DHTOF(dh);
3478 
3479 	(void) closef(fp);
3480 }
3481 
3482 int
3483 door_ki_open(char *pathname, door_handle_t *dhp)
3484 {
3485 	file_t *fp;
3486 	vnode_t *vp;
3487 	int err;
3488 
3489 	if ((err = lookupname(pathname, UIO_SYSSPACE, FOLLOW, NULL, &vp)) != 0)
3490 		return (err);
3491 	if (err = VOP_OPEN(&vp, FREAD, kcred, NULL)) {
3492 		VN_RELE(vp);
3493 		return (err);
3494 	}
3495 	if (vp->v_type != VDOOR) {
3496 		VN_RELE(vp);
3497 		return (EINVAL);
3498 	}
3499 	if ((err = falloc(vp, FREAD | FWRITE, &fp, NULL)) != 0) {
3500 		VN_RELE(vp);
3501 		return (err);
3502 	}
3503 	/* falloc returns with f_tlock held on success */
3504 	mutex_exit(&fp->f_tlock);
3505 	*dhp = FTODH(fp);
3506 	return (0);
3507 }
3508 
3509 int
3510 door_ki_info(door_handle_t dh, struct door_info *dip)
3511 {
3512 	file_t *fp = DHTOF(dh);
3513 	vnode_t *vp;
3514 
3515 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
3516 		vp = fp->f_vnode;
3517 	if (vp->v_type != VDOOR)
3518 		return (EINVAL);
3519 	door_info_common(VTOD(vp), dip, fp);
3520 	return (0);
3521 }
3522 
3523 door_handle_t
3524 door_ki_lookup(int did)
3525 {
3526 	file_t *fp;
3527 	door_handle_t dh;
3528 
3529 	/* is the descriptor really a door? */
3530 	if (door_lookup(did, &fp) == NULL)
3531 		return (NULL);
3532 	/* got the door, put a hold on it and release the fd */
3533 	dh = FTODH(fp);
3534 	door_ki_hold(dh);
3535 	releasef(did);
3536 	return (dh);
3537 }
3538 
3539 int
3540 door_ki_setparam(door_handle_t dh, int type, size_t val)
3541 {
3542 	file_t *fp = DHTOF(dh);
3543 	vnode_t *vp;
3544 
3545 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
3546 		vp = fp->f_vnode;
3547 	if (vp->v_type != VDOOR)
3548 		return (EINVAL);
3549 	return (door_setparam_common(VTOD(vp), 1, type, val));
3550 }
3551 
3552 int
3553 door_ki_getparam(door_handle_t dh, int type, size_t *out)
3554 {
3555 	file_t *fp = DHTOF(dh);
3556 	vnode_t *vp;
3557 
3558 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
3559 		vp = fp->f_vnode;
3560 	if (vp->v_type != VDOOR)
3561 		return (EINVAL);
3562 	return (door_getparam_common(VTOD(vp), type, out));
3563 }
3564