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 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/syscall.h>
  29 #include <sys/utsname.h>
  30 #include <sys/inttypes.h>
  31 #include <sys/stat.h>
  32 #include <sys/mman.h>
  33 #include <sys/fstyp.h>
  34 #include <sys/fsid.h>
  35 #include <sys/systm.h>
  36 #include <sys/auxv.h>
  37 #include <sys/frame.h>
  38 #include <sys/brand.h>
  39 
  40 #include <assert.h>
  41 #include <stdio.h>
  42 #include <stdarg.h>
  43 #include <stdlib.h>
  44 #include <strings.h>
  45 #include <unistd.h>
  46 #include <errno.h>
  47 #include <syslog.h>
  48 #include <signal.h>
  49 #include <fcntl.h>
  50 #include <synch.h>
  51 #include <libelf.h>
  52 #include <libgen.h>
  53 #include <pthread.h>
  54 #include <utime.h>
  55 #include <dirent.h>
  56 #include <ucontext.h>
  57 #include <libintl.h>
  58 #include <locale.h>
  59 
  60 #include <sys/lx_misc.h>
  61 #include <sys/lx_debug.h>
  62 #include <sys/lx_brand.h>
  63 #include <sys/lx_types.h>
  64 #include <sys/lx_stat.h>
  65 #include <sys/lx_statfs.h>
  66 #include <sys/lx_ioctl.h>
  67 #include <sys/lx_signal.h>
  68 #include <sys/lx_syscall.h>
  69 #include <sys/lx_thread.h>
  70 #include <sys/lx_thunk_server.h>
  71 
  72 /*
  73  * Map solaris errno to the linux equivalent.
  74  */
  75 static int stol_errno[] = {
  76         0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
  77         10,  11,  12,  13,  14,  15,  16,  17,  18,  19,
  78         20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
  79         30,  31,  32,  33,  34,  42,  43,  44,  45,  46,
  80         47,  48,  49,  50,  51,  35,  47,  22,  38,  22, /* 49 */
  81         52,  53,  54,  55,  56,  57,  58,  59,  22,  22,
  82         61,  61,  62,  63,  64,  65,  66,  67,  68,  69,
  83         70,  71,  22,  22,  72,  22,  22,  74,  36,  75,
  84         76,  77,  78,  79,  80,  81,  82,  83,  84,  38,
  85         40,  85,  86,  39,  87,  88,  89,  90,  91,  92, /* 99 */
  86         22,  22,  22,  22,  22,  22,  22,  22,  22,  22,
  87         22,  22,  22,  22,  22,  22,  22,  22,  22,  22,
  88         93,  94,  95,  96,  97,  98,  99, 100, 101, 102,
  89         103, 104, 105, 106, 107,  22,  22,  22,  22,  22,
  90         22,  22,  22, 108, 109, 110, 111, 112, 113, 114, /* 149 */
  91         115, 116
  92 };
  93 
  94 char lx_release[128];
  95 
  96 /*
  97  * Map a linux locale ending string to the solaris equivalent.
  98  */
  99 struct lx_locale_ending {
 100         const char      *linux_end;     /* linux ending string */
 101         const char      *solaris_end;   /* to transform with this string */
 102         int             le_size;        /* linux ending string length */
 103         int             se_size;        /* solaris ending string length */
 104 };
 105 
 106 #define l2s_locale(lname, sname) \
 107         {(lname), (sname), sizeof ((lname)) - 1, sizeof ((sname)) - 1}
 108 
 109 /*static struct lx_locale_ending lx_locales[] = {
 110         l2s_locale(".utf8",      ".UTF-8"),
 111         l2s_locale(".utf8@euro", ".UTF-8"),
 112         l2s_locale("@euro",      ".ISO8859-15"),
 113         l2s_locale(".iso885915", ".ISO8859-15"),
 114         l2s_locale(".euckr",     ".EUC"),
 115         l2s_locale(".euctw",     ".EUC"),
 116         l2s_locale(".koi8r",     ".KOI8-R"),
 117         l2s_locale(".gb18030",   ".GB18030"),
 118         l2s_locale(".gbk",       ".GBK"),
 119         l2s_locale("@cyrillic",  ".ISO8859-5")
 120 };*/
 121 
 122 #define MAXLOCALENAMELEN        30
 123 #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
 124 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
 125 #endif
 126 
 127 /*
 128  * This flag is part of the registration with the in-kernel brand module. It's
 129  * used in lx_handler() to determine if we should go back into the kernel after
 130  * a system call in case the kernel needs to perform some post-syscall work
 131  * like tracing for example.
 132  */
 133 int lx_traceflag;
 134 
 135 #define NOSYS_NULL              1
 136 #define NOSYS_NO_EQUIV          2
 137 #define NOSYS_KERNEL            3
 138 #define NOSYS_UNDOC             4
 139 #define NOSYS_OBSOLETE          5
 140 
 141 /*
 142  * SYS_PASSTHRU denotes a system call we can just call on behalf of the
 143  * branded process without having to translate the arguments.
 144  *
 145  * The restriction on this is that the call in question MUST return -1 to
 146  * denote an error.
 147  */
 148 #define SYS_PASSTHRU            5
 149 
 150 static char *nosys_msgs[] = {
 151         "Either not yet done, or we haven't come up with an excuse",
 152         "No such Linux system call",
 153         "No equivalent Solaris functionality",
 154         "Reads/modifies Linux kernel state",
 155         "Undocumented and/or rarely used system call",
 156         "Unsupported, obsolete system call"
 157 };
 158 
 159 struct lx_sysent {
 160         char    *sy_name;
 161         int     (*sy_callc)();
 162         char    sy_flags;
 163         char    sy_narg;
 164 };
 165 
 166 static struct lx_sysent sysents[LX_NSYSCALLS + 1];
 167 
 168 static uintptr_t stack_bottom;
 169 
 170 int lx_install = 0;             /* install mode enabled if non-zero */
 171 boolean_t lx_is_rpm = B_FALSE;
 172 int lx_rpm_delay = 1;
 173 int lx_strict = 0;              /* "strict" mode enabled if non-zero */
 174 int lx_verbose = 0;             /* verbose mode enabled if non-zero */
 175 int lx_debug_enabled = 0;       /* debugging output enabled if non-zero */
 176 
 177 pid_t zoneinit_pid;             /* zone init PID */
 178 
 179 thread_key_t lx_tsd_key;
 180 
 181 int
 182 uucopy_unsafe(const void *src, void *dst, size_t n)
 183 {
 184         bcopy(src, dst, n);
 185         return (0);
 186 }
 187 
 188 int
 189 uucopystr_unsafe(const void *src, void *dst, size_t n)
 190 {
 191         (void) strncpy((char *)src, dst, n);
 192         return (0);
 193 }
 194 
 195 static void
 196 i_lx_msg(int fd, char *msg, va_list ap)
 197 {
 198         int     i;
 199         char    buf[LX_MSG_MAXLEN];
 200 
 201         /* LINTED [possible expansion issues] */
 202         i = vsnprintf(buf, sizeof (buf), msg, ap);
 203         buf[LX_MSG_MAXLEN - 1] = '\0';
 204         if (i == -1)
 205                 return;
 206 
 207         /* if debugging is enabled, send this message to debug output */
 208         if (lx_debug_enabled != 0)
 209                 lx_debug(buf);
 210 
 211         /*
 212          * If we are trying to print to stderr, we also want to send the
 213          * message to syslog.
 214          */
 215         if (fd == 2) {
 216                 syslog(LOG_ERR, "%s", buf);
 217 
 218                 /*
 219                  * We let the user choose whether or not to see these
 220                  * messages on the console.
 221                  */
 222                 if (lx_verbose == 0)
 223                         return;
 224         }
 225 
 226         /* we retry in case of EINTR */
 227         do {
 228                 i = write(fd, buf, strlen(buf));
 229         } while ((i == -1) && (errno == EINTR));
 230 }
 231 
 232 /*PRINTFLIKE1*/
 233 void
 234 lx_err(char *msg, ...)
 235 {
 236         va_list ap;
 237 
 238         assert(msg != NULL);
 239 
 240         va_start(ap, msg);
 241         i_lx_msg(STDERR_FILENO, msg, ap);
 242         va_end(ap);
 243 }
 244 
 245 /*
 246  * This is just a non-zero exit value which also isn't one that would allow
 247  * us to easily detect if a branded process exited because of a recursive
 248  * fatal error.
 249  */
 250 #define LX_ERR_FATAL    42
 251 
 252 /*
 253  * Our own custom version of abort(), this routine will be used in place
 254  * of the one located in libc.  The primary difference is that this version
 255  * will first reset the signal handler for SIGABRT to SIG_DFL, ensuring the
 256  * SIGABRT sent causes us to dump core and is not caught by a user program.
 257  */
 258 void
 259 abort(void)
 260 {
 261         static int aborting = 0;
 262 
 263         struct sigaction sa;
 264         sigset_t sigmask;
 265 
 266         /* watch out for recursive calls to this function */
 267         if (aborting != 0)
 268                 exit(LX_ERR_FATAL);
 269 
 270         aborting = 1;
 271 
 272         /*
 273          * Block all signals here to avoid taking any signals while exiting
 274          * in an effort to avoid any strange user interaction with our death.
 275          */
 276         (void) sigfillset(&sigmask);
 277         (void) sigprocmask(SIG_BLOCK, &sigmask, NULL);
 278 
 279         /*
 280          * Our own version of abort(3C) that we know will never call
 281          * a user-installed SIGABRT handler first.  We WANT to die.
 282          *
 283          * Do this by resetting the handler to SIG_DFL, and releasing any
 284          * held SIGABRTs.
 285          *
 286          * If no SIGABRTs are pending, send ourselves one.
 287          *
 288          * The while loop is a bit of overkill, but abort(3C) does it to
 289          * assure it never returns so we will as well.
 290          */
 291         (void) sigemptyset(&sa.sa_mask);
 292         sa.sa_sigaction = SIG_DFL;
 293         sa.sa_flags = 0;
 294 
 295         for (;;) {
 296                 (void) sigaction(SIGABRT, &sa, NULL);
 297                 (void) sigrelse(SIGABRT);
 298                 (void) thr_kill(thr_self(), SIGABRT);
 299         }
 300 
 301         /*NOTREACHED*/
 302 }
 303 
 304 /*PRINTFLIKE1*/
 305 void
 306 lx_msg(char *msg, ...)
 307 {
 308         va_list ap;
 309 
 310         assert(msg != NULL);
 311         va_start(ap, msg);
 312         i_lx_msg(STDOUT_FILENO, msg, ap);
 313         va_end(ap);
 314 }
 315 
 316 /*PRINTFLIKE1*/
 317 void
 318 lx_err_fatal(char *msg, ...)
 319 {
 320         va_list ap;
 321 
 322         assert(msg != NULL);
 323 
 324         va_start(ap, msg);
 325         i_lx_msg(STDERR_FILENO, msg, ap);
 326         va_end(ap);
 327         abort();
 328 }
 329 
 330 /*
 331  * See if it is safe to alloca() sz bytes.  Return 1 for yes, 0 for no.
 332  */
 333 int
 334 lx_check_alloca(size_t sz)
 335 {
 336         uintptr_t sp = (uintptr_t)&sz;
 337         uintptr_t end = sp - sz;
 338 
 339         return ((end < sp) && (end >= stack_bottom));
 340 }
 341 
 342 /*PRINTFLIKE1*/
 343 void
 344 lx_unsupported(char *msg, ...)
 345 {
 346         va_list ap;
 347 
 348         assert(msg != NULL);
 349 
 350         /* send the msg to the error stream */
 351         va_start(ap, msg);
 352         i_lx_msg(STDERR_FILENO, msg, ap);
 353         va_end(ap);
 354 
 355         /*
 356          * If the user doesn't trust the application to responsibly
 357          * handle ENOTSUP, we kill the application.
 358          */
 359         if (lx_strict)
 360                 (void) kill(getpid(), SIGSYS);
 361 }
 362 
 363 extern void lx_runexe(void *argv, int32_t entry);
 364 int lx_init(int argc, char *argv[], char *envp[]);
 365 
 366 static int
 367 lx_emulate_args(lx_regs_t *rp, struct lx_sysent *s, uintptr_t *args)
 368 {
 369         /*
 370          * If the system call takes 6 args, then libc has stashed them in
 371          * memory at the address contained in %ebx. Except for some syscalls
 372          * which store the 6th argument in %ebp.
 373          */
 374         if (s->sy_narg == 6 && !(s->sy_flags & EBP_HAS_ARG6)) {
 375                 if (uucopy((void *)rp->lxr_ebx, args,
 376                     sizeof (args[0]) * 6) != 0)
 377                         return (-stol_errno[errno]);
 378         } else {
 379                 args[0] = rp->lxr_ebx;
 380                 args[1] = rp->lxr_ecx;
 381                 args[2] = rp->lxr_edx;
 382                 args[3] = rp->lxr_esi;
 383                 args[4] = rp->lxr_edi;
 384                 args[5] = rp->lxr_ebp;
 385         }
 386 
 387         return (0);
 388 }
 389 
 390 void
 391 lx_emulate(lx_regs_t *rp)
 392 {
 393         struct lx_sysent *s;
 394         uintptr_t args[6];
 395         uintptr_t gs = rp->lxr_gs & 0xffff;      /* %gs is only 16 bits */
 396         int syscall_num, ret;
 397 
 398         syscall_num = rp->lxr_eax;
 399 
 400         /*
 401          * lx_brand_int80_callback() ensures that the syscall_num is sane;
 402          * Use it as is.
 403          */
 404         assert(syscall_num >= 0);
 405         assert(syscall_num < (sizeof (sysents) / sizeof (sysents[0])));
 406         s = &sysents[syscall_num];
 407 
 408         if ((ret = lx_emulate_args(rp, s, args)) != 0)
 409                 goto out;
 410 
 411         /*
 412          * If the tracing flag is enabled we call into the brand-specific
 413          * kernel module to handle the tracing activity (DTrace or ptrace).
 414          * It would be tempting to perform DTrace activity in the brand
 415          * module's syscall trap callback, rather than having to return
 416          * to the kernel here, but -- since argument encoding can vary
 417          * according to the specific system call -- that would require
 418          * replicating the knowledge of argument decoding in the kernel
 419          * module as well as here in the brand library.
 420          */
 421         if (lx_traceflag != 0) {
 422                 /*
 423                  * Part of the ptrace "interface" is that on syscall entry
 424                  * %eax should be reported as -ENOSYS while the orig_eax
 425                  * field of the user structure needs to contain the actual
 426                  * system call number. If we end up stopping here, the
 427                  * controlling process will dig the lx_regs_t structure out of
 428                  * our stack.
 429                  */
 430                 rp->lxr_orig_eax = syscall_num;
 431                 rp->lxr_eax = -stol_errno[ENOSYS];
 432 
 433                 (void) syscall(SYS_brand, B_SYSENTRY, syscall_num, args);
 434 
 435                 /*
 436                  * The external tracer may have modified the arguments to this
 437                  * system call. Refresh the argument cache to account for this.
 438                  */
 439                 if ((ret = lx_emulate_args(rp, s, args)) != 0)
 440                         goto out;
 441         }
 442 
 443         if (s->sy_callc == NULL) {
 444                 lx_unsupported(gettext("unimplemented syscall #%d (%s): %s\n"),
 445                     syscall_num, s->sy_name, nosys_msgs[(int)s->sy_flags]);
 446                 ret = -stol_errno[ENOTSUP];
 447                 goto out;
 448         }
 449 
 450         if (lx_debug_enabled != 0) {
 451                 const char *fmt = NULL;
 452 
 453                 switch (s->sy_narg) {
 454                 case 0:
 455                         fmt = "calling %s()";
 456                         break;
 457                 case 1:
 458                         fmt = "calling %s(0x%p)";
 459                         break;
 460                 case 2:
 461                         fmt = "calling %s(0x%p, 0x%p)";
 462                         break;
 463                 case 3:
 464                         fmt = "calling %s(0x%p, 0x%p, 0x%p)";
 465                         break;
 466                 case 4:
 467                         fmt = "calling %s(0x%p, 0x%p, 0x%p, 0x%p)";
 468                         break;
 469                 case 5:
 470                         fmt = "calling %s(0x%p, 0x%p, 0x%p, 0x%p, 0x%p)";
 471                         break;
 472                 case 6:
 473                         fmt = "calling %s(0x%p, 0x%p, 0x%p, 0x%p, 0x%p, 0x%p)";
 474                         break;
 475                 }
 476 
 477                 lx_debug(fmt, s->sy_name, args[0], args[1], args[2], args[3],
 478                     args[4], args[5]);
 479         }
 480 
 481         if (gs != LWPGS_SEL) {
 482                 lx_tsd_t *lx_tsd;
 483 
 484                 /*
 485                  * While a %gs of 0 is technically legal (as long as the
 486                  * application never dereferences memory using %gs), Solaris
 487                  * has its own ideas as to how a zero %gs should be handled in
 488                  * _update_sregs(), such that any 32-bit user process with a
 489                  * %gs of zero running on a system with a 64-bit kernel will
 490                  * have its %gs hidden base register stomped on on return from
 491                  * a system call, leaving an incorrect base address in place
 492                  * until the next time %gs is actually reloaded (forcing a
 493                  * reload of the base address from the appropriate descriptor
 494                  * table.)
 495                  *
 496                  * Of course the kernel will once again stomp on THAT base
 497                  * address when returning from a system call, resulting in an
 498                  * an application segmentation fault.
 499                  *
 500                  * To avoid this situation, disallow a save of a zero %gs
 501                  * here in order to try and capture any Linux process that
 502                  * attempts to make a syscall with a zero %gs installed.
 503                  */
 504                 assert(gs != 0);
 505 
 506                 if ((ret = thr_getspecific(lx_tsd_key,
 507                     (void **)&lx_tsd)) != 0)
 508                         lx_err_fatal(gettext(
 509                             "%s: unable to read thread-specific data: %s"),
 510                             "lx_emulate", strerror(ret));
 511 
 512                 assert(lx_tsd != 0);
 513 
 514                 lx_tsd->lxtsd_gs = gs;
 515 
 516                 lx_debug("lx_emulate(): gsp 0x%p, saved gs: 0x%x", lx_tsd, gs);
 517         }
 518 
 519         if (s->sy_flags == SYS_PASSTHRU)
 520                 lx_debug("\tCalling Solaris %s()", s->sy_name);
 521 
 522         ret = s->sy_callc(args[0], args[1], args[2], args[3], args[4], args[5]);
 523 
 524         if (ret > -65536 && ret < 65536)
 525                 lx_debug("\t= %d", ret);
 526         else
 527                 lx_debug("\t= 0x%x", ret);
 528 
 529         if ((s->sy_flags == SYS_PASSTHRU) && (ret == -1)) {
 530                 ret = -stol_errno[errno];
 531         } else {
 532                 /*
 533                  * If the return value is between -4096 and 0 we assume it's an
 534                  * error, so we translate the Solaris error number into the
 535                  * Linux equivalent.
 536                  */
 537                 if (ret < 0 && ret > -4096) {
 538                         if (-ret >=
 539                             sizeof (stol_errno) / sizeof (stol_errno[0])) {
 540                                 lx_debug("Invalid return value from emulated "
 541                                     "syscall %d (%s): %d\n",
 542                                     syscall_num, s->sy_name, ret);
 543                                 assert(0);
 544                         }
 545 
 546                         ret = -stol_errno[-ret];
 547                 }
 548         }
 549 
 550 out:
 551         /*
 552          * %eax holds the return code from the system call.
 553          */
 554         rp->lxr_eax = ret;
 555 
 556         /*
 557          * If the trace flag is set, bounce into the kernel to let it do
 558          * any necessary tracing (DTrace or ptrace).
 559          */
 560         if (lx_traceflag != 0) {
 561                 rp->lxr_orig_eax = syscall_num;
 562                 (void) syscall(SYS_brand, B_SYSRETURN, syscall_num, ret);
 563         }
 564 }
 565 
 566 /* Transform the Linux locale name to make it look like a Solaris locale name */
 567 /* static const char *
 568 lx_translate_locale(char *translated_name_mem, int mem_size)
 569 {
 570         char *loc;
 571         int i;
 572         size_t len;
 573 
 574         if ((loc = getenv("LC_ALL")) == NULL)
 575                 if ((loc = getenv("LANG")) == NULL)
 576                         return ("C");
 577 
 578         if (strlcpy(translated_name_mem, loc, mem_size) >= mem_size)
 579                 return ("");
 580 
 581         len = strlen(loc);
 582 
 583         // replace the end of the locale name if it's a known pattern 
 584         for (i = 0; i < sizeof (lx_locales) / sizeof (struct lx_locale_ending);
 585             i++) {
 586                 if (len <= lx_locales[i].le_size)
 587                         continue;
 588 
 589                 if (strncmp(loc + len - lx_locales[i].le_size,
 590                     lx_locales[i].linux_end, lx_locales[i].le_size))
 591                         continue; // don't match 
 592 
 593                 if (len - lx_locales[i].le_size + lx_locales[i].se_size
 594                     >= mem_size)
 595                         return ("C"); // size too small for the new name 
 596 
 597                 (void) strlcpy(translated_name_mem + len -
 598                     lx_locales[i].le_size, lx_locales[i].solaris_end,
 599                     lx_locales[i].se_size + 1);
 600 
 601                 return ((const char *)translated_name_mem);
 602         }
 603 
 604         // no match 
 605         return ("");
 606 } */
 607 
 608 static void
 609 lx_close_fh(FILE *file)
 610 {
 611         int fd, fd_new;
 612 
 613         if (file == NULL)
 614                 return;
 615 
 616         if ((fd = fileno(file)) < 0)
 617                 return;
 618 
 619         fd_new = dup(fd);
 620         if (fd_new == -1)
 621                 return;
 622 
 623         (void) fclose(file);
 624         (void) dup2(fd_new, fd);
 625         (void) close(fd_new);
 626 }
 627 
 628 
 629 extern int set_l10n_alternate_root(char *path);
 630 
 631 /*ARGSUSED*/
 632 int
 633 lx_init(int argc, char *argv[], char *envp[])
 634 {
 635         char            *r;
 636         auxv_t          *ap;
 637         int             *p, err;
 638         lx_elf_data_t   edp;
 639         lx_brand_registration_t reg;
 640 /*      char            locale_translated_name[MAXLOCALENAMELEN]; */
 641         static lx_tsd_t lx_tsd;
 642 
 643 
 644         /* Look up the PID that serves as init for this zone */
 645         if ((err = lx_lpid_to_spid(1, &zoneinit_pid)) < 0)
 646                 lx_err_fatal(gettext(
 647                     "Unable to find PID for zone init process: %s"),
 648                     strerror(err));
 649 
 650         /*
 651          * Ubuntu init will fail if its TERM environment variable is not set
 652          * so if we are running init, and TERM is not set, we set term and
 653          * reexec so that the new environment variable is propagated to the
 654          * linux application stack.
 655          */
 656         if ((getpid() == zoneinit_pid) && (getenv("TERM") == NULL)) {
 657                 if (setenv("TERM", "vt100", 1) < 0 || execv(argv[0], argv) < 0)
 658                         lx_err_fatal(gettext("failed to set TERM"));
 659         }
 660 /*
 661         if ((set_l10n_alternate_root("/native") == 0) &&
 662             (setlocale(LC_ALL, lx_translate_locale(locale_translated_name,
 663             sizeof (locale_translated_name))) != NULL) &&
 664             (bindtextdomain(TEXT_DOMAIN, "/native/usr/lib/locale") != NULL)) {
 665                 (void) textdomain(TEXT_DOMAIN);
 666         }
 667 */
 668         stack_bottom = 2 * sysconf(_SC_PAGESIZE);
 669 
 670         /*
 671          * We need to shutdown all libc stdio.  libc stdio normally goes to
 672          * file descriptors, but since we're actually part of a linux
 673          * process we don't own these file descriptors and we can't make
 674          * any assumptions about their state.
 675          */
 676         lx_close_fh(stdin);
 677         lx_close_fh(stdout);
 678         lx_close_fh(stderr);
 679 
 680         lx_debug_init();
 681 
 682         r = getenv("LX_RELEASE");
 683         if (r == NULL) {
 684                 if (lx_get_kern_version() == LX_KERN_2_6)
 685                         (void) strlcpy(lx_release, LX_UNAME_RELEASE_2_6,
 686                             sizeof (lx_release));
 687                 else
 688                         (void) strlcpy(lx_release, LX_UNAME_RELEASE_2_4,
 689                             sizeof (lx_release));
 690         } else {
 691                 (void) strlcpy(lx_release, r, 128);
 692         }
 693 
 694         lx_debug("lx_release: %s\n", lx_release);
 695 
 696         /*
 697          * Should we kill an application that attempts an unimplemented
 698          * system call?
 699          */
 700         if (getenv("LX_STRICT") != NULL) {
 701                 lx_strict = 1;
 702                 lx_debug("STRICT mode enabled.\n");
 703         }
 704 
 705         /*
 706          * Are we in install mode?
 707          */
 708         if (getenv("LX_INSTALL") != NULL) {
 709                 lx_install = 1;
 710                 lx_debug("INSTALL mode enabled.\n");
 711         }
 712 
 713         /*
 714          * Should we attempt to send messages to the screen?
 715          */
 716         if (getenv("LX_VERBOSE") != NULL) {
 717                 lx_verbose = 1;
 718                 lx_debug("VERBOSE mode enabled.\n");
 719         }
 720 
 721         lx_debug("executing linux process: %s", argv[0]);
 722         lx_debug("branding myself and setting handler to 0x%p",
 723             (void *)lx_handler_table);
 724 
 725         /*
 726          * The version of rpm that ships with CentOS/RHEL 3.x has a race
 727          * condition in it.  If it creates a child process to run a
 728          * post-install script, and that child process completes too
 729          * quickly, it will disappear before the parent notices.  This
 730          * causes the parent to hang forever waiting for the already dead
 731          * child to die.  I'm sure there's a Lazarus joke buried in here
 732          * somewhere.
 733          *
 734          * Anyway, as a workaround, we make every child of an 'rpm' process
 735          * sleep for 1 second, giving the parent a chance to enter its
 736          * wait-for-the-child-to-die loop.  Thay may be the hackiest trick
 737          * in all of our Linux emulation code - and that's saying
 738          * something.
 739          */
 740         if (strcmp("rpm", basename(argv[0])) == NULL)
 741                 lx_is_rpm = B_TRUE;
 742 
 743         reg.lxbr_version = LX_VERSION;
 744         reg.lxbr_handler = (void *)&lx_handler_table;
 745         reg.lxbr_tracehandler = (void *)&lx_handler_trace_table;
 746         reg.lxbr_traceflag = &lx_traceflag;
 747 
 748         /*
 749          * Register the address of the user-space handler with the lx
 750          * brand module.
 751          */
 752         if (syscall(SYS_brand, B_REGISTER, &reg))
 753                 lx_err_fatal(gettext("failed to brand the process"));
 754 
 755         /*
 756          * Download data about the lx executable from the kernel.
 757          */
 758         if (syscall(SYS_brand, B_ELFDATA, (void *)&edp))
 759                 lx_err_fatal(gettext(
 760                     "failed to get required ELF data from the kernel"));
 761 
 762         if (lx_ioctl_init() != 0)
 763                 lx_err_fatal(gettext("failed to setup the %s translator"),
 764                     "ioctl");
 765 
 766         if (lx_stat_init() != 0)
 767                 lx_err_fatal(gettext("failed to setup the %s translator"),
 768                     "stat");
 769 
 770         if (lx_statfs_init() != 0)
 771                 lx_err_fatal(gettext("failed to setup the %s translator"),
 772                     "statfs");
 773 
 774         /*
 775          * Find the aux vector on the stack.
 776          */
 777         p = (int *)envp;
 778         while (*p != NULL)
 779                 p++;
 780         /*
 781          * p is now pointing at the 0 word after the environ pointers. After
 782          * that is the aux vectors.
 783          */
 784         p++;
 785         for (ap = (auxv_t *)p; ap->a_type != 0; ap++) {
 786                 switch (ap->a_type) {
 787                         case AT_BASE:
 788                                 ap->a_un.a_val = edp.ed_base;
 789                                 break;
 790                         case AT_ENTRY:
 791                                 ap->a_un.a_val = edp.ed_entry;
 792                                 break;
 793                         case AT_PHDR:
 794                                 ap->a_un.a_val = edp.ed_phdr;
 795                                 break;
 796                         case AT_PHENT:
 797                                 ap->a_un.a_val = edp.ed_phent;
 798                                 break;
 799                         case AT_PHNUM:
 800                                 ap->a_un.a_val = edp.ed_phnum;
 801                                 break;
 802                         default:
 803                                 break;
 804                 }
 805         }
 806 
 807         /* Do any thunk server initalization. */
 808         lxt_server_init(argc, argv);
 809 
 810         /* Setup signal handler information. */
 811         if (lx_siginit())
 812                 lx_err_fatal(gettext(
 813                     "failed to initialize lx signals for the branded process"));
 814 
 815         /* Setup thread-specific data area for managing linux threads. */
 816         if ((err = thr_keycreate(&lx_tsd_key, NULL)) != 0)
 817                 lx_err_fatal(
 818                     gettext("%s failed: %s"), "thr_keycreate(lx_tsd_key)",
 819                     strerror(err));
 820 
 821         lx_debug("thr_keycreate created lx_tsd_key (%d)", lx_tsd_key);
 822 
 823         /* Initialize the thread specific data for this thread. */
 824         bzero(&lx_tsd, sizeof (lx_tsd));
 825         lx_tsd.lxtsd_gs = LWPGS_SEL;
 826 
 827         if ((err = thr_setspecific(lx_tsd_key, &lx_tsd)) != 0)
 828                 lx_err_fatal(gettext(
 829                     "Unable to initialize thread-specific data: %s"),
 830                     strerror(err));
 831 
 832         /*
 833          * Save the current context of this thread.
 834          * We'll restore this context when this thread attempts to exit.
 835          */
 836         if (getcontext(&lx_tsd.lxtsd_exit_context) != 0)
 837                 lx_err_fatal(gettext(
 838                     "Unable to initialize thread-specific exit context: %s"),
 839                     strerror(errno));
 840 
 841         if (lx_tsd.lxtsd_exit == 0) {
 842                 lx_runexe(argv, edp.ed_ldentry);
 843                 /* lx_runexe() never returns. */
 844                 assert(0);
 845         }
 846 
 847         /*
 848          * We are here because the Linux application called the exit() or
 849          * exit_group() system call.  In turn the brand library did a
 850          * setcontext() to jump to the thread context state we saved above.
 851          */
 852         if (lx_tsd.lxtsd_exit == 1)
 853                 thr_exit((void *)lx_tsd.lxtsd_exit_status);
 854         else
 855                 exit(lx_tsd.lxtsd_exit_status);
 856 
 857         assert(0);
 858 
 859         /*NOTREACHED*/
 860         return (0);
 861 }
 862 
 863 /*
 864  * Walk back through the stack until we find the lx_emulate() frame.
 865  */
 866 lx_regs_t *
 867 lx_syscall_regs(void)
 868 {
 869         /* LINTED - alignment */
 870         struct frame *fr = (struct frame *)_getfp();
 871 
 872         while (fr->fr_savpc != (uintptr_t)&lx_emulate_done) {
 873                 fr = (struct frame *)fr->fr_savfp;
 874                 assert(fr->fr_savpc != NULL);
 875         }
 876 
 877         return ((lx_regs_t *)((uintptr_t *)fr)[2]);
 878 }
 879 
 880 int
 881 lx_lpid_to_spair(pid_t lpid, pid_t *spid, lwpid_t *slwp)
 882 {
 883         pid_t pid;
 884         lwpid_t tid;
 885 
 886         if (lpid == 0) {
 887                 pid = getpid();
 888                 tid = thr_self();
 889         } else {
 890                 if (syscall(SYS_brand, B_LPID_TO_SPAIR, lpid, &pid, &tid) < 0)
 891                         return (-errno);
 892 
 893                 /*
 894                  * If the returned pid is -1, that indicates we tried to
 895                  * look up the PID for init, but that process no longer
 896                  * exists.
 897                  */
 898                 if (pid == -1)
 899                         return (-ESRCH);
 900         }
 901 
 902         if (uucopy(&pid, spid, sizeof (pid_t)) != 0)
 903                 return (-errno);
 904 
 905         if (uucopy(&tid, slwp, sizeof (lwpid_t)) != 0)
 906                 return (-errno);
 907 
 908         return (0);
 909 }
 910 
 911 int
 912 lx_lpid_to_spid(pid_t lpid, pid_t *spid)
 913 {
 914         lwpid_t slwp;
 915 
 916         return (lx_lpid_to_spair(lpid, spid, &slwp));
 917 }
 918 
 919 char *
 920 lx_fd_to_path(int fd, char *buf, int buf_size)
 921 {
 922         char    path_proc[MAXPATHLEN];
 923         pid_t   pid;
 924         int     n;
 925 
 926         assert((buf != NULL) && (buf_size >= 0));
 927 
 928         if (fd < 0)
 929                 return (NULL);
 930 
 931         if ((pid = getpid()) == -1)
 932                 return (NULL);
 933 
 934         (void) snprintf(path_proc, MAXPATHLEN,
 935             "/native/proc/%d/path/%d", pid, fd);
 936 
 937         if ((n = readlink(path_proc, buf, buf_size - 1)) == -1)
 938                 return (NULL);
 939         buf[n] = '\0';
 940 
 941         return (buf);
 942 }
 943 
 944 /*
 945  * Create a translation routine that jumps to a particular emulation
 946  * module syscall.
 947  */
 948 #define IN_KERNEL_SYSCALL(name, num)            \
 949 int                                             \
 950 lx_##name(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4,       \
 951         uintptr_t p5, uintptr_t p6)             \
 952 {                                               \
 953         int r;                                  \
 954         lx_debug("\tsyscall %d re-vectoring to lx kernel module "       \
 955             "for " #name "()", num);            \
 956         r = syscall(SYS_brand, B_EMULATE_SYSCALL + num, p1, p2,         \
 957             p3, p4, p5, p6);                    \
 958         return ((r == -1) ? -errno : r);                \
 959 }
 960 
 961 IN_KERNEL_SYSCALL(kill, 37)
 962 IN_KERNEL_SYSCALL(brk, 45)
 963 IN_KERNEL_SYSCALL(ustat, 62)
 964 IN_KERNEL_SYSCALL(getppid, 64)
 965 IN_KERNEL_SYSCALL(sysinfo, 116)
 966 IN_KERNEL_SYSCALL(modify_ldt, 123)
 967 IN_KERNEL_SYSCALL(adjtimex, 124)
 968 IN_KERNEL_SYSCALL(setresuid16, 164)
 969 IN_KERNEL_SYSCALL(setresgid16, 170)
 970 IN_KERNEL_SYSCALL(setresuid, 208)
 971 IN_KERNEL_SYSCALL(setresgid, 210)
 972 IN_KERNEL_SYSCALL(gettid, 224)
 973 IN_KERNEL_SYSCALL(tkill, 238)
 974 IN_KERNEL_SYSCALL(futex, 240)
 975 IN_KERNEL_SYSCALL(set_thread_area, 243)
 976 IN_KERNEL_SYSCALL(get_thread_area, 244)
 977 IN_KERNEL_SYSCALL(set_tid_address, 258)
 978 
 979 static struct lx_sysent sysents[] = {
 980         {"nosys",       NULL,           NOSYS_NULL,     0},     /*  0 */
 981         {"exit",        lx_exit,        0,              1},     /*  1 */
 982         {"fork",        lx_fork,        0,              0},     /*  2 */
 983         {"read",        lx_read,        0,              3},     /*  3 */
 984         {"write",       write,          SYS_PASSTHRU,   3},     /*  4 */
 985         {"open",        lx_open,        0,              3},     /*  5 */
 986         {"close",       close,          SYS_PASSTHRU,   1},     /*  6 */
 987         {"waitpid",     lx_waitpid,     0,              3},     /*  7 */
 988         {"creat",       creat,          SYS_PASSTHRU,   2},     /*  8 */
 989         {"link",        lx_link,        0,              2},     /*  9 */
 990         {"unlink",      lx_unlink,      0,              1},     /* 10 */
 991         {"execve",      lx_execve,      0,              3},     /* 11 */
 992         {"chdir",       chdir,          SYS_PASSTHRU,   1},     /* 12 */
 993         {"time",        lx_time,        0,              1},     /* 13 */
 994         {"mknod",       lx_mknod,       0,              3},     /* 14 */
 995         {"chmod",       lx_chmod,       0,              2},     /* 15 */
 996         {"lchown16",    lx_lchown16,    0,              3},     /* 16 */
 997         {"break",       NULL,           NOSYS_OBSOLETE, 0},     /* 17 */
 998         {"stat",        NULL,           NOSYS_OBSOLETE, 0},     /* 18 */
 999         {"lseek",       lx_lseek,       0,              3},     /* 19 */
1000         {"getpid",      lx_getpid,      0,              0},     /* 20 */
1001         {"mount",       lx_mount,       0,              5},     /* 21 */
1002         {"umount",      lx_umount,      0,              1},     /* 22 */
1003         {"setuid16",    lx_setuid16,    0,              1},     /* 23 */
1004         {"getuid16",    lx_getuid16,    0,              0},     /* 24 */
1005         {"stime",       stime,          SYS_PASSTHRU,   1},     /* 25 */
1006         {"ptrace",      lx_ptrace,      0,              4},     /* 26 */
1007         {"alarm",       (int (*)())alarm, SYS_PASSTHRU, 1},     /* 27 */
1008         {"fstat",       NULL,           NOSYS_OBSOLETE, 0},     /* 28 */
1009         {"pause",       pause,          SYS_PASSTHRU,   0},     /* 29 */
1010         {"utime",       lx_utime,       0,              2},     /* 30 */
1011         {"stty",        NULL,           NOSYS_OBSOLETE, 0},     /* 31 */
1012         {"gtty",        NULL,           NOSYS_OBSOLETE, 0},     /* 32 */
1013         {"access",      access,         SYS_PASSTHRU,   2},     /* 33 */
1014         {"nice",        nice,           SYS_PASSTHRU,   1},     /* 34 */
1015         {"ftime",       NULL,           NOSYS_OBSOLETE, 0},     /* 35 */
1016         {"sync",        lx_sync,        0,              0},     /* 36 */
1017         {"kill",        lx_kill,        0,              2},     /* 37 */
1018         {"rename",      lx_rename,      0,              2},     /* 38 */
1019         {"mkdir",       mkdir,          SYS_PASSTHRU,   2},     /* 39 */
1020         {"rmdir",       lx_rmdir,       0,              1},     /* 40 */
1021         {"dup",         dup,            SYS_PASSTHRU,   1},     /* 41 */
1022         {"pipe",        lx_pipe,        0,              1},     /* 42 */
1023         {"times",       lx_times,       0,              1},     /* 43 */
1024         {"prof",        NULL,           NOSYS_OBSOLETE, 0},     /* 44 */
1025         {"brk",         lx_brk,         0,              1},     /* 45 */
1026         {"setgid16",    lx_setgid16,    0,              1},     /* 46 */
1027         {"getgid16",    lx_getgid16,    0,              0},     /* 47 */
1028         {"signal",      lx_signal,      0,              2},     /* 48 */
1029         {"geteuid16",   lx_geteuid16,   0,              0},     /* 49 */
1030         {"getegid16",   lx_getegid16,   0,              0},     /* 50 */
1031         {"acct",        NULL,           NOSYS_NO_EQUIV, 0},     /* 51 */
1032         {"umount2",     lx_umount2,     0,              2},     /* 52 */
1033         {"lock",        NULL,           NOSYS_OBSOLETE, 0},     /* 53 */
1034         {"ioctl",       lx_ioctl,       0,              3},     /* 54 */
1035         {"fcntl",       lx_fcntl,       0,              3},     /* 55 */
1036         {"mpx",         NULL,           NOSYS_OBSOLETE, 0},     /* 56 */
1037         {"setpgid",     lx_setpgid,     0,              2},     /* 57 */
1038         {"ulimit",      NULL,           NOSYS_OBSOLETE, 0},     /* 58 */
1039         {"olduname",    NULL,           NOSYS_OBSOLETE, 0},     /* 59 */
1040         {"umask",       (int (*)())umask, SYS_PASSTHRU, 1},     /* 60 */
1041         {"chroot",      chroot,         SYS_PASSTHRU,   1},     /* 61 */
1042         {"ustat",       lx_ustat,       0,              2},     /* 62 */
1043         {"dup2",        lx_dup2,        0,              2},     /* 63 */
1044         {"getppid",     lx_getppid,     0,              0},     /* 64 */
1045         {"getpgrp",     lx_getpgrp,     0,              0},     /* 65 */
1046         {"setsid",      lx_setsid,      0,              0},     /* 66 */
1047         {"sigaction",   lx_sigaction,   0,              3},     /* 67 */
1048         {"sgetmask",    NULL,           NOSYS_OBSOLETE, 0},     /* 68 */
1049         {"ssetmask",    NULL,           NOSYS_OBSOLETE, 0},     /* 69 */
1050         {"setreuid16",  lx_setreuid16,  0,              2},     /* 70 */
1051         {"setregid16",  lx_setregid16,  0,              2},     /* 71 */
1052         {"sigsuspend",  lx_sigsuspend,  0,              1},     /* 72 */
1053         {"sigpending",  lx_sigpending,  0,              1},     /* 73 */
1054         {"sethostname", lx_sethostname, 0,              2},     /* 74 */
1055         {"setrlimit",   lx_setrlimit,   0,              2},     /* 75 */
1056         {"getrlimit",   lx_oldgetrlimit, 0,             2},     /* 76 */
1057         {"getrusage",   lx_getrusage,   0,              2},     /* 77 */
1058         {"gettimeofday", lx_gettimeofday, 0,            2},     /* 78 */
1059         {"settimeofday", lx_settimeofday, 0,            2},     /* 79 */
1060         {"getgroups16", lx_getgroups16, 0,              2},     /* 80 */
1061         {"setgroups16", lx_setgroups16, 0,              2},     /* 81 */
1062         {"select",      NULL,           NOSYS_OBSOLETE, 0},     /* 82 */
1063         {"symlink",     symlink,        SYS_PASSTHRU,   2},     /* 83 */
1064         {"oldlstat",    NULL,           NOSYS_OBSOLETE, 0},     /* 84 */
1065         {"readlink",    readlink,       SYS_PASSTHRU,   3},     /* 85 */
1066         {"uselib",      NULL,           NOSYS_KERNEL,   0},     /* 86 */
1067         {"swapon",      NULL,           NOSYS_KERNEL,   0},     /* 87 */
1068         {"reboot",      lx_reboot,      0,              4},     /* 88 */
1069         {"readdir",     lx_readdir,     0,              3},     /* 89 */
1070         {"mmap",        lx_mmap,        0,              6},     /* 90 */
1071         {"munmap",      munmap,         SYS_PASSTHRU,   2},     /* 91 */
1072         {"truncate",    lx_truncate,    0,              2},     /* 92 */
1073         {"ftruncate",   lx_ftruncate,   0,              2},     /* 93 */
1074         {"fchmod",      fchmod,         SYS_PASSTHRU,   2},     /* 94 */
1075         {"fchown16",    lx_fchown16,    0,              3},     /* 95 */
1076         {"getpriority", lx_getpriority, 0,              2},     /* 96 */
1077         {"setpriority", lx_setpriority, 0,              3},     /* 97 */
1078         {"profil",      NULL,           NOSYS_NO_EQUIV, 0},     /* 98 */
1079         {"statfs",      lx_statfs,      0,              2},     /* 99 */
1080         {"fstatfs",     lx_fstatfs,     0,              2},     /* 100 */
1081         {"ioperm",      NULL,           NOSYS_NO_EQUIV, 0},     /* 101 */
1082         {"socketcall",  lx_socketcall,  0,              2},     /* 102 */
1083         {"syslog",      NULL,           NOSYS_KERNEL,   0},     /* 103 */
1084         {"setitimer",   lx_setitimer,   0,              3},     /* 104 */
1085         {"getitimer",   getitimer,      SYS_PASSTHRU,   2},     /* 105 */
1086         {"stat",        lx_stat,        0,              2},     /* 106 */
1087         {"lstat",       lx_lstat,       0,              2},     /* 107 */
1088         {"fstat",       lx_fstat,       0,              2},     /* 108 */
1089         {"uname",       NULL,           NOSYS_OBSOLETE, 0},     /* 109 */
1090         {"oldiopl",     NULL,           NOSYS_NO_EQUIV, 0},     /* 110 */
1091         {"vhangup",     lx_vhangup,     0,              0},     /* 111 */
1092         {"idle",        NULL,           NOSYS_NO_EQUIV, 0},     /* 112 */
1093         {"vm86old",     NULL,           NOSYS_OBSOLETE, 0},     /* 113 */
1094         {"wait4",       lx_wait4,       0,              4},     /* 114 */
1095         {"swapoff",     NULL,           NOSYS_KERNEL,   0},     /* 115 */
1096         {"sysinfo",     lx_sysinfo,     0,              1},     /* 116 */
1097         {"ipc",         lx_ipc,         0,              5},     /* 117 */
1098         {"fsync",       lx_fsync,       0,              1},     /* 118 */
1099         {"sigreturn",   lx_sigreturn,   0,              1},     /* 119 */
1100         {"clone",       lx_clone,       0,              5},     /* 120 */
1101         {"setdomainname", lx_setdomainname, 0,          2},     /* 121 */
1102         {"uname",       lx_uname,       0,              1},     /* 122 */
1103         {"modify_ldt",  lx_modify_ldt,  0,              3},     /* 123 */
1104         {"adjtimex",    lx_adjtimex,    0,              1},     /* 124 */
1105         {"mprotect",    lx_mprotect,    0,              3},     /* 125 */
1106         {"sigprocmask", lx_sigprocmask, 0,              3},     /* 126 */
1107         {"create_module", NULL,         NOSYS_KERNEL,   0},     /* 127 */
1108         {"init_module", NULL,           NOSYS_KERNEL,   0},     /* 128 */
1109         {"delete_module", NULL,         NOSYS_KERNEL,   0},     /* 129 */
1110         {"get_kernel_syms", NULL,       NOSYS_KERNEL,   0},     /* 130 */
1111         {"quotactl",    NULL,           NOSYS_KERNEL,   0},     /* 131 */
1112         {"getpgid",     lx_getpgid,     0,              1},     /* 132 */
1113         {"fchdir",      fchdir,         SYS_PASSTHRU,   1},     /* 133 */
1114         {"bdflush",     NULL,           NOSYS_KERNEL,   0},     /* 134 */
1115         {"sysfs",       lx_sysfs,       0,              3},     /* 135 */
1116         {"personality", lx_personality, 0,              1},     /* 136 */
1117         {"afs_syscall", NULL,           NOSYS_KERNEL,   0},     /* 137 */
1118         {"setfsuid16",  lx_setfsuid16,  0,              1},     /* 138 */
1119         {"setfsgid16",  lx_setfsgid16,  0,              1},     /* 139 */
1120         {"llseek",      lx_llseek,      0,              5},     /* 140 */
1121         {"getdents",    getdents,       SYS_PASSTHRU,   3},     /* 141 */
1122         {"select",      lx_select,      0,              5},     /* 142 */
1123         {"flock",       lx_flock,       0,              2},     /* 143 */
1124         {"msync",       lx_msync,       0,              3},     /* 144 */
1125         {"readv",       lx_readv,       0,              3},     /* 145 */
1126         {"writev",      lx_writev,      0,              3},     /* 146 */
1127         {"getsid",      lx_getsid,      0,              1},     /* 147 */
1128         {"fdatasync",   lx_fdatasync,   0,              1},     /* 148 */
1129         {"sysctl",      lx_sysctl,      0,              1},     /* 149 */
1130         {"mlock",       lx_mlock,       0,              2},     /* 150 */
1131         {"munlock",     lx_munlock,     0,              2},     /* 151 */
1132         {"mlockall",    lx_mlockall,    0,              1},     /* 152 */
1133         {"munlockall",  lx_munlockall,  0,              0},     /* 153 */
1134         {"sched_setparam", lx_sched_setparam,   0,      2},     /* 154 */
1135         {"sched_getparam", lx_sched_getparam,   0,      2},     /* 155 */
1136         {"sched_setscheduler", lx_sched_setscheduler, 0, 3},    /* 156 */
1137         {"sched_getscheduler", lx_sched_getscheduler, 0, 1},    /* 157 */
1138         {"sched_yield", (int (*)())yield, SYS_PASSTHRU, 0},     /* 158 */
1139         {"sched_get_priority_max", lx_sched_get_priority_max, 0, 1}, /* 159 */
1140         {"sched_get_priority_min", lx_sched_get_priority_min, 0, 1}, /* 160 */
1141         {"sched_rr_get_interval", lx_sched_rr_get_interval, 0,  2},  /* 161 */
1142         {"nanosleep",   nanosleep,      SYS_PASSTHRU,   2},     /* 162 */
1143         {"mremap",      NULL,           NOSYS_NO_EQUIV, 0},     /* 163 */
1144         {"setresuid16", lx_setresuid16, 0,              3},     /* 164 */
1145         {"getresuid16", lx_getresuid16, 0,              3},     /* 165 */
1146         {"vm86",        NULL,           NOSYS_NO_EQUIV, 0},     /* 166 */
1147         {"query_module", lx_query_module, NOSYS_KERNEL, 5},     /* 167 */
1148         {"poll",        lx_poll,        0,              3},     /* 168 */
1149         {"nfsservctl",  NULL,           NOSYS_KERNEL,   0},     /* 169 */
1150         {"setresgid16", lx_setresgid16, 0,              3},     /* 170 */
1151         {"getresgid16", lx_getresgid16, 0,              3},     /* 171 */
1152         {"prctl",       NULL,           NOSYS_UNDOC,    0},     /* 172 */
1153         {"rt_sigreturn", lx_rt_sigreturn, 0,            0},     /* 173 */
1154         {"rt_sigaction", lx_rt_sigaction, 0,            4},     /* 174 */
1155         {"rt_sigprocmask", lx_rt_sigprocmask, 0,        4},     /* 175 */
1156         {"rt_sigpending", lx_rt_sigpending, 0,          2},     /* 176 */
1157         {"rt_sigtimedwait", lx_rt_sigtimedwait, 0,      4},     /* 177 */
1158         {"sigqueueinfo", NULL,          NOSYS_UNDOC,    0},     /* 178 */
1159         {"rt_sigsuspend", lx_rt_sigsuspend, 0,          2},     /* 179 */
1160         {"pread64",     lx_pread64,     0,              5},     /* 180 */
1161         {"pwrite64",    lx_pwrite64,    0,              5},     /* 181 */
1162         {"chown16",     lx_chown16,     0,              3},     /* 182 */
1163         {"getcwd",      lx_getcwd,      0,              2},     /* 183 */
1164         {"capget",      NULL,           NOSYS_NO_EQUIV, 0},     /* 184 */
1165         {"capset",      NULL,           NOSYS_NO_EQUIV, 0},     /* 185 */
1166         {"sigaltstack", lx_sigaltstack, 0,              2},     /* 186 */
1167         {"sendfile",    lx_sendfile,    0,              4},     /* 187 */
1168         {"getpmsg",     NULL,           NOSYS_OBSOLETE, 0},     /* 188 */
1169         {"putpmsg",     NULL,           NOSYS_OBSOLETE, 0},     /* 189 */
1170         {"vfork",       lx_vfork,       0,              0},     /* 190 */
1171         {"getrlimit",   lx_getrlimit,   0,              2},     /* 191 */
1172         {"mmap2",       lx_mmap2,       EBP_HAS_ARG6,   6},     /* 192 */
1173         {"truncate64",  lx_truncate64,  0,              3},     /* 193 */
1174         {"ftruncate64", lx_ftruncate64, 0,              3},     /* 194 */
1175         {"stat64",      lx_stat64,      0,              2},     /* 195 */
1176         {"lstat64",     lx_lstat64,     0,              2},     /* 196 */
1177         {"fstat64",     lx_fstat64,     0,              2},     /* 197 */
1178         {"lchown",      lchown,         SYS_PASSTHRU,   3},     /* 198 */
1179         {"getuid",      (int (*)())getuid, SYS_PASSTHRU, 0},    /* 199 */
1180         {"getgid",      (int (*)())getgid, SYS_PASSTHRU, 0},    /* 200 */
1181         {"geteuid",     lx_geteuid,     0,              0},     /* 201 */
1182         {"getegid",     lx_getegid,     0,              0},     /* 202 */
1183         {"setreuid",    setreuid,       SYS_PASSTHRU,   0},     /* 203 */
1184         {"setregid",    setregid,       SYS_PASSTHRU,   0},     /* 204 */
1185         {"getgroups",   getgroups,      SYS_PASSTHRU,   2},     /* 205 */
1186         {"setgroups",   lx_setgroups,   0,              2},     /* 206 */
1187         {"fchown",      lx_fchown,      0,              3},     /* 207 */
1188         {"setresuid",   lx_setresuid,   0,              3},     /* 208 */
1189         {"getresuid",   lx_getresuid,   0,              3},     /* 209 */
1190         {"setresgid",   lx_setresgid,   0,              3},     /* 210 */
1191         {"getresgid",   lx_getresgid,   0,              3},     /* 211 */
1192         {"chown",       lx_chown,       0,              3},     /* 212 */
1193         {"setuid",      setuid,         SYS_PASSTHRU,   1},     /* 213 */
1194         {"setgid",      setgid,         SYS_PASSTHRU,   1},     /* 214 */
1195         {"setfsuid",    lx_setfsuid,    0,              1},     /* 215 */
1196         {"setfsgid",    lx_setfsgid,    0,              1},     /* 216 */
1197         {"pivot_root",  NULL,           NOSYS_KERNEL,   0},     /* 217 */
1198         {"mincore",     mincore,        SYS_PASSTHRU,   3},     /* 218 */
1199         {"madvise",     lx_madvise,     0,              3},     /* 219 */
1200         {"getdents64",  lx_getdents64,  0,              3},     /* 220 */
1201         {"fcntl64",     lx_fcntl64,     0,              3},     /* 221 */
1202         {"tux",         NULL,           NOSYS_NO_EQUIV, 0},     /* 222 */
1203         {"security",    NULL,           NOSYS_NO_EQUIV, 0},     /* 223 */
1204         {"gettid",      lx_gettid,      0,              0},     /* 224 */
1205         {"readahead",   NULL,           NOSYS_NO_EQUIV, 0},     /* 225 */
1206         {"setxattr",    NULL,           NOSYS_NO_EQUIV, 0},     /* 226 */
1207         {"lsetxattr",   NULL,           NOSYS_NO_EQUIV, 0},     /* 227 */
1208         {"fsetxattr",   NULL,           NOSYS_NO_EQUIV, 0},     /* 228 */
1209         {"getxattr",    NULL,           NOSYS_NO_EQUIV, 0},     /* 229 */
1210         {"lgetxattr",   NULL,           NOSYS_NO_EQUIV, 0},     /* 230 */
1211         {"fgetxattr",   NULL,           NOSYS_NO_EQUIV, 0},     /* 231 */
1212         {"listxattr",   NULL,           NOSYS_NO_EQUIV, 0},     /* 232 */
1213         {"llistxattr",  NULL,           NOSYS_NO_EQUIV, 0},     /* 233 */
1214         {"flistxattr",  NULL,           NOSYS_NO_EQUIV, 0},     /* 234 */
1215         {"removexattr", NULL,           NOSYS_NO_EQUIV, 0},     /* 235 */
1216         {"lremovexattr", NULL,          NOSYS_NO_EQUIV, 0},     /* 236 */
1217         {"fremovexattr", NULL,          NOSYS_NO_EQUIV, 0},     /* 237 */
1218         {"tkill",       lx_tkill,       0,              2},     /* 238 */
1219         {"sendfile64",  lx_sendfile64,  0,              4},     /* 239 */
1220         {"futex",       lx_futex,       EBP_HAS_ARG6,   6},     /* 240 */
1221         {"sched_setaffinity",   lx_sched_setaffinity,   0, 3},  /* 241 */
1222         {"sched_getaffinity",   lx_sched_getaffinity,   0, 3},  /* 242 */
1223         {"set_thread_area", lx_set_thread_area, 0,      1},     /* 243 */
1224         {"get_thread_area", lx_get_thread_area, 0,      1},     /* 244 */
1225         {"io_setup",    NULL,           NOSYS_NO_EQUIV, 0},     /* 245 */
1226         {"io_destroy",  NULL,           NOSYS_NO_EQUIV, 0},     /* 246 */
1227         {"io_getevents", NULL,          NOSYS_NO_EQUIV, 0},     /* 247 */
1228         {"io_submit",   NULL,           NOSYS_NO_EQUIV, 0},     /* 248 */
1229         {"io_cancel",   NULL,           NOSYS_NO_EQUIV, 0},     /* 249 */
1230         {"fadvise64",   NULL,           NOSYS_UNDOC,    0},     /* 250 */
1231         {"nosys",       NULL,           0,              0},     /* 251 */
1232         {"group_exit",  lx_group_exit,  0,              1},     /* 252 */
1233         {"lookup_dcookie", NULL,        NOSYS_NO_EQUIV, 0},     /* 253 */
1234         {"epoll_create", NULL,          NOSYS_NO_EQUIV, 0},     /* 254 */
1235         {"epoll_ctl",   NULL,           NOSYS_NO_EQUIV, 0},     /* 255 */
1236         {"epoll_wait",  NULL,           NOSYS_NO_EQUIV, 0},     /* 256 */
1237         {"remap_file_pages", NULL,      NOSYS_NO_EQUIV, 0},     /* 257 */
1238         {"set_tid_address", lx_set_tid_address, 0,      1},     /* 258 */
1239         {"timer_create", NULL,          NOSYS_UNDOC,    0},     /* 259 */
1240         {"timer_settime", NULL,         NOSYS_UNDOC,    0},     /* 260 */
1241         {"timer_gettime", NULL,         NOSYS_UNDOC,    0},     /* 261 */
1242         {"timer_getoverrun", NULL,      NOSYS_UNDOC,    0},     /* 262 */
1243         {"timer_delete", NULL,          NOSYS_UNDOC,    0},     /* 263 */
1244         {"clock_settime", lx_clock_settime,     0,      2},     /* 264 */
1245         {"clock_gettime", lx_clock_gettime,     0,      2},     /* 265 */
1246         {"clock_getres", lx_clock_getres,       0,      2},     /* 266 */
1247         {"clock_nanosleep", lx_clock_nanosleep, 0,      4},     /* 267 */
1248         {"statfs64",    lx_statfs64,    0,              2},     /* 268 */
1249         {"fstatfs64",   lx_fstatfs64,   0,              2},     /* 269 */
1250         {"tgkill",      lx_tgkill,      0,              3},     /* 270 */
1251 
1252         /* The following system calls only exist in kernel 2.6 and greater */
1253         {"utimes",      utimes,         SYS_PASSTHRU,   2},     /* 271 */
1254         {"fadvise64_64", NULL,          NOSYS_NULL,     0},     /* 272 */
1255         {"vserver",     NULL,           NOSYS_NULL,     0},     /* 273 */
1256         {"mbind",       NULL,           NOSYS_NULL,     0},     /* 274 */
1257         {"get_mempolicy", NULL,         NOSYS_NULL,     0},     /* 275 */
1258         {"set_mempolicy", NULL,         NOSYS_NULL,     0},     /* 276 */
1259         {"mq_open",     NULL,           NOSYS_NULL,     0},     /* 277 */
1260         {"mq_unlink",   NULL,           NOSYS_NULL,     0},     /* 278 */
1261         {"mq_timedsend", NULL,          NOSYS_NULL,     0},     /* 279 */
1262         {"mq_timedreceive", NULL,       NOSYS_NULL,     0},     /* 280 */
1263         {"mq_notify",   NULL,           NOSYS_NULL,     0},     /* 281 */
1264         {"mq_getsetattr", NULL,         NOSYS_NULL,     0},     /* 282 */
1265         {"kexec_load",  NULL,           NOSYS_NULL,     0},     /* 283 */
1266         {"waitid",      lx_waitid,      0,              4},     /* 284 */
1267         {"sys_setaltroot", NULL,        NOSYS_NULL,     0},     /* 285 */
1268         {"add_key",     NULL,           NOSYS_NULL,     0},     /* 286 */
1269         {"request_key", NULL,           NOSYS_NULL,     0},     /* 287 */
1270         {"keyctl",      NULL,           NOSYS_NULL,     0},     /* 288 */
1271         {"ioprio_set",  NULL,           NOSYS_NULL,     0},     /* 289 */
1272         {"ioprio_get",  NULL,           NOSYS_NULL,     0},     /* 290 */
1273         {"inotify_init", NULL,          NOSYS_NULL,     0},     /* 291 */
1274         {"inotify_add_watch", NULL,     NOSYS_NULL,     0},     /* 292 */
1275         {"inotify_rm_watch", NULL,      NOSYS_NULL,     0},     /* 293 */
1276         {"migrate_pages", NULL,         NOSYS_NULL,     0},     /* 294 */
1277         {"openat",      lx_openat,      0,              4},     /* 295 */
1278         {"mkdirat",     lx_mkdirat,     0,              3},     /* 296 */
1279         {"mknodat",     lx_mknodat,     0,              4},     /* 297 */
1280         {"fchownat",    lx_fchownat,    0,              5},     /* 298 */
1281         {"futimesat",   lx_futimesat,   0,              3},     /* 299 */
1282         {"fstatat64",   lx_fstatat64,   0,              4},     /* 300 */
1283         {"unlinkat",    lx_unlinkat,    0,              3},     /* 301 */
1284         {"renameat",    lx_renameat,    0,              4},     /* 302 */
1285         {"linkat",      lx_linkat,      0,              5},     /* 303 */
1286         {"symlinkat",   lx_symlinkat,   0,              3},     /* 304 */
1287         {"readlinkat",  lx_readlinkat,  0,              4},     /* 305 */
1288         {"fchmodat",    lx_fchmodat,    0,              4},     /* 306 */
1289         {"faccessat",   lx_faccessat,   0,              4},     /* 307 */
1290         {"pselect6",    NULL,           NOSYS_NULL,     0},     /* 308 */
1291         {"ppoll",       NULL,           NOSYS_NULL,     0},     /* 309 */
1292         {"unshare",     NULL,           NOSYS_NULL,     0},     /* 310 */
1293         {"set_robust_list", NULL,       NOSYS_NULL,     0},     /* 311 */
1294         {"get_robust_list", NULL,       NOSYS_NULL,     0},     /* 312 */
1295         {"splice",      NULL,           NOSYS_NULL,     0},     /* 313 */
1296         {"sync_file_range", NULL,       NOSYS_NULL,     0},     /* 314 */
1297         {"tee",         NULL,           NOSYS_NULL,     0},     /* 315 */
1298         {"vmsplice",    NULL,           NOSYS_NULL,     0},     /* 316 */
1299         {"move_pages",  NULL,           NOSYS_NULL,     0},     /* 317 */
1300 };