Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / src / nonsfi / irt / irt_interfaces.c
1 /*
2  * Copyright (c) 2013 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 #include "native_client/src/nonsfi/irt/irt_interfaces.h"
8
9 #include <assert.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <limits.h>
13 #include <pthread.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/mman.h>
18 #include <sys/stat.h>
19 #include <sys/syscall.h>
20 #include <unistd.h>
21
22 #if defined(__linux__)
23 # include <linux/futex.h>
24 #endif
25
26 #include "native_client/src/include/elf32.h"
27 #include "native_client/src/include/elf_auxv.h"
28 #include "native_client/src/include/nacl_macros.h"
29 #include "native_client/src/trusted/service_runtime/include/machine/_types.h"
30 #include "native_client/src/trusted/service_runtime/include/sys/mman.h"
31 #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
32 #include "native_client/src/trusted/service_runtime/include/sys/time.h"
33 #include "native_client/src/trusted/service_runtime/include/sys/unistd.h"
34 #include "native_client/src/untrusted/irt/irt.h"
35 #include "native_client/src/untrusted/irt/irt_dev.h"
36
37 /*
38  * This is an implementation of NaCl's IRT interfaces that runs
39  * outside of the NaCl sandbox.
40  *
41  * This allows PNaCl to be used as a portability layer without the
42  * SFI-based sandboxing.  PNaCl pexes can be translated to
43  * non-SFI-sandboxed native code and linked against this IRT
44  * implementation.
45  */
46
47
48 #if defined(__ANDROID__) && !defined(FUTEX_PRIVATE_FLAG)
49 /* Android's Linux headers currently don't define this flag. */
50 # define FUTEX_PRIVATE_FLAG 128
51 #endif
52
53 #if defined(__GLIBC__)
54 /*
55  * glibc's headers will define st_atimensec etc. fields, but only if
56  * _POSIX_SOURCE is defined, which disables many other declarations,
57  * such as nanosleep(), getpagesize(), MAP_ANON and clock_gettime().
58  */
59 # define st_atimensec st_atim.tv_nsec
60 # define st_mtimensec st_mtim.tv_nsec
61 # define st_ctimensec st_ctim.tv_nsec
62 #elif defined(__APPLE__)
63 /*
64  * Similarly, Mac OS X's headers will define st_atimensec etc. fields,
65  * but only if _POSIX_SOURCE is defined, which disables declarations
66  * such as _SC_NPROCESSORS_ONLN.
67  */
68 # define st_atimensec st_atimespec.tv_nsec
69 # define st_mtimensec st_mtimespec.tv_nsec
70 # define st_ctimensec st_ctimespec.tv_nsec
71 #endif
72
73 void _user_start(void *info);
74 void _start(void *info);
75
76 /* TODO(mseaborn): Make threads work on Mac OS X. */
77 #if defined(__APPLE__)
78 # define __thread /* nothing */
79 #endif
80 static __thread void *g_tls_value;
81
82
83 /*
84  * The IRT functions in irt.h are declared as taking "struct timespec"
85  * and "struct timeval" pointers, but these are really "struct
86  * nacl_abi_timespec" and "struct nacl_abi_timeval" pointers in this
87  * unsandboxed context.
88  *
89  * To avoid changing irt.h for now and also avoid casting function
90  * pointers, we use the same type signatures as in irt.h and do the
91  * casting here.
92  */
93 static void convert_from_nacl_timespec(struct timespec *dest,
94                                        const struct timespec *src_nacl) {
95   const struct nacl_abi_timespec *src =
96       (const struct nacl_abi_timespec *) src_nacl;
97   dest->tv_sec = src->tv_sec;
98   dest->tv_nsec = src->tv_nsec;
99 }
100
101 static void convert_to_nacl_timespec(struct timespec *dest_nacl,
102                                      const struct timespec *src) {
103   struct nacl_abi_timespec *dest = (struct nacl_abi_timespec *) dest_nacl;
104   dest->tv_sec = src->tv_sec;
105   dest->tv_nsec = src->tv_nsec;
106 }
107
108 static void convert_to_nacl_timeval(struct timeval *dest_nacl,
109                                     const struct timeval *src) {
110   struct nacl_abi_timeval *dest = (struct nacl_abi_timeval *) dest_nacl;
111   dest->nacl_abi_tv_sec = src->tv_sec;
112   dest->nacl_abi_tv_usec = src->tv_usec;
113 }
114
115 static void convert_to_nacl_stat(struct stat *dest_nacl,
116                                  const struct stat *src) {
117   struct nacl_abi_stat *dest = (struct nacl_abi_stat *) dest_nacl;
118   dest->nacl_abi_st_dev = src->st_dev;
119   dest->nacl_abi_st_ino = src->st_ino;
120   dest->nacl_abi_st_mode = src->st_mode;
121   dest->nacl_abi_st_nlink = src->st_nlink;
122   dest->nacl_abi_st_uid = src->st_uid;
123   dest->nacl_abi_st_gid = src->st_gid;
124   dest->nacl_abi_st_rdev = src->st_rdev;
125   dest->nacl_abi_st_size = src->st_size;
126   dest->nacl_abi_st_blksize = src->st_blksize;
127   dest->nacl_abi_st_blocks = src->st_blocks;
128   dest->nacl_abi_st_atime = src->st_atime;
129   dest->nacl_abi_st_atimensec = src->st_atimensec;
130   dest->nacl_abi_st_mtime = src->st_mtime;
131   dest->nacl_abi_st_mtimensec = src->st_mtimensec;
132   dest->nacl_abi_st_ctime = src->st_ctime;
133   dest->nacl_abi_st_ctimensec = src->st_ctimensec;
134 }
135
136 static void copy_flag(int *dest, int src, int new_flag, int old_flag) {
137   if ((src & old_flag) != 0)
138     *dest |= new_flag;
139 }
140
141 /* Returns whether the conversion was successful. */
142 static int convert_from_nacl_mmap_prot(int *prot, int prot_nacl) {
143   if ((prot_nacl & ~NACL_ABI_PROT_MASK) != 0)
144     return 0;
145   *prot = 0;
146   copy_flag(prot, prot_nacl, PROT_READ, NACL_ABI_PROT_READ);
147   copy_flag(prot, prot_nacl, PROT_WRITE, NACL_ABI_PROT_WRITE);
148   copy_flag(prot, prot_nacl, PROT_EXEC, NACL_ABI_PROT_EXEC);
149   return 1;
150 }
151
152 /* Returns whether the conversion was successful. */
153 static int convert_from_nacl_mmap_flags(int *flags, int flags_nacl) {
154   int allowed = NACL_ABI_MAP_SHARED |
155                 NACL_ABI_MAP_PRIVATE |
156                 NACL_ABI_MAP_FIXED |
157                 NACL_ABI_MAP_ANON;
158   if ((flags_nacl & ~allowed) != 0)
159     return 0;
160   *flags = 0;
161   copy_flag(flags, flags_nacl, MAP_SHARED, NACL_ABI_MAP_SHARED);
162   copy_flag(flags, flags_nacl, MAP_PRIVATE, NACL_ABI_MAP_PRIVATE);
163   copy_flag(flags, flags_nacl, MAP_FIXED, NACL_ABI_MAP_FIXED);
164   copy_flag(flags, flags_nacl, MAP_ANON, NACL_ABI_MAP_ANON);
165   return 1;
166 }
167
168 static int check_error(int result) {
169   if (result != 0) {
170     /*
171      * Check that we really have an error and don't indicate success
172      * mistakenly.
173      */
174     assert(errno != 0);
175     return errno;
176   }
177   return 0;
178 }
179
180 static int irt_close(int fd) {
181   return check_error(close(fd));
182 }
183
184 static int irt_dup(int fd, int *new_fd) {
185   int result = dup(fd);
186   if (result < 0)
187     return errno;
188   *new_fd = result;
189   return 0;
190 }
191
192 static int irt_dup2(int fd, int new_fd) {
193   int result = dup2(fd, new_fd);
194   if (result < 0)
195     return errno;
196   assert(result == new_fd);
197   return 0;
198 }
199
200 static int irt_read(int fd, void *buf, size_t count, size_t *nread) {
201   int result = read(fd, buf, count);
202   if (result < 0)
203     return errno;
204   *nread = result;
205   return 0;
206 }
207
208 static int irt_write(int fd, const void *buf, size_t count, size_t *nwrote) {
209   int result = write(fd, buf, count);
210   if (result < 0)
211     return errno;
212   *nwrote = result;
213   return 0;
214 }
215
216 static int irt_seek(int fd, nacl_abi_off_t offset, int whence,
217                     nacl_abi_off_t *new_offset) {
218   off_t result = lseek(fd, offset, whence);
219   if (result < 0)
220     return errno;
221   *new_offset = result;
222   return 0;
223 }
224
225 static int irt_fstat(int fd, struct stat *st) {
226   /* TODO(mseaborn): Implement this and convert "struct stat". */
227   return ENOSYS;
228 }
229
230 static void irt_exit(int status) {
231   _exit(status);
232 }
233
234 static int irt_clock_func(clock_t *ticks) {
235   clock_t result = clock();
236   if (result == (clock_t) -1)
237     return errno;
238   *ticks = result;
239   return 0;
240 }
241
242 static int irt_gettod(struct timeval *time_nacl) {
243   struct timeval time;
244   int result = check_error(gettimeofday(&time, NULL));
245   convert_to_nacl_timeval(time_nacl, &time);
246   return result;
247 }
248
249 static int irt_sched_yield(void) {
250   return check_error(sched_yield());
251 }
252
253 static int irt_nanosleep(const struct timespec *requested_nacl,
254                          struct timespec *remaining_nacl) {
255   struct timespec requested;
256   struct timespec remaining;
257   convert_from_nacl_timespec(&requested, requested_nacl);
258   int result = check_error(nanosleep(&requested, &remaining));
259   if (remaining_nacl != NULL)
260     convert_to_nacl_timespec(remaining_nacl, &remaining);
261   return result;
262 }
263
264 static int irt_sysconf(int name, int *value) {
265   switch (name) {
266     case NACL_ABI__SC_PAGESIZE:
267       /*
268        * For now, return the host's page size (typically 4k) rather
269        * than 64k (NaCl's usual page size), which pexes will usually
270        * be tested with.  We could change this to 64k, but then the
271        * mmap() we define here should round up requested sizes to
272        * multiples of 64k.
273        */
274       *value = getpagesize();
275       return 0;
276     case NACL_ABI__SC_NPROCESSORS_ONLN: {
277       int result = sysconf(_SC_NPROCESSORS_ONLN);
278       if (result == 0)
279         return errno;
280       *value = result;
281       return 0;
282     }
283     default:
284       return EINVAL;
285   }
286 }
287
288 static int irt_mmap(void **addr, size_t len, int prot, int flags,
289                     int fd, nacl_irt_off_t off) {
290   int host_prot;
291   int host_flags;
292   if (!convert_from_nacl_mmap_prot(&host_prot, prot) ||
293       !convert_from_nacl_mmap_flags(&host_flags, flags)) {
294     return EINVAL;
295   }
296   void *result = mmap(*addr, len, host_prot, host_flags, fd, off);
297   if (result == MAP_FAILED)
298     return errno;
299   *addr = result;
300   return 0;
301 }
302
303 static int irt_munmap(void *addr, size_t len) {
304   return check_error(munmap(addr, len));
305 }
306
307 static int tls_init(void *ptr) {
308   g_tls_value = ptr;
309   return 0;
310 }
311
312 static void *tls_get(void) {
313   return g_tls_value;
314 }
315
316 void *__nacl_read_tp(void) {
317   return g_tls_value;
318 }
319
320 struct thread_args {
321   void (*start_func)(void);
322   void *thread_ptr;
323 };
324
325 static void *start_thread(void *arg) {
326   struct thread_args args = *(struct thread_args *) arg;
327   free(arg);
328   g_tls_value = args.thread_ptr;
329   args.start_func();
330   abort();
331 }
332
333 static int thread_create(void (*start_func)(void), void *stack,
334                          void *thread_ptr) {
335   /*
336    * For now, we ignore the stack that user code provides and just use
337    * the stack that the host libpthread allocates.
338    */
339   pthread_attr_t attr;
340   int error = pthread_attr_init(&attr);
341   if (error != 0)
342     return error;
343   error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
344   if (error != 0)
345     return error;
346   struct thread_args *args = malloc(sizeof(struct thread_args));
347   if (args == NULL) {
348     error = ENOMEM;
349     goto cleanup;
350   }
351   args->start_func = start_func;
352   args->thread_ptr = thread_ptr;
353   pthread_t tid;
354   error = pthread_create(&tid, &attr, start_thread, args);
355   if (error != 0)
356     free(args);
357  cleanup:
358   pthread_attr_destroy(&attr);
359   return error;
360 }
361
362 static void thread_exit(int32_t *stack_flag) {
363   *stack_flag = 0;  /* Indicate that the user code's stack can be freed. */
364   pthread_exit(NULL);
365 }
366
367 static int thread_nice(const int nice) {
368   return 0;
369 }
370
371 /*
372  * Mac OS X does not provide futexes or clock_gettime()/getres() natively.
373  * TODO(mseaborn):  Make threads and clock_gettime() work on Mac OS X.
374  */
375 #if defined(__linux__)
376 static int futex_wait_abs(volatile int *addr, int value,
377                           const struct timespec *abstime_nacl) {
378   struct timespec reltime;
379   struct timespec *reltime_ptr = NULL;
380   if (abstime_nacl != NULL) {
381     struct timespec time_now;
382     if (clock_gettime(CLOCK_REALTIME, &time_now) != 0)
383       return errno;
384
385     /* Convert the absolute time to a relative time. */
386     const struct nacl_abi_timespec *abstime =
387         (const struct nacl_abi_timespec *) abstime_nacl;
388     reltime.tv_sec = abstime->tv_sec - time_now.tv_sec;
389     reltime.tv_nsec = abstime->tv_nsec - time_now.tv_nsec;
390     if (reltime.tv_nsec < 0) {
391       reltime.tv_sec -= 1;
392       reltime.tv_nsec += 1000000000;
393     }
394     /*
395      * Linux's FUTEX_WAIT returns EINVAL if given a negative relative
396      * time.  But an absolute time that's in the past is a valid
397      * argument, for which we need to return ETIMEDOUT instead.
398      */
399     if (reltime.tv_sec < 0)
400       return ETIMEDOUT;
401     reltime_ptr = &reltime;
402   }
403   return check_error(syscall(__NR_futex, addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG,
404                              value, reltime_ptr, 0, 0));
405 }
406
407 static int futex_wake(volatile int *addr, int nwake, int *count) {
408   int result = syscall(__NR_futex, addr, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
409                        nwake, 0, 0, 0);
410   if (result < 0)
411     return errno;
412   *count = result;
413   return 0;
414 }
415
416 static int irt_clock_getres(nacl_irt_clockid_t clk_id,
417                             struct timespec *time_nacl) {
418   struct timespec time;
419   int result = check_error(clock_getres(clk_id, &time));
420   convert_to_nacl_timespec(time_nacl, &time);
421   return result;
422 }
423
424 static int irt_clock_gettime(nacl_irt_clockid_t clk_id,
425                              struct timespec *time_nacl) {
426   struct timespec time;
427   int result = check_error(clock_gettime(clk_id, &time));
428   convert_to_nacl_timespec(time_nacl, &time);
429   return result;
430 }
431 #endif
432
433 static int irt_open(const char *pathname, int flags, mode_t mode, int *new_fd) {
434   int fd = open(pathname, flags, mode);
435   if (fd < 0)
436     return errno;
437   *new_fd = fd;
438   return 0;
439 }
440
441 static int irt_stat(const char *pathname, struct stat *stat_info_nacl) {
442   struct stat stat_info;
443   if (stat(pathname, &stat_info) != 0)
444     return errno;
445   convert_to_nacl_stat(stat_info_nacl, &stat_info);
446   return 0;
447 }
448
449 static int irt_mkdir(const char *pathname, mode_t mode) {
450   return check_error(mkdir(pathname, mode));
451 }
452
453 static int irt_rmdir(const char *pathname) {
454   return check_error(rmdir(pathname));
455 }
456
457 static int irt_chdir(const char *pathname) {
458   return check_error(chdir(pathname));
459 }
460
461 static int irt_getcwd(char *pathname, size_t len) {
462   if (getcwd(pathname, len) == NULL)
463     return errno;
464   return 0;
465 }
466
467 static int irt_unlink(const char *pathname) {
468   return check_error(unlink(pathname));
469 }
470
471 static int irt_getpid(int *pid) {
472   *pid = getpid();
473   return 0;
474 }
475
476 static void irt_stub_func(const char *name) {
477   fprintf(stderr, "Error: Unimplemented IRT function: %s\n", name);
478   abort();
479 }
480
481 #define DEFINE_STUB(name) \
482     static void irt_stub_##name() { irt_stub_func(#name); }
483 #define USE_STUB(s, name) (__typeof__(s.name)) irt_stub_##name
484
485 static const struct nacl_irt_basic irt_basic = {
486   irt_exit,
487   irt_gettod,
488   irt_clock_func,
489   irt_nanosleep,
490   irt_sched_yield,
491   irt_sysconf,
492 };
493
494 DEFINE_STUB(getdents)
495 static const struct nacl_irt_fdio irt_fdio = {
496   irt_close,
497   irt_dup,
498   irt_dup2,
499   irt_read,
500   irt_write,
501   irt_seek,
502   irt_fstat,
503   USE_STUB(irt_fdio, getdents),
504 };
505
506 DEFINE_STUB(mprotect)
507 static const struct nacl_irt_memory irt_memory = {
508   irt_mmap,
509   irt_munmap,
510   USE_STUB(irt_memory, mprotect),
511 };
512
513 static const struct nacl_irt_tls irt_tls = {
514   tls_init,
515   tls_get,
516 };
517
518 static const struct nacl_irt_thread irt_thread = {
519   thread_create,
520   thread_exit,
521   thread_nice,
522 };
523
524 #if defined(__linux__)
525 static const struct nacl_irt_futex irt_futex = {
526   futex_wait_abs,
527   futex_wake,
528 };
529
530 static const struct nacl_irt_clock irt_clock = {
531   irt_clock_getres,
532   irt_clock_gettime,
533 };
534 #else
535 DEFINE_STUB(futex_wait_abs)
536 DEFINE_STUB(futex_wake)
537 static const struct nacl_irt_futex irt_futex = {
538   USE_STUB(irt_futex, futex_wait_abs),
539   USE_STUB(irt_futex, futex_wake),
540 };
541 #endif
542
543 DEFINE_STUB(truncate)
544 DEFINE_STUB(lstat)
545 DEFINE_STUB(link)
546 DEFINE_STUB(rename)
547 DEFINE_STUB(symlink)
548 DEFINE_STUB(chmod)
549 DEFINE_STUB(access)
550 DEFINE_STUB(readlink)
551 DEFINE_STUB(utimes)
552 static const struct nacl_irt_dev_filename irt_dev_filename = {
553   irt_open,
554   irt_stat,
555   irt_mkdir,
556   irt_rmdir,
557   irt_chdir,
558   irt_getcwd,
559   irt_unlink,
560   USE_STUB(irt_dev_filename, truncate),
561   USE_STUB(irt_dev_filename, lstat),
562   USE_STUB(irt_dev_filename, link),
563   USE_STUB(irt_dev_filename, rename),
564   USE_STUB(irt_dev_filename, symlink),
565   USE_STUB(irt_dev_filename, chmod),
566   USE_STUB(irt_dev_filename, access),
567   USE_STUB(irt_dev_filename, readlink),
568   USE_STUB(irt_dev_filename, utimes),
569 };
570
571 static const struct nacl_irt_dev_getpid irt_dev_getpid = {
572   irt_getpid,
573 };
574
575 struct nacl_interface_table {
576   const char *name;
577   const void *table;
578   size_t size;
579 };
580
581 static const struct nacl_interface_table irt_interfaces[] = {
582   { NACL_IRT_BASIC_v0_1, &irt_basic, sizeof(irt_basic) },
583   { NACL_IRT_FDIO_v0_1, &irt_fdio, sizeof(irt_fdio) },
584   { NACL_IRT_MEMORY_v0_3, &irt_memory, sizeof(irt_memory) },
585   { NACL_IRT_TLS_v0_1, &irt_tls, sizeof(irt_tls) },
586   { NACL_IRT_THREAD_v0_1, &irt_thread, sizeof(irt_thread) },
587   { NACL_IRT_FUTEX_v0_1, &irt_futex, sizeof(irt_futex) },
588 #if defined(__linux__)
589   { NACL_IRT_CLOCK_v0_1, &irt_clock, sizeof(irt_clock) },
590 #endif
591   { NACL_IRT_DEV_FILENAME_v0_3, &irt_dev_filename, sizeof(irt_dev_filename) },
592   { NACL_IRT_DEV_GETPID_v0_1, &irt_dev_getpid, sizeof(irt_dev_getpid) },
593 };
594
595 static size_t irt_interface_query(const char *interface_ident,
596                                   void *table, size_t tablesize) {
597   unsigned i;
598   for (i = 0; i < NACL_ARRAY_SIZE(irt_interfaces); ++i) {
599     if (0 == strcmp(interface_ident, irt_interfaces[i].name)) {
600       const size_t size = irt_interfaces[i].size;
601       if (size <= tablesize) {
602         memcpy(table, irt_interfaces[i].table, size);
603         return size;
604       }
605       break;
606     }
607   }
608   fprintf(stderr, "Warning: unavailable IRT interface queried: %s\n",
609           interface_ident);
610   return 0;
611 }
612
613 int nacl_irt_nonsfi_entry(int argc, char **argv, char **environ,
614                           nacl_entry_func_t entry_func) {
615   /* Find size of environ array. */
616   size_t env_count = 0;
617   while (environ[env_count] != NULL)
618     env_count++;
619
620   size_t count =
621       1  /* cleanup_func pointer */
622       + 2  /* envc and argc counts */
623       + argc + 1  /* argv array, with terminator */
624       + env_count + 1  /* environ array, with terminator */
625       + 4;  /* auxv: 2 entries, one of them the terminator */
626   uintptr_t *data = malloc(count * sizeof(uintptr_t));
627   if (data == NULL) {
628     fprintf(stderr, "Failed to allocate argv/env/auxv array\n");
629     return 1;
630   }
631   size_t pos = 0;
632   data[pos++] = 0;  /* cleanup_func pointer */
633   data[pos++] = env_count;
634   data[pos++] = argc;
635   /* Copy arrays, with terminators. */
636   size_t i;
637   for (i = 0; i < (size_t) argc; i++)
638     data[pos++] = (uintptr_t) argv[i];
639   data[pos++] = 0;
640   for (i = 0; i < env_count; i++)
641     data[pos++] = (uintptr_t) environ[i];
642   data[pos++] = 0;
643   /* auxv[0] */
644   data[pos++] = AT_SYSINFO;
645   data[pos++] = (uintptr_t) irt_interface_query;
646   /* auxv[1] */
647   data[pos++] = 0;
648   data[pos++] = 0;
649   assert(pos == count);
650
651   entry_func(data);
652   return 1;
653 }
654
655 #if defined(DEFINE_MAIN)
656 int main(int argc, char **argv, char **environ) {
657   /*
658    * On Linux, we rename _start() to _user_start() to avoid a clash
659    * with the "_start" routine in the host toolchain.  On Mac OS X,
660    * lacking objcopy, doing the symbol renaming is trickier, but also
661    * unnecessary, because the host toolchain doesn't have a "_start"
662    * routine.
663    */
664   nacl_entry_func_t entry_func =
665 #if defined(__APPLE__)
666     _start;
667 #else
668     _user_start;
669 #endif
670
671   return nacl_irt_nonsfi_entry(argc, argv, environ, entry_func);
672 }
673 #endif