Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Unified Diff: pnacl/support/unsandboxed_irt.c

Issue 269703002: Non-SFI Mode: Add nonsfi_loader and plumbing to test it (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Review Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pnacl/support/unsandboxed_irt.c
diff --git a/pnacl/support/unsandboxed_irt.c b/pnacl/support/unsandboxed_irt.c
deleted file mode 100644
index acc774c4b0e6f8b30c5309dc309ee81ba0b5f928..0000000000000000000000000000000000000000
--- a/pnacl/support/unsandboxed_irt.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * Copyright (c) 2013 The Native Client Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#if defined(__linux__)
-# include <linux/futex.h>
-#endif
-
-#include "native_client/src/include/elf32.h"
-#include "native_client/src/include/elf_auxv.h"
-#include "native_client/src/include/nacl_macros.h"
-#include "native_client/src/trusted/service_runtime/include/machine/_types.h"
-#include "native_client/src/trusted/service_runtime/include/sys/mman.h"
-#include "native_client/src/trusted/service_runtime/include/sys/stat.h"
-#include "native_client/src/trusted/service_runtime/include/sys/time.h"
-#include "native_client/src/trusted/service_runtime/include/sys/unistd.h"
-#include "native_client/src/untrusted/irt/irt.h"
-#include "native_client/src/untrusted/irt/irt_dev.h"
-
-/*
- * This is an implementation of NaCl's IRT interfaces that runs
- * outside of the NaCl sandbox.
- *
- * This allows PNaCl to be used as a portability layer without the
- * SFI-based sandboxing. PNaCl pexes can be translated to
- * non-SFI-sandboxed native code and linked against this IRT
- * implementation.
- */
-
-
-#if defined(__ANDROID__) && !defined(FUTEX_PRIVATE_FLAG)
-/* Android's Linux headers currently don't define this flag. */
-# define FUTEX_PRIVATE_FLAG 128
-#endif
-
-#if defined(__GLIBC__)
-/*
- * glibc's headers will define st_atimensec etc. fields, but only if
- * _POSIX_SOURCE is defined, which disables many other declarations,
- * such as nanosleep(), getpagesize(), MAP_ANON and clock_gettime().
- */
-# define st_atimensec st_atim.tv_nsec
-# define st_mtimensec st_mtim.tv_nsec
-# define st_ctimensec st_ctim.tv_nsec
-#elif defined(__APPLE__)
-/*
- * Similarly, Mac OS X's headers will define st_atimensec etc. fields,
- * but only if _POSIX_SOURCE is defined, which disables declarations
- * such as _SC_NPROCESSORS_ONLN.
- */
-# define st_atimensec st_atimespec.tv_nsec
-# define st_mtimensec st_mtimespec.tv_nsec
-# define st_ctimensec st_ctimespec.tv_nsec
-#endif
-
-void _user_start(void *info);
-void _start(void *info);
-
-/* TODO(mseaborn): Make threads work on Mac OS X. */
-#if defined(__APPLE__)
-# define __thread /* nothing */
-#endif
-static __thread void *g_tls_value;
-
-
-/*
- * The IRT functions in irt.h are declared as taking "struct timespec"
- * and "struct timeval" pointers, but these are really "struct
- * nacl_abi_timespec" and "struct nacl_abi_timeval" pointers in this
- * unsandboxed context.
- *
- * To avoid changing irt.h for now and also avoid casting function
- * pointers, we use the same type signatures as in irt.h and do the
- * casting here.
- */
-static void convert_from_nacl_timespec(struct timespec *dest,
- const struct timespec *src_nacl) {
- const struct nacl_abi_timespec *src =
- (const struct nacl_abi_timespec *) src_nacl;
- dest->tv_sec = src->tv_sec;
- dest->tv_nsec = src->tv_nsec;
-}
-
-static void convert_to_nacl_timespec(struct timespec *dest_nacl,
- const struct timespec *src) {
- struct nacl_abi_timespec *dest = (struct nacl_abi_timespec *) dest_nacl;
- dest->tv_sec = src->tv_sec;
- dest->tv_nsec = src->tv_nsec;
-}
-
-static void convert_to_nacl_timeval(struct timeval *dest_nacl,
- const struct timeval *src) {
- struct nacl_abi_timeval *dest = (struct nacl_abi_timeval *) dest_nacl;
- dest->nacl_abi_tv_sec = src->tv_sec;
- dest->nacl_abi_tv_usec = src->tv_usec;
-}
-
-static void convert_to_nacl_stat(struct stat *dest_nacl,
- const struct stat *src) {
- struct nacl_abi_stat *dest = (struct nacl_abi_stat *) dest_nacl;
- dest->nacl_abi_st_dev = src->st_dev;
- dest->nacl_abi_st_ino = src->st_ino;
- dest->nacl_abi_st_mode = src->st_mode;
- dest->nacl_abi_st_nlink = src->st_nlink;
- dest->nacl_abi_st_uid = src->st_uid;
- dest->nacl_abi_st_gid = src->st_gid;
- dest->nacl_abi_st_rdev = src->st_rdev;
- dest->nacl_abi_st_size = src->st_size;
- dest->nacl_abi_st_blksize = src->st_blksize;
- dest->nacl_abi_st_blocks = src->st_blocks;
- dest->nacl_abi_st_atime = src->st_atime;
- dest->nacl_abi_st_atimensec = src->st_atimensec;
- dest->nacl_abi_st_mtime = src->st_mtime;
- dest->nacl_abi_st_mtimensec = src->st_mtimensec;
- dest->nacl_abi_st_ctime = src->st_ctime;
- dest->nacl_abi_st_ctimensec = src->st_ctimensec;
-}
-
-static void copy_flag(int *dest, int src, int new_flag, int old_flag) {
- if ((src & old_flag) != 0)
- *dest |= new_flag;
-}
-
-/* Returns whether the conversion was successful. */
-static int convert_from_nacl_mmap_prot(int *prot, int prot_nacl) {
- if ((prot_nacl & ~NACL_ABI_PROT_MASK) != 0)
- return 0;
- *prot = 0;
- copy_flag(prot, prot_nacl, PROT_READ, NACL_ABI_PROT_READ);
- copy_flag(prot, prot_nacl, PROT_WRITE, NACL_ABI_PROT_WRITE);
- copy_flag(prot, prot_nacl, PROT_EXEC, NACL_ABI_PROT_EXEC);
- return 1;
-}
-
-/* Returns whether the conversion was successful. */
-static int convert_from_nacl_mmap_flags(int *flags, int flags_nacl) {
- int allowed = NACL_ABI_MAP_SHARED |
- NACL_ABI_MAP_PRIVATE |
- NACL_ABI_MAP_FIXED |
- NACL_ABI_MAP_ANON;
- if ((flags_nacl & ~allowed) != 0)
- return 0;
- *flags = 0;
- copy_flag(flags, flags_nacl, MAP_SHARED, NACL_ABI_MAP_SHARED);
- copy_flag(flags, flags_nacl, MAP_PRIVATE, NACL_ABI_MAP_PRIVATE);
- copy_flag(flags, flags_nacl, MAP_FIXED, NACL_ABI_MAP_FIXED);
- copy_flag(flags, flags_nacl, MAP_ANON, NACL_ABI_MAP_ANON);
- return 1;
-}
-
-static int check_error(int result) {
- if (result != 0) {
- /*
- * Check that we really have an error and don't indicate success
- * mistakenly.
- */
- assert(errno != 0);
- return errno;
- }
- return 0;
-}
-
-static int irt_close(int fd) {
- return check_error(close(fd));
-}
-
-static int irt_dup(int fd, int *new_fd) {
- int result = dup(fd);
- if (result < 0)
- return errno;
- *new_fd = result;
- return 0;
-}
-
-static int irt_dup2(int fd, int new_fd) {
- int result = dup2(fd, new_fd);
- if (result < 0)
- return errno;
- assert(result == new_fd);
- return 0;
-}
-
-static int irt_read(int fd, void *buf, size_t count, size_t *nread) {
- int result = read(fd, buf, count);
- if (result < 0)
- return errno;
- *nread = result;
- return 0;
-}
-
-static int irt_write(int fd, const void *buf, size_t count, size_t *nwrote) {
- int result = write(fd, buf, count);
- if (result < 0)
- return errno;
- *nwrote = result;
- return 0;
-}
-
-static int irt_seek(int fd, nacl_abi_off_t offset, int whence,
- nacl_abi_off_t *new_offset) {
- off_t result = lseek(fd, offset, whence);
- if (result < 0)
- return errno;
- *new_offset = result;
- return 0;
-}
-
-static int irt_fstat(int fd, struct stat *st) {
- /* TODO(mseaborn): Implement this and convert "struct stat". */
- return ENOSYS;
-}
-
-static void irt_exit(int status) {
- _exit(status);
-}
-
-static int irt_clock_func(clock_t *ticks) {
- clock_t result = clock();
- if (result == (clock_t) -1)
- return errno;
- *ticks = result;
- return 0;
-}
-
-static int irt_gettod(struct timeval *time_nacl) {
- struct timeval time;
- int result = check_error(gettimeofday(&time, NULL));
- convert_to_nacl_timeval(time_nacl, &time);
- return result;
-}
-
-static int irt_sched_yield(void) {
- return check_error(sched_yield());
-}
-
-static int irt_nanosleep(const struct timespec *requested_nacl,
- struct timespec *remaining_nacl) {
- struct timespec requested;
- struct timespec remaining;
- convert_from_nacl_timespec(&requested, requested_nacl);
- int result = check_error(nanosleep(&requested, &remaining));
- if (remaining_nacl != NULL)
- convert_to_nacl_timespec(remaining_nacl, &remaining);
- return result;
-}
-
-static int irt_sysconf(int name, int *value) {
- switch (name) {
- case NACL_ABI__SC_PAGESIZE:
- /*
- * For now, return the host's page size (typically 4k) rather
- * than 64k (NaCl's usual page size), which pexes will usually
- * be tested with. We could change this to 64k, but then the
- * mmap() we define here should round up requested sizes to
- * multiples of 64k.
- */
- *value = getpagesize();
- return 0;
- case NACL_ABI__SC_NPROCESSORS_ONLN: {
- int result = sysconf(_SC_NPROCESSORS_ONLN);
- if (result == 0)
- return errno;
- *value = result;
- return 0;
- }
- default:
- return EINVAL;
- }
-}
-
-static int irt_mmap(void **addr, size_t len, int prot, int flags,
- int fd, nacl_irt_off_t off) {
- int host_prot;
- int host_flags;
- if (!convert_from_nacl_mmap_prot(&host_prot, prot) ||
- !convert_from_nacl_mmap_flags(&host_flags, flags)) {
- return EINVAL;
- }
- void *result = mmap(*addr, len, host_prot, host_flags, fd, off);
- if (result == MAP_FAILED)
- return errno;
- *addr = result;
- return 0;
-}
-
-static int irt_munmap(void *addr, size_t len) {
- return check_error(munmap(addr, len));
-}
-
-static int tls_init(void *ptr) {
- g_tls_value = ptr;
- return 0;
-}
-
-static void *tls_get(void) {
- return g_tls_value;
-}
-
-void *__nacl_read_tp(void) {
- return g_tls_value;
-}
-
-struct thread_args {
- void (*start_func)(void);
- void *thread_ptr;
-};
-
-static void *start_thread(void *arg) {
- struct thread_args args = *(struct thread_args *) arg;
- free(arg);
- g_tls_value = args.thread_ptr;
- args.start_func();
- abort();
-}
-
-static int thread_create(void (*start_func)(void), void *stack,
- void *thread_ptr) {
- /*
- * For now, we ignore the stack that user code provides and just use
- * the stack that the host libpthread allocates.
- */
- pthread_attr_t attr;
- int error = pthread_attr_init(&attr);
- if (error != 0)
- return error;
- error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (error != 0)
- return error;
- struct thread_args *args = malloc(sizeof(struct thread_args));
- if (args == NULL) {
- error = ENOMEM;
- goto cleanup;
- }
- args->start_func = start_func;
- args->thread_ptr = thread_ptr;
- pthread_t tid;
- error = pthread_create(&tid, &attr, start_thread, args);
- if (error != 0)
- free(args);
- cleanup:
- pthread_attr_destroy(&attr);
- return error;
-}
-
-static void thread_exit(int32_t *stack_flag) {
- *stack_flag = 0; /* Indicate that the user code's stack can be freed. */
- pthread_exit(NULL);
-}
-
-static int thread_nice(const int nice) {
- return 0;
-}
-
-/*
- * Mac OS X does not provide futexes or clock_gettime()/getres() natively.
- * TODO(mseaborn): Make threads and clock_gettime() work on Mac OS X.
- */
-#if defined(__linux__)
-static int futex_wait_abs(volatile int *addr, int value,
- const struct timespec *abstime_nacl) {
- struct timespec reltime;
- struct timespec *reltime_ptr = NULL;
- if (abstime_nacl != NULL) {
- struct timespec time_now;
- if (clock_gettime(CLOCK_REALTIME, &time_now) != 0)
- return errno;
-
- /* Convert the absolute time to a relative time. */
- const struct nacl_abi_timespec *abstime =
- (const struct nacl_abi_timespec *) abstime_nacl;
- reltime.tv_sec = abstime->tv_sec - time_now.tv_sec;
- reltime.tv_nsec = abstime->tv_nsec - time_now.tv_nsec;
- if (reltime.tv_nsec < 0) {
- reltime.tv_sec -= 1;
- reltime.tv_nsec += 1000000000;
- }
- /*
- * Linux's FUTEX_WAIT returns EINVAL if given a negative relative
- * time. But an absolute time that's in the past is a valid
- * argument, for which we need to return ETIMEDOUT instead.
- */
- if (reltime.tv_sec < 0)
- return ETIMEDOUT;
- reltime_ptr = &reltime;
- }
- return check_error(syscall(__NR_futex, addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG,
- value, reltime_ptr, 0, 0));
-}
-
-static int futex_wake(volatile int *addr, int nwake, int *count) {
- int result = syscall(__NR_futex, addr, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
- nwake, 0, 0, 0);
- if (result < 0)
- return errno;
- *count = result;
- return 0;
-}
-
-static int irt_clock_getres(nacl_irt_clockid_t clk_id,
- struct timespec *time_nacl) {
- struct timespec time;
- int result = check_error(clock_getres(clk_id, &time));
- convert_to_nacl_timespec(time_nacl, &time);
- return result;
-}
-
-static int irt_clock_gettime(nacl_irt_clockid_t clk_id,
- struct timespec *time_nacl) {
- struct timespec time;
- int result = check_error(clock_gettime(clk_id, &time));
- convert_to_nacl_timespec(time_nacl, &time);
- return result;
-}
-#endif
-
-static int irt_open(const char *pathname, int flags, mode_t mode, int *new_fd) {
- int fd = open(pathname, flags, mode);
- if (fd < 0)
- return errno;
- *new_fd = fd;
- return 0;
-}
-
-static int irt_stat(const char *pathname, struct stat *stat_info_nacl) {
- struct stat stat_info;
- if (stat(pathname, &stat_info) != 0)
- return errno;
- convert_to_nacl_stat(stat_info_nacl, &stat_info);
- return 0;
-}
-
-static int irt_mkdir(const char *pathname, mode_t mode) {
- return check_error(mkdir(pathname, mode));
-}
-
-static int irt_rmdir(const char *pathname) {
- return check_error(rmdir(pathname));
-}
-
-static int irt_chdir(const char *pathname) {
- return check_error(chdir(pathname));
-}
-
-static int irt_getcwd(char *pathname, size_t len) {
- if (getcwd(pathname, len) == NULL)
- return errno;
- return 0;
-}
-
-static int irt_unlink(const char *pathname) {
- return check_error(unlink(pathname));
-}
-
-static int irt_getpid(int *pid) {
- *pid = getpid();
- return 0;
-}
-
-static void irt_stub_func(const char *name) {
- fprintf(stderr, "Error: Unimplemented IRT function: %s\n", name);
- abort();
-}
-
-#define DEFINE_STUB(name) \
- static void irt_stub_##name() { irt_stub_func(#name); }
-#define USE_STUB(s, name) (typeof(s.name)) irt_stub_##name
-
-static const struct nacl_irt_basic irt_basic = {
- irt_exit,
- irt_gettod,
- irt_clock_func,
- irt_nanosleep,
- irt_sched_yield,
- irt_sysconf,
-};
-
-DEFINE_STUB(getdents)
-static const struct nacl_irt_fdio irt_fdio = {
- irt_close,
- irt_dup,
- irt_dup2,
- irt_read,
- irt_write,
- irt_seek,
- irt_fstat,
- USE_STUB(irt_fdio, getdents),
-};
-
-DEFINE_STUB(mprotect)
-static const struct nacl_irt_memory irt_memory = {
- irt_mmap,
- irt_munmap,
- USE_STUB(irt_memory, mprotect),
-};
-
-static const struct nacl_irt_tls irt_tls = {
- tls_init,
- tls_get,
-};
-
-static const struct nacl_irt_thread irt_thread = {
- thread_create,
- thread_exit,
- thread_nice,
-};
-
-#if defined(__linux__)
-static const struct nacl_irt_futex irt_futex = {
- futex_wait_abs,
- futex_wake,
-};
-
-static const struct nacl_irt_clock irt_clock = {
- irt_clock_getres,
- irt_clock_gettime,
-};
-#else
-DEFINE_STUB(futex_wait_abs)
-DEFINE_STUB(futex_wake)
-static const struct nacl_irt_futex irt_futex = {
- USE_STUB(irt_futex, futex_wait_abs),
- USE_STUB(irt_futex, futex_wake),
-};
-#endif
-
-DEFINE_STUB(truncate)
-DEFINE_STUB(lstat)
-DEFINE_STUB(link)
-DEFINE_STUB(rename)
-DEFINE_STUB(symlink)
-DEFINE_STUB(chmod)
-DEFINE_STUB(access)
-DEFINE_STUB(readlink)
-DEFINE_STUB(utimes)
-static const struct nacl_irt_dev_filename irt_dev_filename = {
- irt_open,
- irt_stat,
- irt_mkdir,
- irt_rmdir,
- irt_chdir,
- irt_getcwd,
- irt_unlink,
- USE_STUB(irt_dev_filename, truncate),
- USE_STUB(irt_dev_filename, lstat),
- USE_STUB(irt_dev_filename, link),
- USE_STUB(irt_dev_filename, rename),
- USE_STUB(irt_dev_filename, symlink),
- USE_STUB(irt_dev_filename, chmod),
- USE_STUB(irt_dev_filename, access),
- USE_STUB(irt_dev_filename, readlink),
- USE_STUB(irt_dev_filename, utimes),
-};
-
-static const struct nacl_irt_dev_getpid irt_dev_getpid = {
- irt_getpid,
-};
-
-struct nacl_interface_table {
- const char *name;
- const void *table;
- size_t size;
-};
-
-static const struct nacl_interface_table irt_interfaces[] = {
- { NACL_IRT_BASIC_v0_1, &irt_basic, sizeof(irt_basic) },
- { NACL_IRT_FDIO_v0_1, &irt_fdio, sizeof(irt_fdio) },
- { NACL_IRT_MEMORY_v0_3, &irt_memory, sizeof(irt_memory) },
- { NACL_IRT_TLS_v0_1, &irt_tls, sizeof(irt_tls) },
- { NACL_IRT_THREAD_v0_1, &irt_thread, sizeof(irt_thread) },
- { NACL_IRT_FUTEX_v0_1, &irt_futex, sizeof(irt_futex) },
-#if defined(__linux__)
- { NACL_IRT_CLOCK_v0_1, &irt_clock, sizeof(irt_clock) },
-#endif
- { NACL_IRT_DEV_FILENAME_v0_3, &irt_dev_filename, sizeof(irt_dev_filename) },
- { NACL_IRT_DEV_GETPID_v0_1, &irt_dev_getpid, sizeof(irt_dev_getpid) },
-};
-
-static size_t irt_interface_query(const char *interface_ident,
- void *table, size_t tablesize) {
- unsigned i;
- for (i = 0; i < NACL_ARRAY_SIZE(irt_interfaces); ++i) {
- if (0 == strcmp(interface_ident, irt_interfaces[i].name)) {
- const size_t size = irt_interfaces[i].size;
- if (size <= tablesize) {
- memcpy(table, irt_interfaces[i].table, size);
- return size;
- }
- break;
- }
- }
- fprintf(stderr, "Warning: unavailable IRT interface queried: %s\n",
- interface_ident);
- return 0;
-}
-
-int main(int argc, char **argv, char **environ) {
- /* Find size of environ array. */
- size_t env_count = 0;
- while (environ[env_count] != NULL)
- env_count++;
-
- size_t count =
- 1 /* cleanup_func pointer */
- + 2 /* envc and argc counts */
- + argc + 1 /* argv array, with terminator */
- + env_count + 1 /* environ array, with terminator */
- + 4; /* auxv: 2 entries, one of them the terminator */
- uintptr_t *data = malloc(count * sizeof(uintptr_t));
- if (data == NULL) {
- fprintf(stderr, "Failed to allocate argv/env/auxv array\n");
- return 1;
- }
- size_t pos = 0;
- data[pos++] = 0; /* cleanup_func pointer */
- data[pos++] = env_count;
- data[pos++] = argc;
- /* Copy arrays, with terminators. */
- size_t i;
- for (i = 0; i < (size_t) argc; i++)
- data[pos++] = (uintptr_t) argv[i];
- data[pos++] = 0;
- for (i = 0; i < env_count; i++)
- data[pos++] = (uintptr_t) environ[i];
- data[pos++] = 0;
- /* auxv[0] */
- data[pos++] = AT_SYSINFO;
- data[pos++] = (uintptr_t) irt_interface_query;
- /* auxv[1] */
- data[pos++] = 0;
- data[pos++] = 0;
- assert(pos == count);
-
- /*
- * On Linux, we rename _start() to _user_start() to avoid a clash
- * with the "_start" routine in the host toolchain. On Mac OS X,
- * lacking objcopy, doing the symbol renaming is trickier, but also
- * unnecessary, because the host toolchain doesn't have a "_start"
- * routine.
- */
-#if defined(__APPLE__)
- _start(data);
-#else
- _user_start(data);
-#endif
- return 1;
-}

Powered by Google App Engine
This is Rietveld 408576698