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