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[s->sy_flags]); 446 ret = -stol_errno[ENOTSUP]; 447 goto out; 448 } 449 450 if (lx_debug_enabled != 0) { 451 const char *fmt; 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 extern int set_l10n_alternate_root(char *path); 629 630 /*ARGSUSED*/ 631 int 632 lx_init(int argc, char *argv[], char *envp[]) 633 { 634 char *r; 635 auxv_t *ap; 636 int *p, err; 637 lx_elf_data_t edp; 638 lx_brand_registration_t reg; 639 char locale_translated_name[MAXLOCALENAMELEN]; 640 static lx_tsd_t lx_tsd; 641 642 /* Look up the PID that serves as init for this zone */ 643 if ((err = lx_lpid_to_spid(1, &zoneinit_pid)) < 0) 644 lx_err_fatal(gettext( 645 "Unable to find PID for zone init process: %s"), 646 strerror(err)); 647 648 /* 649 * Ubuntu init will fail if its TERM environment variable is not set 650 * so if we are running init, and TERM is not set, we set term and 651 * reexec so that the new environment variable is propagated to the 652 * linux application stack. 653 */ 654 if ((getpid() == zoneinit_pid) && (getenv("TERM") == NULL)) { 655 if (setenv("TERM", "vt100", 1) < 0 || execv(argv[0], argv) < 0) 656 lx_err_fatal(gettext("failed to set TERM")); 657 } 658 659 if ((set_l10n_alternate_root("/native") == 0) && 660 (setlocale(LC_ALL, lx_translate_locale(locale_translated_name, 661 sizeof (locale_translated_name))) != NULL) && 662 (bindtextdomain(TEXT_DOMAIN, "/native/usr/lib/locale") != NULL)) { 663 (void) textdomain(TEXT_DOMAIN); 664 } 665 666 stack_bottom = 2 * sysconf(_SC_PAGESIZE); 667 668 /* 669 * We need to shutdown all libc stdio. libc stdio normally goes to 670 * file descriptors, but since we're actually part of a linux 671 * process we don't own these file descriptors and we can't make 672 * any assumptions about their state. 673 */ 674 lx_close_fh(stdin); 675 lx_close_fh(stdout); 676 lx_close_fh(stderr); 677 678 lx_debug_init(); 679 680 r = getenv("LX_RELEASE"); 681 if (r == NULL) { 682 if (lx_get_kern_version() == LX_KERN_2_6) 683 (void) strlcpy(lx_release, LX_UNAME_RELEASE_2_6, 684 sizeof (lx_release)); 685 else 686 (void) strlcpy(lx_release, LX_UNAME_RELEASE_2_4, 687 sizeof (lx_release)); 688 } else { 689 (void) strlcpy(lx_release, r, 128); 690 } 691 692 lx_debug("lx_release: %s\n", lx_release); 693 694 /* 695 * Should we kill an application that attempts an unimplemented 696 * system call? 697 */ 698 if (getenv("LX_STRICT") != NULL) { 699 lx_strict = 1; 700 lx_debug("STRICT mode enabled.\n"); 701 } 702 703 /* 704 * Are we in install mode? 705 */ 706 if (getenv("LX_INSTALL") != NULL) { 707 lx_install = 1; 708 lx_debug("INSTALL mode enabled.\n"); 709 } 710 711 /* 712 * Should we attempt to send messages to the screen? 713 */ 714 if (getenv("LX_VERBOSE") != NULL) { 715 lx_verbose = 1; 716 lx_debug("VERBOSE mode enabled.\n"); 717 } 718 719 lx_debug("executing linux process: %s", argv[0]); 720 lx_debug("branding myself and setting handler to 0x%p", 721 (void *)lx_handler_table); 722 723 /* 724 * The version of rpm that ships with CentOS/RHEL 3.x has a race 725 * condition in it. If it creates a child process to run a 726 * post-install script, and that child process completes too 727 * quickly, it will disappear before the parent notices. This 728 * causes the parent to hang forever waiting for the already dead 729 * child to die. I'm sure there's a Lazarus joke buried in here 730 * somewhere. 731 * 732 * Anyway, as a workaround, we make every child of an 'rpm' process 733 * sleep for 1 second, giving the parent a chance to enter its 734 * wait-for-the-child-to-die loop. Thay may be the hackiest trick 735 * in all of our Linux emulation code - and that's saying 736 * something. 737 */ 738 if (strcmp("rpm", basename(argv[0])) == NULL) 739 lx_is_rpm = B_TRUE; 740 741 reg.lxbr_version = LX_VERSION; 742 reg.lxbr_handler = (void *)&lx_handler_table; 743 reg.lxbr_tracehandler = (void *)&lx_handler_trace_table; 744 reg.lxbr_traceflag = &lx_traceflag; 745 746 /* 747 * Register the address of the user-space handler with the lx 748 * brand module. 749 */ 750 if (syscall(SYS_brand, B_REGISTER, ®)) 751 lx_err_fatal(gettext("failed to brand the process")); 752 753 /* 754 * Download data about the lx executable from the kernel. 755 */ 756 if (syscall(SYS_brand, B_ELFDATA, (void *)&edp)) 757 lx_err_fatal(gettext( 758 "failed to get required ELF data from the kernel")); 759 760 if (lx_ioctl_init() != 0) 761 lx_err_fatal(gettext("failed to setup the %s translator"), 762 "ioctl"); 763 764 if (lx_stat_init() != 0) 765 lx_err_fatal(gettext("failed to setup the %s translator"), 766 "stat"); 767 768 if (lx_statfs_init() != 0) 769 lx_err_fatal(gettext("failed to setup the %s translator"), 770 "statfs"); 771 772 /* 773 * Find the aux vector on the stack. 774 */ 775 p = (int *)envp; 776 while (*p != NULL) 777 p++; 778 /* 779 * p is now pointing at the 0 word after the environ pointers. After 780 * that is the aux vectors. 781 */ 782 p++; 783 for (ap = (auxv_t *)p; ap->a_type != 0; ap++) { 784 switch (ap->a_type) { 785 case AT_BASE: 786 ap->a_un.a_val = edp.ed_base; 787 break; 788 case AT_ENTRY: 789 ap->a_un.a_val = edp.ed_entry; 790 break; 791 case AT_PHDR: 792 ap->a_un.a_val = edp.ed_phdr; 793 break; 794 case AT_PHENT: 795 ap->a_un.a_val = edp.ed_phent; 796 break; 797 case AT_PHNUM: 798 ap->a_un.a_val = edp.ed_phnum; 799 break; 800 default: 801 break; 802 } 803 } 804 805 /* Do any thunk server initalization. */ 806 lxt_server_init(argc, argv); 807 808 /* Setup signal handler information. */ 809 if (lx_siginit()) 810 lx_err_fatal(gettext( 811 "failed to initialize lx signals for the branded process")); 812 813 /* Setup thread-specific data area for managing linux threads. */ 814 if ((err = thr_keycreate(&lx_tsd_key, NULL)) != 0) 815 lx_err_fatal( 816 gettext("%s failed: %s"), "thr_keycreate(lx_tsd_key)", 817 strerror(err)); 818 819 lx_debug("thr_keycreate created lx_tsd_key (%d)", lx_tsd_key); 820 821 /* Initialize the thread specific data for this thread. */ 822 bzero(&lx_tsd, sizeof (lx_tsd)); 823 lx_tsd.lxtsd_gs = LWPGS_SEL; 824 825 if ((err = thr_setspecific(lx_tsd_key, &lx_tsd)) != 0) 826 lx_err_fatal(gettext( 827 "Unable to initialize thread-specific data: %s"), 828 strerror(err)); 829 830 /* 831 * Save the current context of this thread. 832 * We'll restore this context when this thread attempts to exit. 833 */ 834 if (getcontext(&lx_tsd.lxtsd_exit_context) != 0) 835 lx_err_fatal(gettext( 836 "Unable to initialize thread-specific exit context: %s"), 837 strerror(errno)); 838 839 if (lx_tsd.lxtsd_exit == 0) { 840 lx_runexe(argv, edp.ed_ldentry); 841 /* lx_runexe() never returns. */ 842 assert(0); 843 } 844 845 /* 846 * We are here because the Linux application called the exit() or 847 * exit_group() system call. In turn the brand library did a 848 * setcontext() to jump to the thread context state we saved above. 849 */ 850 if (lx_tsd.lxtsd_exit == 1) 851 thr_exit((void *)lx_tsd.lxtsd_exit_status); 852 else 853 exit(lx_tsd.lxtsd_exit_status); 854 855 assert(0); 856 857 /*NOTREACHED*/ 858 return (0); 859 } 860 861 /* 862 * Walk back through the stack until we find the lx_emulate() frame. 863 */ 864 lx_regs_t * 865 lx_syscall_regs(void) 866 { 867 /* LINTED - alignment */ 868 struct frame *fr = (struct frame *)_getfp(); 869 870 while (fr->fr_savpc != (uintptr_t)&lx_emulate_done) { 871 fr = (struct frame *)fr->fr_savfp; 872 assert(fr->fr_savpc != NULL); 873 } 874 875 return ((lx_regs_t *)((uintptr_t *)fr)[2]); 876 } 877 878 int 879 lx_lpid_to_spair(pid_t lpid, pid_t *spid, lwpid_t *slwp) 880 { 881 pid_t pid; 882 lwpid_t tid; 883 884 if (lpid == 0) { 885 pid = getpid(); 886 tid = thr_self(); 887 } else { 888 if (syscall(SYS_brand, B_LPID_TO_SPAIR, lpid, &pid, &tid) < 0) 889 return (-errno); 890 891 /* 892 * If the returned pid is -1, that indicates we tried to 893 * look up the PID for init, but that process no longer 894 * exists. 895 */ 896 if (pid == -1) 897 return (-ESRCH); 898 } 899 900 if (uucopy(&pid, spid, sizeof (pid_t)) != 0) 901 return (-errno); 902 903 if (uucopy(&tid, slwp, sizeof (lwpid_t)) != 0) 904 return (-errno); 905 906 return (0); 907 } 908 909 int 910 lx_lpid_to_spid(pid_t lpid, pid_t *spid) 911 { 912 lwpid_t slwp; 913 914 return (lx_lpid_to_spair(lpid, spid, &slwp)); 915 } 916 917 char * 918 lx_fd_to_path(int fd, char *buf, int buf_size) 919 { 920 char path_proc[MAXPATHLEN]; 921 pid_t pid; 922 int n; 923 924 assert((buf != NULL) && (buf_size >= 0)); 925 926 if (fd < 0) 927 return (NULL); 928 929 if ((pid = getpid()) == -1) 930 return (NULL); 931 932 (void) snprintf(path_proc, MAXPATHLEN, 933 "/native/proc/%d/path/%d", pid, fd); 934 935 if ((n = readlink(path_proc, buf, buf_size - 1)) == -1) 936 return (NULL); 937 buf[n] = '\0'; 938 939 return (buf); 940 } 941 942 /* 943 * Create a translation routine that jumps to a particular emulation 944 * module syscall. 945 */ 946 #define IN_KERNEL_SYSCALL(name, num) \ 947 int \ 948 lx_##name(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, \ 949 uintptr_t p5, uintptr_t p6) \ 950 { \ 951 int r; \ 952 lx_debug("\tsyscall %d re-vectoring to lx kernel module " \ 953 "for " #name "()", num); \ 954 r = syscall(SYS_brand, B_EMULATE_SYSCALL + num, p1, p2, \ 955 p3, p4, p5, p6); \ 956 return ((r == -1) ? -errno : r); \ 957 } 958 959 IN_KERNEL_SYSCALL(kill, 37) 960 IN_KERNEL_SYSCALL(brk, 45) 961 IN_KERNEL_SYSCALL(ustat, 62) 962 IN_KERNEL_SYSCALL(getppid, 64) 963 IN_KERNEL_SYSCALL(sysinfo, 116) 964 IN_KERNEL_SYSCALL(modify_ldt, 123) 965 IN_KERNEL_SYSCALL(adjtimex, 124) 966 IN_KERNEL_SYSCALL(setresuid16, 164) 967 IN_KERNEL_SYSCALL(setresgid16, 170) 968 IN_KERNEL_SYSCALL(setresuid, 208) 969 IN_KERNEL_SYSCALL(setresgid, 210) 970 IN_KERNEL_SYSCALL(gettid, 224) 971 IN_KERNEL_SYSCALL(tkill, 238) 972 IN_KERNEL_SYSCALL(futex, 240) 973 IN_KERNEL_SYSCALL(set_thread_area, 243) 974 IN_KERNEL_SYSCALL(get_thread_area, 244) 975 IN_KERNEL_SYSCALL(set_tid_address, 258) 976 977 static struct lx_sysent sysents[] = { 978 {"nosys", NULL, NOSYS_NULL, 0}, /* 0 */ 979 {"exit", lx_exit, 0, 1}, /* 1 */ 980 {"fork", lx_fork, 0, 0}, /* 2 */ 981 {"read", lx_read, 0, 3}, /* 3 */ 982 {"write", write, SYS_PASSTHRU, 3}, /* 4 */ 983 {"open", lx_open, 0, 3}, /* 5 */ 984 {"close", close, SYS_PASSTHRU, 1}, /* 6 */ 985 {"waitpid", lx_waitpid, 0, 3}, /* 7 */ 986 {"creat", creat, SYS_PASSTHRU, 2}, /* 8 */ 987 {"link", lx_link, 0, 2}, /* 9 */ 988 {"unlink", lx_unlink, 0, 1}, /* 10 */ 989 {"execve", lx_execve, 0, 3}, /* 11 */ 990 {"chdir", chdir, SYS_PASSTHRU, 1}, /* 12 */ 991 {"time", lx_time, 0, 1}, /* 13 */ 992 {"mknod", lx_mknod, 0, 3}, /* 14 */ 993 {"chmod", lx_chmod, 0, 2}, /* 15 */ 994 {"lchown16", lx_lchown16, 0, 3}, /* 16 */ 995 {"break", NULL, NOSYS_OBSOLETE, 0}, /* 17 */ 996 {"stat", NULL, NOSYS_OBSOLETE, 0}, /* 18 */ 997 {"lseek", lx_lseek, 0, 3}, /* 19 */ 998 {"getpid", lx_getpid, 0, 0}, /* 20 */ 999 {"mount", lx_mount, 0, 5}, /* 21 */ 1000 {"umount", lx_umount, 0, 1}, /* 22 */ 1001 {"setuid16", lx_setuid16, 0, 1}, /* 23 */ 1002 {"getuid16", lx_getuid16, 0, 0}, /* 24 */ 1003 {"stime", stime, SYS_PASSTHRU, 1}, /* 25 */ 1004 {"ptrace", lx_ptrace, 0, 4}, /* 26 */ 1005 {"alarm", (int (*)())alarm, SYS_PASSTHRU, 1}, /* 27 */ 1006 {"fstat", NULL, NOSYS_OBSOLETE, 0}, /* 28 */ 1007 {"pause", pause, SYS_PASSTHRU, 0}, /* 29 */ 1008 {"utime", lx_utime, 0, 2}, /* 30 */ 1009 {"stty", NULL, NOSYS_OBSOLETE, 0}, /* 31 */ 1010 {"gtty", NULL, NOSYS_OBSOLETE, 0}, /* 32 */ 1011 {"access", access, SYS_PASSTHRU, 2}, /* 33 */ 1012 {"nice", nice, SYS_PASSTHRU, 1}, /* 34 */ 1013 {"ftime", NULL, NOSYS_OBSOLETE, 0}, /* 35 */ 1014 {"sync", lx_sync, 0, 0}, /* 36 */ 1015 {"kill", lx_kill, 0, 2}, /* 37 */ 1016 {"rename", lx_rename, 0, 2}, /* 38 */ 1017 {"mkdir", mkdir, SYS_PASSTHRU, 2}, /* 39 */ 1018 {"rmdir", lx_rmdir, 0, 1}, /* 40 */ 1019 {"dup", dup, SYS_PASSTHRU, 1}, /* 41 */ 1020 {"pipe", lx_pipe, 0, 1}, /* 42 */ 1021 {"times", lx_times, 0, 1}, /* 43 */ 1022 {"prof", NULL, NOSYS_OBSOLETE, 0}, /* 44 */ 1023 {"brk", lx_brk, 0, 1}, /* 45 */ 1024 {"setgid16", lx_setgid16, 0, 1}, /* 46 */ 1025 {"getgid16", lx_getgid16, 0, 0}, /* 47 */ 1026 {"signal", lx_signal, 0, 2}, /* 48 */ 1027 {"geteuid16", lx_geteuid16, 0, 0}, /* 49 */ 1028 {"getegid16", lx_getegid16, 0, 0}, /* 50 */ 1029 {"acct", NULL, NOSYS_NO_EQUIV, 0}, /* 51 */ 1030 {"umount2", lx_umount2, 0, 2}, /* 52 */ 1031 {"lock", NULL, NOSYS_OBSOLETE, 0}, /* 53 */ 1032 {"ioctl", lx_ioctl, 0, 3}, /* 54 */ 1033 {"fcntl", lx_fcntl, 0, 3}, /* 55 */ 1034 {"mpx", NULL, NOSYS_OBSOLETE, 0}, /* 56 */ 1035 {"setpgid", lx_setpgid, 0, 2}, /* 57 */ 1036 {"ulimit", NULL, NOSYS_OBSOLETE, 0}, /* 58 */ 1037 {"olduname", NULL, NOSYS_OBSOLETE, 0}, /* 59 */ 1038 {"umask", (int (*)())umask, SYS_PASSTHRU, 1}, /* 60 */ 1039 {"chroot", chroot, SYS_PASSTHRU, 1}, /* 61 */ 1040 {"ustat", lx_ustat, 0, 2}, /* 62 */ 1041 {"dup2", lx_dup2, 0, 2}, /* 63 */ 1042 {"getppid", lx_getppid, 0, 0}, /* 64 */ 1043 {"getpgrp", lx_getpgrp, 0, 0}, /* 65 */ 1044 {"setsid", lx_setsid, 0, 0}, /* 66 */ 1045 {"sigaction", lx_sigaction, 0, 3}, /* 67 */ 1046 {"sgetmask", NULL, NOSYS_OBSOLETE, 0}, /* 68 */ 1047 {"ssetmask", NULL, NOSYS_OBSOLETE, 0}, /* 69 */ 1048 {"setreuid16", lx_setreuid16, 0, 2}, /* 70 */ 1049 {"setregid16", lx_setregid16, 0, 2}, /* 71 */ 1050 {"sigsuspend", lx_sigsuspend, 0, 1}, /* 72 */ 1051 {"sigpending", lx_sigpending, 0, 1}, /* 73 */ 1052 {"sethostname", lx_sethostname, 0, 2}, /* 74 */ 1053 {"setrlimit", lx_setrlimit, 0, 2}, /* 75 */ 1054 {"getrlimit", lx_oldgetrlimit, 0, 2}, /* 76 */ 1055 {"getrusage", lx_getrusage, 0, 2}, /* 77 */ 1056 {"gettimeofday", lx_gettimeofday, 0, 2}, /* 78 */ 1057 {"settimeofday", lx_settimeofday, 0, 2}, /* 79 */ 1058 {"getgroups16", lx_getgroups16, 0, 2}, /* 80 */ 1059 {"setgroups16", lx_setgroups16, 0, 2}, /* 81 */ 1060 {"select", NULL, NOSYS_OBSOLETE, 0}, /* 82 */ 1061 {"symlink", symlink, SYS_PASSTHRU, 2}, /* 83 */ 1062 {"oldlstat", NULL, NOSYS_OBSOLETE, 0}, /* 84 */ 1063 {"readlink", readlink, SYS_PASSTHRU, 3}, /* 85 */ 1064 {"uselib", NULL, NOSYS_KERNEL, 0}, /* 86 */ 1065 {"swapon", NULL, NOSYS_KERNEL, 0}, /* 87 */ 1066 {"reboot", lx_reboot, 0, 4}, /* 88 */ 1067 {"readdir", lx_readdir, 0, 3}, /* 89 */ 1068 {"mmap", lx_mmap, 0, 6}, /* 90 */ 1069 {"munmap", munmap, SYS_PASSTHRU, 2}, /* 91 */ 1070 {"truncate", lx_truncate, 0, 2}, /* 92 */ 1071 {"ftruncate", lx_ftruncate, 0, 2}, /* 93 */ 1072 {"fchmod", fchmod, SYS_PASSTHRU, 2}, /* 94 */ 1073 {"fchown16", lx_fchown16, 0, 3}, /* 95 */ 1074 {"getpriority", lx_getpriority, 0, 2}, /* 96 */ 1075 {"setpriority", lx_setpriority, 0, 3}, /* 97 */ 1076 {"profil", NULL, NOSYS_NO_EQUIV, 0}, /* 98 */ 1077 {"statfs", lx_statfs, 0, 2}, /* 99 */ 1078 {"fstatfs", lx_fstatfs, 0, 2}, /* 100 */ 1079 {"ioperm", NULL, NOSYS_NO_EQUIV, 0}, /* 101 */ 1080 {"socketcall", lx_socketcall, 0, 2}, /* 102 */ 1081 {"syslog", NULL, NOSYS_KERNEL, 0}, /* 103 */ 1082 {"setitimer", lx_setitimer, 0, 3}, /* 104 */ 1083 {"getitimer", getitimer, SYS_PASSTHRU, 2}, /* 105 */ 1084 {"stat", lx_stat, 0, 2}, /* 106 */ 1085 {"lstat", lx_lstat, 0, 2}, /* 107 */ 1086 {"fstat", lx_fstat, 0, 2}, /* 108 */ 1087 {"uname", NULL, NOSYS_OBSOLETE, 0}, /* 109 */ 1088 {"oldiopl", NULL, NOSYS_NO_EQUIV, 0}, /* 110 */ 1089 {"vhangup", lx_vhangup, 0, 0}, /* 111 */ 1090 {"idle", NULL, NOSYS_NO_EQUIV, 0}, /* 112 */ 1091 {"vm86old", NULL, NOSYS_OBSOLETE, 0}, /* 113 */ 1092 {"wait4", lx_wait4, 0, 4}, /* 114 */ 1093 {"swapoff", NULL, NOSYS_KERNEL, 0}, /* 115 */ 1094 {"sysinfo", lx_sysinfo, 0, 1}, /* 116 */ 1095 {"ipc", lx_ipc, 0, 5}, /* 117 */ 1096 {"fsync", lx_fsync, 0, 1}, /* 118 */ 1097 {"sigreturn", lx_sigreturn, 0, 1}, /* 119 */ 1098 {"clone", lx_clone, 0, 5}, /* 120 */ 1099 {"setdomainname", lx_setdomainname, 0, 2}, /* 121 */ 1100 {"uname", lx_uname, 0, 1}, /* 122 */ 1101 {"modify_ldt", lx_modify_ldt, 0, 3}, /* 123 */ 1102 {"adjtimex", lx_adjtimex, 0, 1}, /* 124 */ 1103 {"mprotect", lx_mprotect, 0, 3}, /* 125 */ 1104 {"sigprocmask", lx_sigprocmask, 0, 3}, /* 126 */ 1105 {"create_module", NULL, NOSYS_KERNEL, 0}, /* 127 */ 1106 {"init_module", NULL, NOSYS_KERNEL, 0}, /* 128 */ 1107 {"delete_module", NULL, NOSYS_KERNEL, 0}, /* 129 */ 1108 {"get_kernel_syms", NULL, NOSYS_KERNEL, 0}, /* 130 */ 1109 {"quotactl", NULL, NOSYS_KERNEL, 0}, /* 131 */ 1110 {"getpgid", lx_getpgid, 0, 1}, /* 132 */ 1111 {"fchdir", fchdir, SYS_PASSTHRU, 1}, /* 133 */ 1112 {"bdflush", NULL, NOSYS_KERNEL, 0}, /* 134 */ 1113 {"sysfs", lx_sysfs, 0, 3}, /* 135 */ 1114 {"personality", lx_personality, 0, 1}, /* 136 */ 1115 {"afs_syscall", NULL, NOSYS_KERNEL, 0}, /* 137 */ 1116 {"setfsuid16", lx_setfsuid16, 0, 1}, /* 138 */ 1117 {"setfsgid16", lx_setfsgid16, 0, 1}, /* 139 */ 1118 {"llseek", lx_llseek, 0, 5}, /* 140 */ 1119 {"getdents", getdents, SYS_PASSTHRU, 3}, /* 141 */ 1120 {"select", lx_select, 0, 5}, /* 142 */ 1121 {"flock", lx_flock, 0, 2}, /* 143 */ 1122 {"msync", lx_msync, 0, 3}, /* 144 */ 1123 {"readv", lx_readv, 0, 3}, /* 145 */ 1124 {"writev", lx_writev, 0, 3}, /* 146 */ 1125 {"getsid", lx_getsid, 0, 1}, /* 147 */ 1126 {"fdatasync", lx_fdatasync, 0, 1}, /* 148 */ 1127 {"sysctl", lx_sysctl, 0, 1}, /* 149 */ 1128 {"mlock", lx_mlock, 0, 2}, /* 150 */ 1129 {"munlock", lx_munlock, 0, 2}, /* 151 */ 1130 {"mlockall", lx_mlockall, 0, 1}, /* 152 */ 1131 {"munlockall", lx_munlockall, 0, 0}, /* 153 */ 1132 {"sched_setparam", lx_sched_setparam, 0, 2}, /* 154 */ 1133 {"sched_getparam", lx_sched_getparam, 0, 2}, /* 155 */ 1134 {"sched_setscheduler", lx_sched_setscheduler, 0, 3}, /* 156 */ 1135 {"sched_getscheduler", lx_sched_getscheduler, 0, 1}, /* 157 */ 1136 {"sched_yield", (int (*)())yield, SYS_PASSTHRU, 0}, /* 158 */ 1137 {"sched_get_priority_max", lx_sched_get_priority_max, 0, 1}, /* 159 */ 1138 {"sched_get_priority_min", lx_sched_get_priority_min, 0, 1}, /* 160 */ 1139 {"sched_rr_get_interval", lx_sched_rr_get_interval, 0, 2}, /* 161 */ 1140 {"nanosleep", nanosleep, SYS_PASSTHRU, 2}, /* 162 */ 1141 {"mremap", NULL, NOSYS_NO_EQUIV, 0}, /* 163 */ 1142 {"setresuid16", lx_setresuid16, 0, 3}, /* 164 */ 1143 {"getresuid16", lx_getresuid16, 0, 3}, /* 165 */ 1144 {"vm86", NULL, NOSYS_NO_EQUIV, 0}, /* 166 */ 1145 {"query_module", lx_query_module, NOSYS_KERNEL, 5}, /* 167 */ 1146 {"poll", lx_poll, 0, 3}, /* 168 */ 1147 {"nfsservctl", NULL, NOSYS_KERNEL, 0}, /* 169 */ 1148 {"setresgid16", lx_setresgid16, 0, 3}, /* 170 */ 1149 {"getresgid16", lx_getresgid16, 0, 3}, /* 171 */ 1150 {"prctl", NULL, NOSYS_UNDOC, 0}, /* 172 */ 1151 {"rt_sigreturn", lx_rt_sigreturn, 0, 0}, /* 173 */ 1152 {"rt_sigaction", lx_rt_sigaction, 0, 4}, /* 174 */ 1153 {"rt_sigprocmask", lx_rt_sigprocmask, 0, 4}, /* 175 */ 1154 {"rt_sigpending", lx_rt_sigpending, 0, 2}, /* 176 */ 1155 {"rt_sigtimedwait", lx_rt_sigtimedwait, 0, 4}, /* 177 */ 1156 {"sigqueueinfo", NULL, NOSYS_UNDOC, 0}, /* 178 */ 1157 {"rt_sigsuspend", lx_rt_sigsuspend, 0, 2}, /* 179 */ 1158 {"pread64", lx_pread64, 0, 5}, /* 180 */ 1159 {"pwrite64", lx_pwrite64, 0, 5}, /* 181 */ 1160 {"chown16", lx_chown16, 0, 3}, /* 182 */ 1161 {"getcwd", lx_getcwd, 0, 2}, /* 183 */ 1162 {"capget", NULL, NOSYS_NO_EQUIV, 0}, /* 184 */ 1163 {"capset", NULL, NOSYS_NO_EQUIV, 0}, /* 185 */ 1164 {"sigaltstack", lx_sigaltstack, 0, 2}, /* 186 */ 1165 {"sendfile", lx_sendfile, 0, 4}, /* 187 */ 1166 {"getpmsg", NULL, NOSYS_OBSOLETE, 0}, /* 188 */ 1167 {"putpmsg", NULL, NOSYS_OBSOLETE, 0}, /* 189 */ 1168 {"vfork", lx_vfork, 0, 0}, /* 190 */ 1169 {"getrlimit", lx_getrlimit, 0, 2}, /* 191 */ 1170 {"mmap2", lx_mmap2, EBP_HAS_ARG6, 6}, /* 192 */ 1171 {"truncate64", lx_truncate64, 0, 3}, /* 193 */ 1172 {"ftruncate64", lx_ftruncate64, 0, 3}, /* 194 */ 1173 {"stat64", lx_stat64, 0, 2}, /* 195 */ 1174 {"lstat64", lx_lstat64, 0, 2}, /* 196 */ 1175 {"fstat64", lx_fstat64, 0, 2}, /* 197 */ 1176 {"lchown", lchown, SYS_PASSTHRU, 3}, /* 198 */ 1177 {"getuid", (int (*)())getuid, SYS_PASSTHRU, 0}, /* 199 */ 1178 {"getgid", (int (*)())getgid, SYS_PASSTHRU, 0}, /* 200 */ 1179 {"geteuid", lx_geteuid, 0, 0}, /* 201 */ 1180 {"getegid", lx_getegid, 0, 0}, /* 202 */ 1181 {"setreuid", setreuid, SYS_PASSTHRU, 0}, /* 203 */ 1182 {"setregid", setregid, SYS_PASSTHRU, 0}, /* 204 */ 1183 {"getgroups", getgroups, SYS_PASSTHRU, 2}, /* 205 */ 1184 {"setgroups", lx_setgroups, 0, 2}, /* 206 */ 1185 {"fchown", lx_fchown, 0, 3}, /* 207 */ 1186 {"setresuid", lx_setresuid, 0, 3}, /* 208 */ 1187 {"getresuid", lx_getresuid, 0, 3}, /* 209 */ 1188 {"setresgid", lx_setresgid, 0, 3}, /* 210 */ 1189 {"getresgid", lx_getresgid, 0, 3}, /* 211 */ 1190 {"chown", lx_chown, 0, 3}, /* 212 */ 1191 {"setuid", setuid, SYS_PASSTHRU, 1}, /* 213 */ 1192 {"setgid", setgid, SYS_PASSTHRU, 1}, /* 214 */ 1193 {"setfsuid", lx_setfsuid, 0, 1}, /* 215 */ 1194 {"setfsgid", lx_setfsgid, 0, 1}, /* 216 */ 1195 {"pivot_root", NULL, NOSYS_KERNEL, 0}, /* 217 */ 1196 {"mincore", mincore, SYS_PASSTHRU, 3}, /* 218 */ 1197 {"madvise", lx_madvise, 0, 3}, /* 219 */ 1198 {"getdents64", lx_getdents64, 0, 3}, /* 220 */ 1199 {"fcntl64", lx_fcntl64, 0, 3}, /* 221 */ 1200 {"tux", NULL, NOSYS_NO_EQUIV, 0}, /* 222 */ 1201 {"security", NULL, NOSYS_NO_EQUIV, 0}, /* 223 */ 1202 {"gettid", lx_gettid, 0, 0}, /* 224 */ 1203 {"readahead", NULL, NOSYS_NO_EQUIV, 0}, /* 225 */ 1204 {"setxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 226 */ 1205 {"lsetxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 227 */ 1206 {"fsetxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 228 */ 1207 {"getxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 229 */ 1208 {"lgetxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 230 */ 1209 {"fgetxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 231 */ 1210 {"listxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 232 */ 1211 {"llistxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 233 */ 1212 {"flistxattr", NULL, NOSYS_NO_EQUIV, 0}, /* 234 */ 1213 {"removexattr", NULL, NOSYS_NO_EQUIV, 0}, /* 235 */ 1214 {"lremovexattr", NULL, NOSYS_NO_EQUIV, 0}, /* 236 */ 1215 {"fremovexattr", NULL, NOSYS_NO_EQUIV, 0}, /* 237 */ 1216 {"tkill", lx_tkill, 0, 2}, /* 238 */ 1217 {"sendfile64", lx_sendfile64, 0, 4}, /* 239 */ 1218 {"futex", lx_futex, EBP_HAS_ARG6, 6}, /* 240 */ 1219 {"sched_setaffinity", lx_sched_setaffinity, 0, 3}, /* 241 */ 1220 {"sched_getaffinity", lx_sched_getaffinity, 0, 3}, /* 242 */ 1221 {"set_thread_area", lx_set_thread_area, 0, 1}, /* 243 */ 1222 {"get_thread_area", lx_get_thread_area, 0, 1}, /* 244 */ 1223 {"io_setup", NULL, NOSYS_NO_EQUIV, 0}, /* 245 */ 1224 {"io_destroy", NULL, NOSYS_NO_EQUIV, 0}, /* 246 */ 1225 {"io_getevents", NULL, NOSYS_NO_EQUIV, 0}, /* 247 */ 1226 {"io_submit", NULL, NOSYS_NO_EQUIV, 0}, /* 248 */ 1227 {"io_cancel", NULL, NOSYS_NO_EQUIV, 0}, /* 249 */ 1228 {"fadvise64", NULL, NOSYS_UNDOC, 0}, /* 250 */ 1229 {"nosys", NULL, 0, 0}, /* 251 */ 1230 {"group_exit", lx_group_exit, 0, 1}, /* 252 */ 1231 {"lookup_dcookie", NULL, NOSYS_NO_EQUIV, 0}, /* 253 */ 1232 {"epoll_create", NULL, NOSYS_NO_EQUIV, 0}, /* 254 */ 1233 {"epoll_ctl", NULL, NOSYS_NO_EQUIV, 0}, /* 255 */ 1234 {"epoll_wait", NULL, NOSYS_NO_EQUIV, 0}, /* 256 */ 1235 {"remap_file_pages", NULL, NOSYS_NO_EQUIV, 0}, /* 257 */ 1236 {"set_tid_address", lx_set_tid_address, 0, 1}, /* 258 */ 1237 {"timer_create", NULL, NOSYS_UNDOC, 0}, /* 259 */ 1238 {"timer_settime", NULL, NOSYS_UNDOC, 0}, /* 260 */ 1239 {"timer_gettime", NULL, NOSYS_UNDOC, 0}, /* 261 */ 1240 {"timer_getoverrun", NULL, NOSYS_UNDOC, 0}, /* 262 */ 1241 {"timer_delete", NULL, NOSYS_UNDOC, 0}, /* 263 */ 1242 {"clock_settime", lx_clock_settime, 0, 2}, /* 264 */ 1243 {"clock_gettime", lx_clock_gettime, 0, 2}, /* 265 */ 1244 {"clock_getres", lx_clock_getres, 0, 2}, /* 266 */ 1245 {"clock_nanosleep", lx_clock_nanosleep, 0, 4}, /* 267 */ 1246 {"statfs64", lx_statfs64, 0, 2}, /* 268 */ 1247 {"fstatfs64", lx_fstatfs64, 0, 2}, /* 269 */ 1248 {"tgkill", lx_tgkill, 0, 3}, /* 270 */ 1249 1250 /* The following system calls only exist in kernel 2.6 and greater */ 1251 {"utimes", utimes, SYS_PASSTHRU, 2}, /* 271 */ 1252 {"fadvise64_64", NULL, NOSYS_NULL, 0}, /* 272 */ 1253 {"vserver", NULL, NOSYS_NULL, 0}, /* 273 */ 1254 {"mbind", NULL, NOSYS_NULL, 0}, /* 274 */ 1255 {"get_mempolicy", NULL, NOSYS_NULL, 0}, /* 275 */ 1256 {"set_mempolicy", NULL, NOSYS_NULL, 0}, /* 276 */ 1257 {"mq_open", NULL, NOSYS_NULL, 0}, /* 277 */ 1258 {"mq_unlink", NULL, NOSYS_NULL, 0}, /* 278 */ 1259 {"mq_timedsend", NULL, NOSYS_NULL, 0}, /* 279 */ 1260 {"mq_timedreceive", NULL, NOSYS_NULL, 0}, /* 280 */ 1261 {"mq_notify", NULL, NOSYS_NULL, 0}, /* 281 */ 1262 {"mq_getsetattr", NULL, NOSYS_NULL, 0}, /* 282 */ 1263 {"kexec_load", NULL, NOSYS_NULL, 0}, /* 283 */ 1264 {"waitid", lx_waitid, 0, 4}, /* 284 */ 1265 {"sys_setaltroot", NULL, NOSYS_NULL, 0}, /* 285 */ 1266 {"add_key", NULL, NOSYS_NULL, 0}, /* 286 */ 1267 {"request_key", NULL, NOSYS_NULL, 0}, /* 287 */ 1268 {"keyctl", NULL, NOSYS_NULL, 0}, /* 288 */ 1269 {"ioprio_set", NULL, NOSYS_NULL, 0}, /* 289 */ 1270 {"ioprio_get", NULL, NOSYS_NULL, 0}, /* 290 */ 1271 {"inotify_init", NULL, NOSYS_NULL, 0}, /* 291 */ 1272 {"inotify_add_watch", NULL, NOSYS_NULL, 0}, /* 292 */ 1273 {"inotify_rm_watch", NULL, NOSYS_NULL, 0}, /* 293 */ 1274 {"migrate_pages", NULL, NOSYS_NULL, 0}, /* 294 */ 1275 {"openat", lx_openat, 0, 4}, /* 295 */ 1276 {"mkdirat", lx_mkdirat, 0, 3}, /* 296 */ 1277 {"mknodat", lx_mknodat, 0, 4}, /* 297 */ 1278 {"fchownat", lx_fchownat, 0, 5}, /* 298 */ 1279 {"futimesat", lx_futimesat, 0, 3}, /* 299 */ 1280 {"fstatat64", lx_fstatat64, 0, 4}, /* 300 */ 1281 {"unlinkat", lx_unlinkat, 0, 3}, /* 301 */ 1282 {"renameat", lx_renameat, 0, 4}, /* 302 */ 1283 {"linkat", lx_linkat, 0, 5}, /* 303 */ 1284 {"symlinkat", lx_symlinkat, 0, 3}, /* 304 */ 1285 {"readlinkat", lx_readlinkat, 0, 4}, /* 305 */ 1286 {"fchmodat", lx_fchmodat, 0, 4}, /* 306 */ 1287 {"faccessat", lx_faccessat, 0, 4}, /* 307 */ 1288 {"pselect6", NULL, NOSYS_NULL, 0}, /* 308 */ 1289 {"ppoll", NULL, NOSYS_NULL, 0}, /* 309 */ 1290 {"unshare", NULL, NOSYS_NULL, 0}, /* 310 */ 1291 {"set_robust_list", NULL, NOSYS_NULL, 0}, /* 311 */ 1292 {"get_robust_list", NULL, NOSYS_NULL, 0}, /* 312 */ 1293 {"splice", NULL, NOSYS_NULL, 0}, /* 313 */ 1294 {"sync_file_range", NULL, NOSYS_NULL, 0}, /* 314 */ 1295 {"tee", NULL, NOSYS_NULL, 0}, /* 315 */ 1296 {"vmsplice", NULL, NOSYS_NULL, 0}, /* 316 */ 1297 {"move_pages", NULL, NOSYS_NULL, 0}, /* 317 */ 1298 };