2 * Copyright (c) 2014 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
8 * This file defines various POSIX-like functions directly using Linux
9 * syscalls. This is analogous to src/untrusted/nacl/sys_private.c, which
10 * defines functions using NaCl syscalls directly.
24 #include "native_client/src/include/elf32.h"
25 #include "native_client/src/nonsfi/linux/abi_conversion.h"
26 #include "native_client/src/nonsfi/linux/linux_sys_private.h"
27 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h"
28 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h"
29 #include "native_client/src/nonsfi/linux/linux_syscall_wrappers.h"
30 #include "native_client/src/nonsfi/linux/linux_syscalls.h"
31 #include "native_client/src/public/linux_syscalls/poll.h"
32 #include "native_client/src/public/linux_syscalls/sys/prctl.h"
33 #include "native_client/src/public/linux_syscalls/sys/socket.h"
34 #include "native_client/src/untrusted/nacl/tls.h"
38 * Note that Non-SFI NaCl uses a 4k page size, in contrast to SFI NaCl's
41 static const int kPageSize = 0x1000;
43 static uintptr_t errno_value_call(uintptr_t result) {
44 if (linux_is_error_result(result)) {
51 void _exit(int status) {
52 linux_syscall1(__NR_exit_group, status);
56 int gettimeofday(struct timeval *tv, void *tz) {
57 struct linux_abi_timeval linux_tv;
58 int result = errno_value_call(
59 linux_syscall2(__NR_gettimeofday, (uintptr_t) &linux_tv, 0));
61 linux_timeval_to_nacl_timeval(&linux_tv, tv);
65 int nanosleep(const struct timespec *req, struct timespec *rem) {
66 struct linux_abi_timespec linux_req;
67 nacl_timespec_to_linux_timespec(req, &linux_req);
68 struct linux_abi_timespec linux_rem;
69 int result = errno_value_call(linux_syscall2(__NR_nanosleep,
70 (uintptr_t) &linux_req,
71 (uintptr_t) &linux_rem));
74 * NaCl does not support async signals, so we don't fill out rem on
77 if (result == 0 && rem != NULL)
78 linux_timespec_to_nacl_timespec(&linux_rem, rem);
82 int clock_gettime(clockid_t clk_id, struct timespec *ts) {
83 struct linux_abi_timespec linux_ts;
84 int result = errno_value_call(
85 linux_syscall2(__NR_clock_gettime, clk_id, (uintptr_t) &linux_ts));
87 linux_timespec_to_nacl_timespec(&linux_ts, ts);
91 int clock_getres(clockid_t clk_id, struct timespec *res) {
92 struct linux_abi_timespec linux_res;
93 int result = errno_value_call(
94 linux_syscall2(__NR_clock_getres, clk_id, (uintptr_t) &linux_res));
95 /* Unlike clock_gettime, clock_getres allows NULL timespecs. */
96 if (result == 0 && res != NULL)
97 linux_timespec_to_nacl_timespec(&linux_res, res);
101 int sched_yield(void) {
102 return errno_value_call(linux_syscall0(__NR_sched_yield));
105 long int sysconf(int name) {
114 static void *mmap_internal(void *start, size_t length, int prot, int flags,
115 int fd, off_t offset) {
116 #if defined(__i386__) || defined(__arm__)
117 static const int kPageBits = 12;
118 if (offset & ((1 << kPageBits) - 1)) {
119 /* An unaligned offset is specified. */
123 offset >>= kPageBits;
125 return (void *) errno_value_call(
126 linux_syscall6(__NR_mmap2, (uintptr_t) start, length,
127 prot, flags, fd, offset));
129 # error Unsupported architecture
133 void *mmap(void *start, size_t length, int prot, int flags,
134 int fd, off_t offset) {
136 * On Chrome OS and on Chrome's seccomp sandbox, mmap() with PROT_EXEC is
137 * prohibited. So, instead, mmap() the memory without PROT_EXEC first, and
138 * then give it the PROT_EXEC by mprotect.
141 mmap_internal(start, length, (prot & ~PROT_EXEC), flags, fd, offset);
142 if (result != MAP_FAILED && (prot & PROT_EXEC) != 0) {
143 if (mprotect(result, length, prot) < 0) {
145 * If mprotect failed, we cannot do much else other than abort(), because
146 * we cannot undo the mmap() (specifically, when MAP_FIXED is set).
148 static const char msg[] =
149 "mprotect() in mmap() to set PROT_EXEC failed.";
150 write(2, msg, sizeof(msg) - 1);
157 int munmap(void *start, size_t length) {
158 return errno_value_call(
159 linux_syscall2(__NR_munmap, (uintptr_t) start, length));
162 int mprotect(void *start, size_t length, int prot) {
163 return errno_value_call(
164 linux_syscall3(__NR_mprotect, (uintptr_t) start, length, prot));
167 int read(int fd, void *buf, size_t count) {
168 return errno_value_call(linux_syscall3(__NR_read, fd,
169 (uintptr_t) buf, count));
172 int write(int fd, const void *buf, size_t count) {
173 return errno_value_call(linux_syscall3(__NR_write, fd,
174 (uintptr_t) buf, count));
177 int open(char const *pathname, int oflag, ...) {
181 if (oflag & O_CREAT) {
183 cmode = va_arg(ap, mode_t);
189 return errno_value_call(
190 linux_syscall3(__NR_open, (uintptr_t) pathname, oflag, cmode));
194 return errno_value_call(linux_syscall1(__NR_close, fd));
197 ssize_t pread(int fd, void *buf, size_t count, off_t offset) {
198 uint32_t offset_low = (uint32_t) offset;
199 uint32_t offset_high = offset >> 32;
200 #if defined(__i386__)
201 return errno_value_call(
202 linux_syscall5(__NR_pread64, fd, (uintptr_t) buf, count,
203 offset_low, offset_high));
204 #elif defined(__arm__)
206 * On ARM, a 64-bit parameter has to be in an even-odd register
207 * pair. Hence these calls ignore their fourth argument (r3) so that
208 * their fifth and sixth make such a pair (r4,r5).
210 return errno_value_call(
211 linux_syscall6(__NR_pread64, fd, (uintptr_t) buf, count,
212 0 /* dummy */, offset_low, offset_high));
214 # error Unsupported architecture
218 ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) {
219 uint32_t offset_low = (uint32_t) offset;
220 uint32_t offset_high = offset >> 32;
221 #if defined(__i386__)
222 return errno_value_call(
223 linux_syscall5(__NR_pwrite64, fd, (uintptr_t) buf, count,
224 offset_low, offset_high));
225 #elif defined(__arm__)
226 return errno_value_call(
227 linux_syscall6(__NR_pwrite64, fd, (uintptr_t) buf, count,
228 0 /* dummy */, offset_low, offset_high));
230 # error Unsupported architecture
234 off_t lseek(int fd, off_t offset, int whence) {
235 #if defined(__i386__) || defined(__arm__)
236 uint32_t offset_low = (uint32_t) offset;
237 uint32_t offset_high = offset >> 32;
239 int rc = errno_value_call(
240 linux_syscall5(__NR__llseek, fd, offset_high, offset_low,
241 (uintptr_t) &result, whence));
246 # error Unsupported architecture
251 return errno_value_call(linux_syscall1(__NR_dup, fd));
254 int dup2(int oldfd, int newfd) {
255 return errno_value_call(linux_syscall2(__NR_dup2, oldfd, newfd));
258 int fstat(int fd, struct stat *st) {
259 struct linux_abi_stat64 linux_st;
260 int rc = errno_value_call(
261 linux_syscall2(__NR_fstat64, fd, (uintptr_t) &linux_st));
264 linux_stat_to_nacl_stat(&linux_st, st);
268 int stat(const char *file, struct stat *st) {
269 struct linux_abi_stat64 linux_st;
270 int rc = errno_value_call(
271 linux_syscall2(__NR_stat64, (uintptr_t) file, (uintptr_t) &linux_st));
274 linux_stat_to_nacl_stat(&linux_st, st);
278 int lstat(const char *file, struct stat *st) {
279 struct linux_abi_stat64 linux_st;
280 int rc = errno_value_call(
281 linux_syscall2(__NR_lstat64, (uintptr_t) file, (uintptr_t) &linux_st));
284 linux_stat_to_nacl_stat(&linux_st, st);
288 int mkdir(const char *path, mode_t mode) {
289 return errno_value_call(linux_syscall2(__NR_mkdir, (uintptr_t) path, mode));
292 int rmdir(const char *path) {
293 return errno_value_call(linux_syscall1(__NR_rmdir, (uintptr_t) path));
296 int chdir(const char *path) {
297 return errno_value_call(linux_syscall1(__NR_chdir, (uintptr_t) path));
300 char *getcwd(char *buffer, size_t len) {
301 int rc = errno_value_call(
302 linux_syscall2(__NR_getcwd, (uintptr_t) buffer, len));
308 int unlink(const char *path) {
309 return errno_value_call(linux_syscall1(__NR_unlink, (uintptr_t) path));
312 int truncate(const char *path, off_t length) {
313 uint32_t length_low = (uint32_t) length;
314 uint32_t length_high = length >> 32;
315 #if defined(__i386__)
316 return errno_value_call(
317 linux_syscall3(__NR_truncate64, (uintptr_t) path,
318 length_low, length_high));
319 #elif defined(__arm__)
321 * On ARM, a 64-bit parameter has to be in an even-odd register
322 * pair. Hence these calls ignore their second argument (r1) so that
323 * their third and fourth make such a pair (r2,r3).
325 return errno_value_call(
326 linux_syscall4(__NR_truncate64, (uintptr_t) path,
327 0 /* dummy */, length_low, length_high));
329 # error Unsupported architecture
333 int link(const char *oldpath, const char *newpath) {
334 return errno_value_call(
335 linux_syscall2(__NR_link, (uintptr_t) oldpath, (uintptr_t) newpath));
338 int rename(const char *oldpath, const char* newpath) {
339 return errno_value_call(
340 linux_syscall2(__NR_rename, (uintptr_t) oldpath, (uintptr_t) newpath));
343 int symlink(const char *oldpath, const char* newpath) {
344 return errno_value_call(
345 linux_syscall2(__NR_symlink, (uintptr_t) oldpath, (uintptr_t) newpath));
348 int chmod(const char *path, mode_t mode) {
349 return errno_value_call(
350 linux_syscall2(__NR_chmod, (uintptr_t) path, mode));
353 int access(const char *path, int amode) {
354 return errno_value_call(
355 linux_syscall2(__NR_access, (uintptr_t) path, amode));
358 int readlink(const char *path, char *buf, int bufsize) {
359 return errno_value_call(
360 linux_syscall3(__NR_readlink, (uintptr_t) path,
361 (uintptr_t) buf, bufsize));
364 int fcntl(int fd, int cmd, ...) {
365 if (cmd == F_GETFL || cmd == F_GETFD) {
366 return errno_value_call(linux_syscall2(__NR_fcntl64, fd, cmd));
368 if (cmd == F_SETFL || cmd == F_SETFD) {
371 int32_t arg = va_arg(ap, int32_t);
373 return errno_value_call(linux_syscall3(__NR_fcntl64, fd, cmd, arg));
375 /* We only support the fcntl commands above. */
381 return errno_value_call(linux_syscall0(__NR_getpid));
385 /* Set SIGCHLD as flag so we can wait. */
386 return errno_value_call(
387 linux_syscall5(__NR_clone, LINUX_SIGCHLD,
388 0 /* stack */, 0 /* ptid */, 0 /* tls */, 0 /* ctid */));
391 #if defined(__i386__) || defined(__arm__)
392 struct linux_termios {
401 # error Unsupported architecture
405 struct linux_termios term;
406 return errno_value_call(
407 linux_syscall3(__NR_ioctl, fd, LINUX_TCGETS, (uintptr_t) &term)) == 0;
410 int pipe(int pipefd[2]) {
411 return errno_value_call(linux_syscall1(__NR_pipe, (uintptr_t) pipefd));
414 int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
415 return errno_value_call(
416 linux_syscall3(__NR_poll, (uintptr_t) fds, nfds, timeout));
419 int prctl(int option, uintptr_t arg2, uintptr_t arg3,
420 uintptr_t arg4, uintptr_t arg5) {
421 return errno_value_call(
422 linux_syscall5(__NR_prctl, option, arg2, arg3, arg4, arg5));
425 #if defined(__i386__)
426 /* On x86-32 Linux, socket related syscalls are defined by using socketcall. */
428 static uintptr_t socketcall(int op, void *args) {
429 return errno_value_call(
430 linux_syscall2(__NR_socketcall, op, (uintptr_t) args));
433 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
434 uint32_t args[] = { sockfd, (uintptr_t) msg, flags };
435 return socketcall(SYS_RECVMSG, args);
438 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
439 uint32_t args[] = { sockfd, (uintptr_t) msg, flags };
440 return socketcall(SYS_SENDMSG, args);
443 int shutdown(int sockfd, int how) {
444 uint32_t args[] = { sockfd, how };
445 return socketcall(SYS_SHUTDOWN, args);
448 int socketpair(int domain, int type, int protocol, int sv[2]) {
449 uint32_t args[] = { domain, type, protocol, (uintptr_t) sv };
450 return socketcall(SYS_SOCKETPAIR, args);
453 #elif defined(__arm__)
454 /* On ARM Linux, socketcall is not defined. Instead use each syscall. */
456 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
457 return errno_value_call(
458 linux_syscall3(__NR_recvmsg, sockfd, (uintptr_t) msg, flags));
461 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
462 return errno_value_call(
463 linux_syscall3(__NR_sendmsg, sockfd, (uintptr_t) msg, flags));
466 int shutdown(int sockfd, int how) {
467 return errno_value_call(linux_syscall2(__NR_shutdown, sockfd, how));
470 int socketpair(int domain, int type, int protocol, int sv[2]) {
471 return errno_value_call(
472 linux_syscall4(__NR_socketpair, domain, type, protocol, (uintptr_t) sv));
476 # error Unsupported architecture
479 pid_t waitpid(pid_t pid, int *status, int options) {
480 return errno_value_call(
481 linux_syscall4(__NR_wait4, pid, (uintptr_t) status, options,
485 int linux_sigaction(int signum, const struct linux_sigaction *act,
486 struct linux_sigaction *oldact) {
487 /* This is the size of Linux kernel's sigset_t. */
488 const int kSigsetSize = 8;
490 * We do not support returning from a signal handler invoked by a
491 * real time signal. To support this, we need to set sa_restorer
492 * when it is not set by the caller, but we probably will not need
493 * this. See the following for how we do it.
494 * https://code.google.com/p/linux-syscall-support/source/browse/trunk/lss/linux_syscall_support.h
496 return errno_value_call(
497 linux_syscall4(__NR_rt_sigaction, signum,
498 (uintptr_t) act, (uintptr_t) oldact, kSigsetSize));
502 * Obtain Linux signal number from portable signal number.
504 static int nacl_signum_to_linux_signum(int signum) {
505 /* SIGSTKFLT is not defined in newlib, hence no mapping. */
506 #define HANDLE_SIGNUM(SIGNUM) case SIGNUM: return LINUX_##SIGNUM;
508 HANDLE_SIGNUM(SIGHUP);
509 HANDLE_SIGNUM(SIGINT);
510 HANDLE_SIGNUM(SIGQUIT);
511 HANDLE_SIGNUM(SIGILL);
512 HANDLE_SIGNUM(SIGTRAP);
513 HANDLE_SIGNUM(SIGABRT);
514 HANDLE_SIGNUM(SIGBUS);
515 HANDLE_SIGNUM(SIGFPE);
516 HANDLE_SIGNUM(SIGKILL);
517 HANDLE_SIGNUM(SIGUSR1);
518 HANDLE_SIGNUM(SIGSEGV);
519 HANDLE_SIGNUM(SIGUSR2);
520 HANDLE_SIGNUM(SIGPIPE);
521 HANDLE_SIGNUM(SIGALRM);
522 HANDLE_SIGNUM(SIGTERM);
523 HANDLE_SIGNUM(SIGSYS);
530 sighandler_t signal(int signum, sighandler_t handler) {
531 int linux_signum = nacl_signum_to_linux_signum(signum);
532 if (linux_signum == -1)
535 struct linux_sigaction sa;
536 memset(&sa, 0, sizeof(sa));
538 * In Linux's sigaction, sa_sigaction and sa_handler share the same
539 * memory region by union.
541 sa.sa_sigaction = (void (*)(int, linux_siginfo_t *, void *)) handler;
542 sa.sa_flags = LINUX_SA_RESTART;
543 sigemptyset(&sa.sa_mask);
544 sigaddset(&sa.sa_mask, linux_signum);
545 struct linux_sigaction osa;
546 int result = linux_sigaction(linux_signum, &sa, &osa);
549 return (sighandler_t) osa.sa_sigaction;
553 * This is a stub since _start will call it but we don't want to
554 * do the normal initialization.
556 void __libnacl_irt_init(Elf32_auxv_t *auxv) {
559 int nacl_tls_init(void *thread_ptr) {
560 #if defined(__i386__)
561 struct linux_user_desc desc = create_linux_user_desc(
562 1 /* allocate_new_entry */, thread_ptr);
563 uint32_t result = linux_syscall1(__NR_set_thread_area, (uint32_t) &desc);
567 * Leave the segment selector's bit 2 (table indicator) as zero because
568 * set_thread_area() always allocates an entry in the GDT.
570 int privilege_level = 3;
571 int gs_segment_selector = (desc.entry_number << 3) + privilege_level;
572 __asm__("mov %0, %%gs" : : "r"(gs_segment_selector));
573 #elif defined(__arm__)
574 uint32_t result = linux_syscall1(__NR_ARM_set_tls, (uint32_t) thread_ptr);
578 # error Unsupported architecture
581 * Sanity check: Ensure that the thread pointer reads back correctly.
582 * This checks that the set_thread_area() syscall worked and that the
583 * thread pointer points to itself, which is required on x86-32.
585 if (__nacl_read_tp() != thread_ptr)
590 void *nacl_tls_get(void) {
592 #if defined(__i386__)
593 __asm__("mov %%gs:0, %0" : "=r"(result));
594 #elif defined(__arm__)
595 __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(result));