Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / native_client / src / nonsfi / linux / linux_sys_private.c
1 /*
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.
5  */
6
7 /*
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.
11  */
12
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <sched.h>
16 #include <signal.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include <sys/mman.h>
20 #include <sys/time.h>
21 #include <time.h>
22 #include <unistd.h>
23
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"
35
36
37 /*
38  * Note that Non-SFI NaCl uses a 4k page size, in contrast to SFI NaCl's
39  * 64k page size.
40  */
41 static const int kPageSize = 0x1000;
42
43 static uintptr_t errno_value_call(uintptr_t result) {
44   if (linux_is_error_result(result)) {
45     errno = -result;
46     return -1;
47   }
48   return result;
49 }
50
51 void _exit(int status) {
52   linux_syscall1(__NR_exit_group, status);
53   __builtin_trap();
54 }
55
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));
60   if (result == 0)
61     linux_timeval_to_nacl_timeval(&linux_tv, tv);
62   return result;
63 }
64
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));
72
73   /*
74    * NaCl does not support async signals, so we don't fill out rem on
75    * result == -EINTR.
76    */
77   if (result == 0 && rem != NULL)
78     linux_timespec_to_nacl_timespec(&linux_rem, rem);
79   return result;
80 }
81
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));
86   if (result == 0)
87     linux_timespec_to_nacl_timespec(&linux_ts, ts);
88   return result;
89 }
90
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);
98   return result;
99 }
100
101 int sched_yield(void) {
102   return errno_value_call(linux_syscall0(__NR_sched_yield));
103 }
104
105 long int sysconf(int name) {
106   switch (name) {
107     case _SC_PAGESIZE:
108       return kPageSize;
109   }
110   errno = EINVAL;
111   return -1;
112 }
113
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. */
120     errno = EINVAL;
121     return MAP_FAILED;
122   }
123   offset >>= kPageBits;
124
125   return (void *) errno_value_call(
126       linux_syscall6(__NR_mmap2, (uintptr_t) start, length,
127                      prot, flags, fd, offset));
128 #else
129 # error Unsupported architecture
130 #endif
131 }
132
133 void *mmap(void *start, size_t length, int prot, int flags,
134            int fd, off_t offset) {
135   /*
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.
139    */
140   void *result =
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) {
144       /*
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).
147        */
148       static const char msg[] =
149           "mprotect() in mmap() to set PROT_EXEC failed.";
150       write(2, msg, sizeof(msg) - 1);
151       abort();
152     }
153   }
154   return result;
155 }
156
157 int munmap(void *start, size_t length) {
158   return errno_value_call(
159       linux_syscall2(__NR_munmap, (uintptr_t) start, length));
160 }
161
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));
165 }
166
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));
170 }
171
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));
175 }
176
177 int open(char const *pathname, int oflag, ...) {
178   mode_t cmode;
179   va_list ap;
180
181   if (oflag & O_CREAT) {
182     va_start(ap, oflag);
183     cmode = va_arg(ap, mode_t);
184     va_end(ap);
185   } else {
186     cmode = 0;
187   }
188
189   return errno_value_call(
190       linux_syscall3(__NR_open, (uintptr_t) pathname, oflag, cmode));
191 }
192
193 int close(int fd) {
194   return errno_value_call(linux_syscall1(__NR_close, fd));
195 }
196
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__)
205   /*
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).
209    */
210   return errno_value_call(
211       linux_syscall6(__NR_pread64, fd, (uintptr_t) buf, count,
212                      0  /* dummy */, offset_low, offset_high));
213 #else
214 # error Unsupported architecture
215 #endif
216 }
217
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));
229 #else
230 # error Unsupported architecture
231 #endif
232 }
233
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;
238   off_t result;
239   int rc = errno_value_call(
240       linux_syscall5(__NR__llseek, fd, offset_high, offset_low,
241                      (uintptr_t) &result, whence));
242   if (rc == -1)
243     return -1;
244   return result;
245 #else
246 # error Unsupported architecture
247 #endif
248 }
249
250 int dup(int fd) {
251   return errno_value_call(linux_syscall1(__NR_dup, fd));
252 }
253
254 int dup2(int oldfd, int newfd) {
255   return errno_value_call(linux_syscall2(__NR_dup2, oldfd, newfd));
256 }
257
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));
262   if (rc == -1)
263     return -1;
264   linux_stat_to_nacl_stat(&linux_st, st);
265   return 0;
266 }
267
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));
272   if (rc == -1)
273     return -1;
274   linux_stat_to_nacl_stat(&linux_st, st);
275   return 0;
276 }
277
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));
282   if (rc == -1)
283     return -1;
284   linux_stat_to_nacl_stat(&linux_st, st);
285   return 0;
286 }
287
288 int mkdir(const char *path, mode_t mode) {
289   return errno_value_call(linux_syscall2(__NR_mkdir, (uintptr_t) path, mode));
290 }
291
292 int rmdir(const char *path) {
293   return errno_value_call(linux_syscall1(__NR_rmdir, (uintptr_t) path));
294 }
295
296 int chdir(const char *path) {
297   return errno_value_call(linux_syscall1(__NR_chdir, (uintptr_t) path));
298 }
299
300 char *getcwd(char *buffer, size_t len) {
301   int rc = errno_value_call(
302       linux_syscall2(__NR_getcwd, (uintptr_t) buffer, len));
303   if (rc == -1)
304     return NULL;
305   return buffer;
306 }
307
308 int unlink(const char *path) {
309   return errno_value_call(linux_syscall1(__NR_unlink, (uintptr_t) path));
310 }
311
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__)
320   /*
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).
324    */
325   return errno_value_call(
326       linux_syscall4(__NR_truncate64, (uintptr_t) path,
327                      0  /* dummy */, length_low, length_high));
328 #else
329 # error Unsupported architecture
330 #endif
331 }
332
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));
336 }
337
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));
341 }
342
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));
346 }
347
348 int chmod(const char *path, mode_t mode) {
349   return errno_value_call(
350       linux_syscall2(__NR_chmod, (uintptr_t) path, mode));
351 }
352
353 int access(const char *path, int amode) {
354   return errno_value_call(
355       linux_syscall2(__NR_access, (uintptr_t) path, amode));
356 }
357
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));
362 }
363
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));
367   }
368   if (cmd == F_SETFL || cmd == F_SETFD) {
369     va_list ap;
370     va_start(ap, cmd);
371     int32_t arg = va_arg(ap, int32_t);
372     va_end(ap);
373     return errno_value_call(linux_syscall3(__NR_fcntl64, fd, cmd, arg));
374   }
375   /* We only support the fcntl commands above. */
376   errno = EINVAL;
377   return -1;
378 }
379
380 int getpid(void) {
381   return errno_value_call(linux_syscall0(__NR_getpid));
382 }
383
384 int fork(void) {
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 */));
389 }
390
391 #if defined(__i386__) || defined(__arm__)
392 struct linux_termios {
393   uint32_t c_iflag;
394   uint32_t c_oflag;
395   uint32_t c_cflag;
396   uint32_t c_lflag;
397   int8_t c_line;
398   int8_t c_cc[19];
399 };
400 #else
401 # error Unsupported architecture
402 #endif
403
404 int isatty(int fd) {
405   struct linux_termios term;
406   return errno_value_call(
407       linux_syscall3(__NR_ioctl, fd, LINUX_TCGETS, (uintptr_t) &term)) == 0;
408 }
409
410 int pipe(int pipefd[2]) {
411   return errno_value_call(linux_syscall1(__NR_pipe, (uintptr_t) pipefd));
412 }
413
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));
417 }
418
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));
423 }
424
425 #if defined(__i386__)
426 /* On x86-32 Linux, socket related syscalls are defined by using socketcall. */
427
428 static uintptr_t socketcall(int op, void *args) {
429   return errno_value_call(
430       linux_syscall2(__NR_socketcall, op, (uintptr_t) args));
431 }
432
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);
436 }
437
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);
441 }
442
443 int shutdown(int sockfd, int how) {
444   uint32_t args[] = { sockfd, how };
445   return socketcall(SYS_SHUTDOWN, args);
446 }
447
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);
451 }
452
453 #elif defined(__arm__)
454 /* On ARM Linux, socketcall is not defined. Instead use each syscall. */
455
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));
459 }
460
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));
464 }
465
466 int shutdown(int sockfd, int how) {
467   return errno_value_call(linux_syscall2(__NR_shutdown, sockfd, how));
468 }
469
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));
473 }
474
475 #else
476 # error Unsupported architecture
477 #endif
478
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,
482                      0  /* rusage */));
483 }
484
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;
489   /*
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
495    */
496   return errno_value_call(
497       linux_syscall4(__NR_rt_sigaction, signum,
498                      (uintptr_t) act, (uintptr_t) oldact, kSigsetSize));
499 }
500
501 /*
502  * Obtain Linux signal number from portable signal number.
503  */
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;
507   switch(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);
524   }
525 #undef HANDLE_SIGNUM
526   errno = EINVAL;
527   return -1;
528 }
529
530 sighandler_t signal(int signum, sighandler_t handler) {
531   int linux_signum = nacl_signum_to_linux_signum(signum);
532   if (linux_signum == -1)
533     return SIG_ERR;
534
535   struct linux_sigaction sa;
536   memset(&sa, 0, sizeof(sa));
537   /*
538    * In Linux's sigaction, sa_sigaction and sa_handler share the same
539    * memory region by union.
540    */
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);
547   if (result != 0)
548     return SIG_ERR;
549   return (sighandler_t) osa.sa_sigaction;
550 }
551
552 /*
553  * This is a stub since _start will call it but we don't want to
554  * do the normal initialization.
555  */
556 void __libnacl_irt_init(Elf32_auxv_t *auxv) {
557 }
558
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);
564   if (result != 0)
565     __builtin_trap();
566   /*
567    * Leave the segment selector's bit 2 (table indicator) as zero because
568    * set_thread_area() always allocates an entry in the GDT.
569    */
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);
575   if (result != 0)
576     __builtin_trap();
577 #else
578 # error Unsupported architecture
579 #endif
580   /*
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.
584    */
585   if (__nacl_read_tp() != thread_ptr)
586     __builtin_trap();
587   return 0;
588 }
589
590 void *nacl_tls_get(void) {
591   void *result;
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));
596 #endif
597   return result;
598 }