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) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
  24  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  25  * Copyright 2016, Joyent, Inc.
  26  */
  27 
  28 #include <sys/errno.h>
  29 #include <sys/exec.h>
  30 #include <sys/file.h>
  31 #include <sys/kmem.h>
  32 #include <sys/modctl.h>
  33 #include <sys/model.h>
  34 #include <sys/proc.h>
  35 #include <sys/syscall.h>
  36 #include <sys/systm.h>
  37 #include <sys/thread.h>
  38 #include <sys/cmn_err.h>
  39 #include <sys/archsystm.h>
  40 #include <sys/pathname.h>
  41 #include <sys/sunddi.h>
  42 
  43 #include <sys/machbrand.h>
  44 #include <sys/brand.h>
  45 #include "s10_brand.h"
  46 
  47 char *s10_emulation_table = NULL;
  48 
  49 void    s10_init_brand_data(zone_t *, kmutex_t *);
  50 void    s10_free_brand_data(zone_t *);
  51 void    s10_setbrand(proc_t *);
  52 int     s10_getattr(zone_t *, int, void *, size_t *);
  53 int     s10_setattr(zone_t *, int, void *, size_t);
  54 int     s10_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
  55                 uintptr_t);
  56 void    s10_copy_procdata(proc_t *, proc_t *);
  57 void    s10_proc_exit(struct proc *);
  58 void    s10_exec();
  59 void    s10_initlwp(klwp_t *, void *);
  60 void    s10_forklwp(klwp_t *, klwp_t *);
  61 void    s10_freelwp(klwp_t *);
  62 void    s10_lwpexit(klwp_t *);
  63 int     s10_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
  64         long *, int, caddr_t, cred_t *, int *);
  65 void    s10_sigset_native_to_s10(sigset_t *);
  66 void    s10_sigset_s10_to_native(sigset_t *);
  67 
  68 /* s10 brand */
  69 struct brand_ops s10_brops = {
  70         s10_init_brand_data,            /* b_init_brand_data */
  71         s10_free_brand_data,            /* b_free_brand_data */
  72         s10_brandsys,                   /* b_brandsys */
  73         s10_setbrand,                   /* b_setbrand */
  74         s10_getattr,                    /* b_getattr */
  75         s10_setattr,                    /* b_setattr */
  76         s10_copy_procdata,              /* b_copy_procdata */
  77         s10_proc_exit,                  /* b_proc_exit */
  78         s10_exec,                       /* b_exec */
  79         lwp_setrval,                    /* b_lwp_setrval */
  80         NULL,                           /* b_lwpdata_alloc */
  81         NULL,                           /* b_lwpdata_free */
  82         s10_initlwp,                    /* b_initlwp */
  83         NULL,                           /* b_initlwp_post */
  84         s10_forklwp,                    /* b_forklwp */
  85         s10_freelwp,                    /* b_freelwp */
  86         s10_lwpexit,                    /* b_lwpexit */
  87         s10_elfexec,                    /* b_elfexec */
  88         s10_sigset_native_to_s10,       /* b_sigset_native_to_brand */
  89         s10_sigset_s10_to_native,       /* b_sigset_brand_to_native */
  90         NULL,                           /* b_sigfd_translate */
  91         S10_NSIG,                       /* b_nsig */
  92         NULL,                           /* b_exit_with_sig */
  93         NULL,                           /* b_wait_filter */
  94         NULL,                           /* b_native_exec */
  95         NULL,                           /* b_map32limit */
  96         NULL,                           /* b_stop_notify */
  97         NULL,                           /* b_waitid_helper */
  98         NULL,                           /* b_sigcld_repost */
  99         NULL,                           /* b_issig_stop */
 100         NULL,                           /* b_sig_ignorable */
 101         NULL,                           /* b_savecontext */
 102 #if defined(_SYSCALL32_IMPL)
 103         NULL,                           /* b_savecontext32 */
 104 #endif
 105         NULL,                           /* b_restorecontext */
 106         NULL,                           /* b_sendsig_stack */
 107         NULL,                           /* b_sendsig */
 108         NULL,                           /* b_setid_clear */
 109         NULL,                           /* b_pagefault */
 110         B_TRUE                          /* b_intp_parse_arg */
 111 };
 112 
 113 #ifdef  sparc
 114 
 115 struct brand_mach_ops s10_mops = {
 116         s10_brand_syscall_callback,
 117         s10_brand_syscall32_callback
 118 };
 119 
 120 #else   /* sparc */
 121 
 122 #ifdef  __amd64
 123 
 124 struct brand_mach_ops s10_mops = {
 125         s10_brand_sysenter_callback,
 126         NULL,
 127         s10_brand_int91_callback,
 128         s10_brand_syscall_callback,
 129         s10_brand_syscall32_callback,
 130         NULL,
 131         NULL
 132 };
 133 
 134 #else   /* ! __amd64 */
 135 
 136 struct brand_mach_ops s10_mops = {
 137         s10_brand_sysenter_callback,
 138         NULL,
 139         NULL,
 140         s10_brand_syscall_callback,
 141         NULL,
 142         NULL,
 143         NULL
 144 };
 145 #endif  /* __amd64 */
 146 
 147 #endif  /* _sparc */
 148 
 149 struct brand    s10_brand = {
 150         BRAND_VER_1,
 151         "solaris10",
 152         &s10_brops,
 153         &s10_mops,
 154         sizeof (brand_proc_data_t),
 155 };
 156 
 157 static struct modlbrand modlbrand = {
 158         &mod_brandops,              /* type of module */
 159         "Solaris 10 Brand",     /* description of module */
 160         &s10_brand          /* driver ops */
 161 };
 162 
 163 static struct modlinkage modlinkage = {
 164         MODREV_1, (void *)&modlbrand, NULL
 165 };
 166 
 167 void
 168 s10_setbrand(proc_t *p)
 169 {
 170         brand_solaris_setbrand(p, &s10_brand);
 171 }
 172 
 173 /*ARGSUSED*/
 174 int
 175 s10_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
 176 {
 177         ASSERT(zone->zone_brand == &s10_brand);
 178         if (attr == S10_EMUL_BITMAP) {
 179                 if (buf == NULL || *bufsize != sizeof (s10_emul_bitmap_t))
 180                         return (EINVAL);
 181                 if (copyout(((s10_zone_data_t *)zone->zone_brand_data)->
 182                     emul_bitmap, buf, sizeof (s10_emul_bitmap_t)) != 0)
 183                         return (EFAULT);
 184                 return (0);
 185         }
 186 
 187         return (EINVAL);
 188 }
 189 
 190 int
 191 s10_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
 192 {
 193         ASSERT(zone->zone_brand == &s10_brand);
 194         if (attr == S10_EMUL_BITMAP) {
 195                 if (buf == NULL || bufsize != sizeof (s10_emul_bitmap_t))
 196                         return (EINVAL);
 197                 if (copyin(buf, ((s10_zone_data_t *)zone->zone_brand_data)->
 198                     emul_bitmap, sizeof (s10_emul_bitmap_t)) != 0)
 199                         return (EFAULT);
 200                 return (0);
 201         }
 202 
 203         return (EINVAL);
 204 }
 205 
 206 #ifdef  __amd64
 207 /*
 208  * The Nevada kernel clears %fs for threads in 64-bit x86 processes but S10's
 209  * libc expects %fs to be nonzero.  This causes some committed
 210  * libc/libthread interfaces (e.g., thr_main()) to fail, which impacts several
 211  * libraries, including libdoor.  This function sets the specified LWP's %fs
 212  * register to the legacy S10 selector value (LWPFS_SEL).
 213  *
 214  * The best solution to the aforementioned problem is backporting CRs
 215  * 6467491 to Solaris 10 so that 64-bit x86 Solaris 10 processes
 216  * would accept zero for %fs.  Backporting the CRs is a requirement for running
 217  * S10 Containers in PV domUs because 64-bit Xen clears %fsbase when %fs is
 218  * nonzero.  Such behavior breaks 64-bit processes because Xen has to fetch the
 219  * FS segments' base addresses from the LWPs' GDTs, which are only capable of
 220  * 32-bit addressing.
 221  */
 222 /*ARGSUSED*/
 223 static void
 224 s10_amd64_correct_fsreg(klwp_t *l)
 225 {
 226         if (lwp_getdatamodel(l) == DATAMODEL_NATIVE) {
 227                 kpreempt_disable();
 228                 l->lwp_pcb.pcb_fs = LWPFS_SEL;
 229                 l->lwp_pcb.pcb_rupdate = 1;
 230                 lwptot(l)->t_post_sys = 1;   /* Guarantee update_sregs() */
 231                 kpreempt_enable();
 232         }
 233 }
 234 #endif  /* __amd64 */
 235 
 236 /*
 237  * Native processes are started with the native ld.so.1 as the command.  This
 238  * brand op is invoked by s10_npreload to fix up the command and arguments
 239  * so that apps like pgrep or ps see the expected command strings.
 240  */
 241 int
 242 s10_native(void *cmd, void *args)
 243 {
 244         struct user     *up = PTOU(curproc);
 245         char            cmd_buf[MAXCOMLEN + 1];
 246         char            arg_buf[PSARGSZ];
 247 
 248         if (copyin(cmd, &cmd_buf, sizeof (cmd_buf)) != 0)
 249                 return (EFAULT);
 250         if (copyin(args, &arg_buf, sizeof (arg_buf)) != 0)
 251                 return (EFAULT);
 252 
 253         /*
 254          * Make sure that the process' interpreter is the native dynamic linker.
 255          * Convention dictates that native processes executing within solaris10-
 256          * branded zones are interpreted by the native dynamic linker (the
 257          * process and its arguments are specified as arguments to the dynamic
 258          * linker).  If this convention is violated (i.e.,
 259          * brandsys(B_S10_NATIVE, ...) is invoked by a process that shouldn't be
 260          * native), then do nothing and silently indicate success.
 261          */
 262         if (strcmp(up->u_comm, S10_LINKER_NAME) != 0)
 263                 return (0);
 264 
 265         /*
 266          * The sizeof has an extra value for the trailing '\0' so this covers
 267          * the appended " " in the following strcmps.
 268          */
 269         if (strncmp(up->u_psargs, BRAND_NATIVE_LINKER64 " ",
 270             sizeof (BRAND_NATIVE_LINKER64)) != 0 &&
 271             strncmp(up->u_psargs, BRAND_NATIVE_LINKER32 " ",
 272             sizeof (BRAND_NATIVE_LINKER32)) != 0)
 273                 return (0);
 274 
 275         mutex_enter(&curproc->p_lock);
 276         (void) strlcpy(up->u_comm, cmd_buf, sizeof (up->u_comm));
 277         (void) strlcpy(up->u_psargs, arg_buf, sizeof (up->u_psargs));
 278         mutex_exit(&curproc->p_lock);
 279 
 280         return (0);
 281 }
 282 
 283 /* ARGSUSED5 */
 284 int
 285 s10_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
 286     uintptr_t arg3, uintptr_t arg4)
 287 {
 288         proc_t  *p = curproc;
 289         int     res;
 290 
 291         *rval = 0;
 292 
 293         if (cmd == B_S10_NATIVE)
 294                 return (s10_native((void *)arg1, (void *)arg2));
 295 
 296         res = brand_solaris_cmd(cmd, arg1, arg2, arg3, &s10_brand, S10_VERSION);
 297         if (res >= 0)
 298                 return (res);
 299 
 300         switch ((cmd)) {
 301         case B_S10_PIDINFO:
 302                 /*
 303                  * The s10 brand needs to be able to get the pid of the
 304                  * current process and the pid of the zone's init, and it
 305                  * needs to do this on every process startup.  Early in
 306                  * brand startup, we can't call getpid() because calls to
 307                  * getpid() represent a magical signal to some old-skool
 308                  * debuggers.  By merging all of this into one call, we
 309                  * make this quite a bit cheaper and easier to handle in
 310                  * the brand module.
 311                  */
 312                 if (copyout(&p->p_pid, (void *)arg1, sizeof (pid_t)) != 0)
 313                         return (EFAULT);
 314                 if (copyout(&p->p_zone->zone_proc_initpid, (void *)arg2,
 315                     sizeof (pid_t)) != 0)
 316                         return (EFAULT);
 317                 return (0);
 318 
 319         case B_S10_ISFDXATTRDIR: {
 320                 /*
 321                  * This subcommand enables the userland brand emulation library
 322                  * to determine whether a file descriptor refers to an extended
 323                  * file attributes directory.  There is no standard syscall or
 324                  * libc function that can make such a determination.
 325                  */
 326                 file_t *dir_filep;
 327 
 328                 dir_filep = getf((int)arg1);
 329                 if (dir_filep == NULL)
 330                         return (EBADF);
 331                 ASSERT(dir_filep->f_vnode != NULL);
 332                 *rval = IS_XATTRDIR(dir_filep->f_vnode);
 333                 releasef((int)arg1);
 334                 return (0);
 335         }
 336 
 337 #ifdef  __amd64
 338         case B_S10_FSREGCORRECTION:
 339                 /*
 340                  * This subcommand exists so that the SYS_lwp_private and
 341                  * SYS_lwp_create syscalls can manually set the current thread's
 342                  * %fs register to the legacy S10 selector value for 64-bit x86
 343                  * processes.
 344                  */
 345                 s10_amd64_correct_fsreg(ttolwp(curthread));
 346                 return (0);
 347 #endif  /* __amd64 */
 348         }
 349 
 350         return (EINVAL);
 351 }
 352 
 353 void
 354 s10_copy_procdata(proc_t *child, proc_t *parent)
 355 {
 356         brand_solaris_copy_procdata(child, parent, &s10_brand);
 357 }
 358 
 359 void
 360 s10_proc_exit(struct proc *p)
 361 {
 362         brand_solaris_proc_exit(p, &s10_brand);
 363 }
 364 
 365 void
 366 s10_exec()
 367 {
 368         brand_solaris_exec(&s10_brand);
 369 }
 370 
 371 void
 372 s10_initlwp(klwp_t *l, void *bd)
 373 {
 374         brand_solaris_initlwp(l, &s10_brand);
 375 }
 376 
 377 void
 378 s10_forklwp(klwp_t *p, klwp_t *c)
 379 {
 380         brand_solaris_forklwp(p, c, &s10_brand);
 381 
 382 #ifdef  __amd64
 383         /*
 384          * Only correct the child's %fs register if the parent's %fs register
 385          * is LWPFS_SEL.  If the parent's %fs register is zero, then the Solaris
 386          * 10 environment that we're emulating uses a version of libc that
 387          * works when %fs is zero (i.e., it contains backports of CRs 6467491
 388          * and 6501650).
 389          */
 390         if (p->lwp_pcb.pcb_fs == LWPFS_SEL)
 391                 s10_amd64_correct_fsreg(c);
 392 #endif  /* __amd64 */
 393 }
 394 
 395 void
 396 s10_freelwp(klwp_t *l)
 397 {
 398         brand_solaris_freelwp(l, &s10_brand);
 399 }
 400 
 401 void
 402 s10_lwpexit(klwp_t *l)
 403 {
 404         brand_solaris_lwpexit(l, &s10_brand);
 405 }
 406 
 407 void
 408 s10_free_brand_data(zone_t *zone)
 409 {
 410         kmem_free(zone->zone_brand_data, sizeof (s10_zone_data_t));
 411 }
 412 
 413 void
 414 s10_init_brand_data(zone_t *zone, kmutex_t *zsl)
 415 {
 416         ASSERT(zone->zone_brand == &s10_brand);
 417         ASSERT(zone->zone_brand_data == NULL);
 418         zone->zone_brand_data = kmem_zalloc(sizeof (s10_zone_data_t), KM_SLEEP);
 419 }
 420 
 421 int
 422 s10_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
 423     int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
 424     int *brand_action)
 425 {
 426         return (brand_solaris_elfexec(vp, uap, args, idatap, level, execsz,
 427             setid, exec_file, cred, brand_action, &s10_brand, S10_BRANDNAME,
 428             S10_LIB, S10_LIB32));
 429 }
 430 
 431 void
 432 s10_sigset_native_to_s10(sigset_t *set)
 433 {
 434         int nativesig;
 435         int s10sig;
 436         sigset_t s10set;
 437 
 438         /*
 439          * Shortcut: we know the first 32 signals are the same in both
 440          * s10 and native Solaris.  Just assign the first word.
 441          */
 442         s10set.__sigbits[0] = set->__sigbits[0];
 443         s10set.__sigbits[1] = 0;
 444         s10set.__sigbits[2] = 0;
 445         s10set.__sigbits[3] = 0;
 446 
 447         /*
 448          * Copy the remainder of the initial set of common signals.
 449          */
 450         for (nativesig = 33; nativesig < S10_SIGRTMIN; nativesig++)
 451                 if (sigismember(set, nativesig))
 452                         sigaddset(&s10set, nativesig);
 453 
 454         /*
 455          * Convert any native RT signals to their S10 values.
 456          */
 457         for (nativesig = _SIGRTMIN, s10sig = S10_SIGRTMIN;
 458             nativesig <= _SIGRTMAX && s10sig <= S10_SIGRTMAX;
 459             nativesig++, s10sig++) {
 460                 if (sigismember(set, nativesig))
 461                         sigaddset(&s10set, s10sig);
 462         }
 463 
 464         *set = s10set;
 465 }
 466 
 467 void
 468 s10_sigset_s10_to_native(sigset_t *set)
 469 {
 470         int s10sig;
 471         int nativesig;
 472         sigset_t nativeset;
 473 
 474         /*
 475          * Shortcut: we know the first 32 signals are the same in both
 476          * s10 and native Solaris.  Just assign the first word.
 477          */
 478         nativeset.__sigbits[0] = set->__sigbits[0];
 479         nativeset.__sigbits[1] = 0;
 480         nativeset.__sigbits[2] = 0;
 481         nativeset.__sigbits[3] = 0;
 482 
 483         /*
 484          * Copy the remainder of the initial set of common signals.
 485          */
 486         for (s10sig = 33; s10sig < S10_SIGRTMIN; s10sig++)
 487                 if (sigismember(set, s10sig))
 488                         sigaddset(&nativeset, s10sig);
 489 
 490         /*
 491          * Convert any S10 RT signals to their native values.
 492          */
 493         for (s10sig = S10_SIGRTMIN, nativesig = _SIGRTMIN;
 494             s10sig <= S10_SIGRTMAX && nativesig <= _SIGRTMAX;
 495             s10sig++, nativesig++) {
 496                 if (sigismember(set, s10sig))
 497                         sigaddset(&nativeset, nativesig);
 498         }
 499 
 500         *set = nativeset;
 501 }
 502 
 503 int
 504 _init(void)
 505 {
 506         int err;
 507 
 508         /*
 509          * Set up the table indicating which system calls we want to
 510          * interpose on.  We should probably build this automatically from
 511          * a list of system calls that is shared with the user-space
 512          * library.
 513          */
 514         s10_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
 515         s10_emulation_table[S10_SYS_forkall] = 1;               /*   2 */
 516         s10_emulation_table[S10_SYS_open] = 1;                  /*   5 */
 517         s10_emulation_table[S10_SYS_wait] = 1;                  /*   7 */
 518         s10_emulation_table[S10_SYS_creat] = 1;                 /*   8 */
 519         s10_emulation_table[S10_SYS_link] = 1;                  /*   9 */
 520         s10_emulation_table[S10_SYS_unlink] = 1;                /*  10 */
 521         s10_emulation_table[S10_SYS_exec] = 1;                  /*  11 */
 522         s10_emulation_table[S10_SYS_mknod] = 1;                 /*  14 */
 523         s10_emulation_table[S10_SYS_chmod] = 1;                 /*  15 */
 524         s10_emulation_table[S10_SYS_chown] = 1;                 /*  16 */
 525         s10_emulation_table[S10_SYS_stat] = 1;                  /*  18 */
 526         s10_emulation_table[S10_SYS_umount] = 1;                /*  22 */
 527         s10_emulation_table[S10_SYS_fstat] = 1;                 /*  28 */
 528         s10_emulation_table[S10_SYS_utime] = 1;                 /*  30 */
 529         s10_emulation_table[S10_SYS_access] = 1;                /*  33 */
 530         s10_emulation_table[SYS_kill] = 1;                      /*  37 */
 531         s10_emulation_table[S10_SYS_dup] = 1;                   /*  41 */
 532         s10_emulation_table[S10_SYS_pipe] = 1;                  /*  42 */
 533         s10_emulation_table[SYS_ioctl] = 1;                     /*  54 */
 534         s10_emulation_table[SYS_execve] = 1;                    /*  59 */
 535         s10_emulation_table[SYS_acctctl] = 1;                   /*  71 */
 536         s10_emulation_table[S10_SYS_issetugid] = 1;             /*  75 */
 537         s10_emulation_table[S10_SYS_fsat] = 1;                  /*  76 */
 538         s10_emulation_table[S10_SYS_rmdir] = 1;                 /*  79 */
 539         s10_emulation_table[S10_SYS_mkdir] = 1;                 /*  80 */
 540         s10_emulation_table[SYS_getdents] = 1;                  /*  81 */
 541         s10_emulation_table[S10_SYS_poll] = 1;                  /*  87 */
 542         s10_emulation_table[S10_SYS_lstat] = 1;                 /*  88 */
 543         s10_emulation_table[S10_SYS_symlink] = 1;               /*  89 */
 544         s10_emulation_table[S10_SYS_readlink] = 1;              /*  90 */
 545         s10_emulation_table[S10_SYS_fchmod] = 1;                /*  93 */
 546         s10_emulation_table[S10_SYS_fchown] = 1;                /*  94 */
 547         s10_emulation_table[SYS_sigprocmask] = 1;               /*  95 */
 548         s10_emulation_table[SYS_sigsuspend] = 1;                /*  96 */
 549         s10_emulation_table[SYS_sigaction] = 1;                 /*  98 */
 550         s10_emulation_table[SYS_sigpending] = 1;                /*  99 */
 551         s10_emulation_table[SYS_waitid] = 1;                    /* 107 */
 552         s10_emulation_table[SYS_sigsendsys] = 1;                /* 108 */
 553 #if defined(__x86)
 554         s10_emulation_table[S10_SYS_xstat] = 1;                 /* 123 */
 555         s10_emulation_table[S10_SYS_lxstat] = 1;                /* 124 */
 556         s10_emulation_table[S10_SYS_fxstat] = 1;                /* 125 */
 557         s10_emulation_table[S10_SYS_xmknod] = 1;                /* 126 */
 558 #endif
 559         s10_emulation_table[S10_SYS_lchown] = 1;                /* 130 */
 560         s10_emulation_table[S10_SYS_rename] = 1;                /* 134 */
 561         s10_emulation_table[SYS_uname] = 1;                     /* 135 */
 562         s10_emulation_table[SYS_sysconfig] = 1;                 /* 137 */
 563         s10_emulation_table[SYS_systeminfo] = 1;                /* 139 */
 564         s10_emulation_table[S10_SYS_fork1] = 1;                 /* 143 */
 565         s10_emulation_table[SYS_sigtimedwait] = 1;              /* 144 */
 566         s10_emulation_table[S10_SYS_lwp_sema_wait] = 1;         /* 147 */
 567         s10_emulation_table[S10_SYS_utimes] = 1;                /* 154 */
 568         s10_emulation_table[SYS_lwp_create] = 1;                /* 159 */
 569         s10_emulation_table[SYS_lwp_kill] = 1;                  /* 163 */
 570         s10_emulation_table[SYS_lwp_sigmask] = 1;               /* 165 */
 571 #if defined(__amd64)
 572         s10_emulation_table[SYS_lwp_private] = 1;               /* 166 */
 573 #endif  /* __amd64 */
 574         s10_emulation_table[S10_SYS_lwp_mutex_lock] = 1;        /* 169 */
 575         s10_emulation_table[SYS_pwrite] = 1;                    /* 174 */
 576         s10_emulation_table[SYS_acl] = 1;                       /* 185 */
 577         s10_emulation_table[SYS_auditsys] = 1;                  /* 186 */
 578         s10_emulation_table[SYS_sigqueue] = 1;                  /* 190 */
 579         s10_emulation_table[SYS_facl] = 1;                      /* 200 */
 580         s10_emulation_table[SYS_signotify] = 1;                 /* 205 */
 581         s10_emulation_table[SYS_lwp_mutex_timedlock] = 1;       /* 210 */
 582         s10_emulation_table[SYS_getdents64] = 1;                /* 213 */
 583         s10_emulation_table[S10_SYS_stat64] = 1;                /* 215 */
 584         s10_emulation_table[S10_SYS_lstat64] = 1;               /* 216 */
 585         s10_emulation_table[S10_SYS_fstat64] = 1;               /* 217 */
 586         s10_emulation_table[SYS_pwrite64] = 1;                  /* 223 */
 587         s10_emulation_table[S10_SYS_creat64] = 1;               /* 224 */
 588         s10_emulation_table[S10_SYS_open64] = 1;                /* 225 */
 589         s10_emulation_table[SYS_zone] = 1;                      /* 227 */
 590         s10_emulation_table[S10_SYS_so_socket] = 1;             /* 230 */
 591         s10_emulation_table[S10_SYS_accept] = 1;                /* 234 */
 592         s10_emulation_table[SYS_lwp_mutex_trylock] = 1;         /* 251 */
 593 
 594         err = mod_install(&modlinkage);
 595         if (err) {
 596                 cmn_err(CE_WARN, "Couldn't install brand module");
 597                 kmem_free(s10_emulation_table, NSYSCALL);
 598         }
 599 
 600         return (err);
 601 }
 602 
 603 int
 604 _info(struct modinfo *modinfop)
 605 {
 606         return (mod_info(&modlinkage, modinfop));
 607 }
 608 
 609 int
 610 _fini(void)
 611 {
 612         return (brand_solaris_fini(&s10_emulation_table, &modlinkage,
 613             &s10_brand));
 614 }