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, ®))
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 };