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