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