/* This tests a NaCl syscall that takes no arguments. */
void TestSyscall(uintptr_t syscall_addr) {
  struct NaClSignalContext call_regs;
  char stack[0x10000];

  RegsFillTestValues(&call_regs, /* seed= */ 0);
  call_regs.stack_ptr = (uintptr_t) stack + sizeof(stack);
  call_regs.prog_ctr = (uintptr_t) ContinueAfterSyscall;
  RegsApplySandboxConstraints(&call_regs);

  g_expected_regs = call_regs;
  RegsUnsetNonCalleeSavedRegisters(&g_expected_regs);
  SetNaClSwitchExpectations(&g_expected_regs);

  if (!setjmp(g_return_jmp_buf)) {
#if defined(__i386__)
    call_regs.eax = syscall_addr;
    ASM_WITH_REGS(
        &call_regs,
        "push $ContinueAfterSyscall\n"  /* Push return address */
        "nacljmp %%eax\n");
#elif defined(__x86_64__)
    /*
     * This fast path syscall happens to preserve various registers,
     * but that is obviously not guaranteed by the ABI.
     */
    if (syscall_addr == (uintptr_t) NACL_SYSCALL(tls_get) ||
        syscall_addr == (uintptr_t) NACL_SYSCALL(second_tls_get)) {
      /* Undo some effects of RegsUnsetNonCalleeSavedRegisters(). */
      g_expected_regs.rsi = call_regs.rsi;
      g_expected_regs.rdi = call_regs.rdi;
      g_expected_regs.r8 = call_regs.r8;
      g_expected_regs.r9 = call_regs.r9;
      g_expected_regs.r10 = call_regs.r10;
      /*
       * The current implementation clobbers %rcx with the
       * non-%r15-extended return address.
       */
      g_expected_regs.rcx = (uint32_t) g_expected_regs.prog_ctr;
    }

    call_regs.rax = syscall_addr;
    ASM_WITH_REGS(
        &call_regs,
        "push $ContinueAfterSyscall\n"  /* Push return address */
        "nacljmp %%eax, %%r15\n");
#elif defined(__arm__)
    call_regs.r1 = syscall_addr;  /* Scratch register */
    call_regs.lr = (uintptr_t) ContinueAfterSyscall;  /* Return address */
    ASM_WITH_REGS(
        &call_regs,
        "bic r1, r1, #0xf000000f\n"
        "bx r1\n");
#else
# error Unsupported architecture
#endif
    assert(!"Should not reach here");
  }
}
void test_stack_in_code(void) {
  int rc = NACL_SYSCALL(exception_handler)(bad_stack_exception_handler, NULL);
  assert(rc == 0);
  rc = NACL_SYSCALL(exception_stack)(stack_in_code, stack_in_code_size);
  assert(rc == 0);
  fprintf(stderr, "** intended_exit_status=unwritable_exception_stack\n");
  /* Cause crash. */
  *(volatile int *) 0 = 0;
}
/*
 * This test case does not crash.  It successfully runs
 * bad_stack_exception_handler() in order to check that it works, so
 * that we can be sure that other tests do not crash (and hence pass)
 * accidentally.
 */
void test_stack_in_rwdata(void) {
  int rc = NACL_SYSCALL(exception_handler)(bad_stack_exception_handler, NULL);
  assert(rc == 0);
  rc = NACL_SYSCALL(exception_stack)((void *) stack_in_rwdata,
                                     sizeof(stack_in_rwdata));
  assert(rc == 0);
  fprintf(stderr, "** intended_exit_status=1\n");
  /* Cause crash. */
  *(volatile int *) 0 = 0;
}
/*
 * This checks that crashes in trusted code (such as inside NaCl
 * syscalls) do not cause the untrusted exception handler to run.
 */
void test_crash_in_syscall(void) {
  int rc = NACL_SYSCALL(exception_handler)(bad_stack_exception_handler, NULL);
  assert(rc == 0);
  rc = NACL_SYSCALL(exception_stack)((void *) stack_in_rwdata,
                                     sizeof(stack_in_rwdata));
  assert(rc == 0);
  fprintf(stderr, "** intended_exit_status=trusted_segfault\n");
  /*
   * Cause a crash inside a NaCl syscall.
   */
  NACL_SYSCALL(test_crash)(NACL_TEST_CRASH_MEMORY);
  /* Should not reach here. */
  _exit(1);
}
Ejemplo n.º 5
0
static int nacl_irt_thread_create(void *start_user_address, void *stack,
                                  void *thread_ptr) {
#if defined(NACL_IN_IRT)
  /*
   * We want the first TLS to point to an unmapped location.  The
   * thread_create() syscall rejects a zero argument for the first
   * TLS, so use a non-zero value in the unmapped first 64k page.
   */
  void *user_tls = (void *) 0x1000;
  return -NACL_SYSCALL(thread_create)(start_user_address, stack,
                                      user_tls, thread_ptr);
#else
  return -NACL_SYSCALL(thread_create)(start_user_address, stack, thread_ptr, 0);
#endif
}
Ejemplo n.º 6
0
static int nc_thread_cond_init(pthread_cond_t *cond,
                               pthread_condattr_t *cond_attr) {
  cond->handle = NACL_SYSCALL(cond_create)();

  /* 0 for success, 1 for failure */
  return (cond->handle < 0);
}
Ejemplo n.º 7
0
void _exit (int status)
{
  NACL_SYSCALL (exit) (status);
  /* In case the syscall returns: */
  while (1)
    __asm__("hlt");
}
Ejemplo n.º 8
0
static int nacl_irt_mutex_create(int *mutex_handle) {
  int rv = NACL_SYSCALL(mutex_create)();
  if (rv < 0)
    return -rv;
  *mutex_handle = rv;
  return 0;
}
Ejemplo n.º 9
0
int main(int argc, char* argv[]) {
  if (argc == 555) {
    /* this should never be executed */
    var_tls = 11;
    var_tls_double = 22.0;

    var_static = 33;
    var_static_double = 44.0;

    var_global = 55;
    var_global_double = 66.0;
  }

  if (argc == 6666) {
    /* this should never be executed */
    return  (int) &var_tls +
            (int) &var_static +
            (int) &var_global +
            (int) &var_tls_double +
            (int) &var_static_double +
            (int) &var_global_double;
  }
#if !defined(NO_NACL_STUFF)
  NACL_SYSCALL(exit)(55);
#endif
  /* UNREACHABLE */
  return 0;
}
Ejemplo n.º 10
0
/* Set registers to known values and enter a NaCl syscall. */
static void SyscallRegisterSetterThread(struct SuspendTestShm *test_shm) {
  struct NaClSignalContext call_regs;
  char stack[0x10000];

  RegsFillTestValues(&call_regs, /* seed= */ 0);
  call_regs.stack_ptr = (uintptr_t) stack + sizeof(stack);
  call_regs.prog_ctr = (uintptr_t) ContinueAfterSyscall;
  RegsApplySandboxConstraints(&call_regs);

  /*
   * call_regs are the registers we set on entry to the syscall.
   * expected_regs are the registers that should be reported by
   * NaClAppThreadGetSuspendedRegisters().  Since not all registers
   * are saved when entering a syscall, expected_regs will be the same
   * as call_regs but with various registers zeroed out.
   */
  test_shm->expected_regs = call_regs;
  RegsUnsetNonCalleeSavedRegisters(&test_shm->expected_regs);

  uintptr_t syscall_addr = (uintptr_t) NACL_SYSCALL(test_syscall_1);
  if (!setjmp(return_jmp_buf)) {
#if defined(__i386__)
    test_shm->expected_regs.stack_ptr -= 4;  /* Account for argument */
    call_regs.eax = syscall_addr;
    call_regs.ecx = (uintptr_t) test_shm;  /* Scratch register */
    ASM_WITH_REGS(
        &call_regs,
        "push %%ecx\n"  /* Push syscall argument */
        "push $ContinueAfterSyscall\n"  /* Push return address */
        "nacljmp %%eax\n");
#elif defined(__x86_64__)
    call_regs.rax = syscall_addr;
    call_regs.rdi = (uintptr_t) test_shm;  /* Set syscall argument */
    ASM_WITH_REGS(
        &call_regs,
        "push $ContinueAfterSyscall\n"  /* Push return address */
        "nacljmp %%eax, %%r15\n");
#elif defined(__arm__)
    call_regs.r0 = (uintptr_t) test_shm;  /* Set syscall argument */
    call_regs.r1 = syscall_addr;  /* Scratch register */
    call_regs.lr = (uintptr_t) ContinueAfterSyscall;
    ASM_WITH_REGS(
        &call_regs,
        "bic r1, r1, #0xf000000f\n"
        "bx r1\n");
#elif defined(__mips__)
    call_regs.a0 = (uintptr_t) test_shm;  /* Set syscall argument */
    call_regs.t9 = syscall_addr;  /* Scratch register */
    call_regs.return_addr = (uintptr_t) ContinueAfterSyscall;
    ASM_WITH_REGS(
        &call_regs,
        "and $t9, $t9, $t6\n"
        "jr $t9\n"
        "nop\n");
#else
# error Unsupported architecture
#endif
    assert(!"Should not reach here");
  }
}
Ejemplo n.º 11
0
static int nacl_irt_isatty(int fd, int *result) {
  int rv = NACL_SYSCALL(isatty)(fd);
  if (rv < 0)
    return -rv;
  *result = rv;
  return 0;
}
Ejemplo n.º 12
0
static int nacl_irt_read(int fd, void *buf, size_t count, size_t *nread) {
  int rv = NACL_GC_WRAP_SYSCALL(NACL_SYSCALL(read)(fd, buf, count));
  if (rv < 0)
    return -rv;
  *nread = rv;
  return 0;
}
/*
 * This tests that when a new thread is created, untrusted code is
 * entered with well-defined register state.  None of the registers
 * should come from uninitialised values.
 */
void TestInitialRegsAtThreadEntry(void) {
  char *stack_top = g_stack + sizeof(g_stack);
  uintptr_t aligned_stack_top =
      ((uintptr_t) stack_top & ~NACL_STACK_ALIGN_MASK)
      - NACL_STACK_PAD_BELOW_ALIGN;
  /*
   * We do not care about TLS for this test, but sel_ldr rejects a
   * zero tls argument, so use an arbitrary non-zero value.
   */
  char *tls = (char *) 0x1000;
  g_stack_in_use = 1;
  int rc = NACL_SYSCALL(thread_create)((void *) (uintptr_t) ThreadFuncWrapper,
                                       stack_top, tls, 0);
  assert(rc == 0);
  /* Spin until the thread exits. */
  while (g_stack_in_use) {
    sched_yield();
  }
  ANNOTATE_CONDVAR_WAIT(&g_stack_in_use);
  struct NaClSignalContext actual_regs = g_initial_thread_regs;

  struct NaClSignalContext expected_regs;
  /* By default, we expect registers to be initialised to zero. */
  memset(&expected_regs, 0, sizeof(expected_regs));
  expected_regs.prog_ctr = (uintptr_t) ThreadFuncWrapper;
  expected_regs.stack_ptr = aligned_stack_top;
  RegsApplySandboxConstraints(&expected_regs);
  SetNaClSwitchExpectations(&expected_regs);
#if defined(__x86_64__)
  /* NaCl happens to initialise %rbp to be the same as %rsp. */
  expected_regs.rbp = expected_regs.stack_ptr;
#endif

  RegsAssertEqual(&actual_regs, &expected_regs);
}
Ejemplo n.º 14
0
/*
 * This replaces __pthread_initialize_minimal() from libnacl and
 * __pthread_initialize() from libpthread.
 */
void __pthread_initialize(void) {
  struct nc_combined_tdb *tdb;

  /*
   * Allocate the area.  If malloc fails here, we'll crash before it returns.
   */
  size_t combined_size = __nacl_tls_combined_size(sizeof(*tdb));
  void *combined_area = malloc(combined_size);

  /*
   * Initialize TLS proper (i.e., __thread variable initializers).
   */
  void *tp = __nacl_tls_initialize_memory(combined_area, sizeof(*tdb));
  tdb = get_irt_tdb(tp);
  __nc_initialize_unjoinable_thread(tdb);
  tdb->tdb.irt_thread_data = combined_area;

  /*
   * Now install it for later fetching.
   * This is what our private version of __nacl_read_tp will read.
   */
  NACL_SYSCALL(second_tls_set)(tp);

  /*
   * Finally, do newlib per-thread initialization.
   */
  __newlib_thread_init();

  __nc_initialize_globals();
}
Ejemplo n.º 15
0
static int nacl_irt_dup(int fd, int *newfd) {
  int rv = NACL_SYSCALL(dup)(fd);
  if (rv < 0)
    return -rv;
  *newfd = rv;
  return 0;
}
Ejemplo n.º 16
0
static int nacl_irt_thread_create(void (*start_func)(void), void *stack,
                                  void *thread_ptr) {
  struct nc_combined_tdb *tdb;

  /*
   * Before we start the thread, allocate the IRT-private TLS area for it.
   */
  size_t combined_size = __nacl_tls_combined_size(sizeof(*tdb));
  void *combined_area = malloc(combined_size);
  if (combined_area == NULL)
    return EAGAIN;

  /*
   * Note that __nacl_tls_initialize_memory() is not reversible,
   * because it takes a pointer that need not be aligned and can
   * return a pointer that is aligned.  In order to
   * free(combined_area) later, we must save the value of
   * combined_area.
   */
  void *irt_tp = __nacl_tls_initialize_memory(combined_area, sizeof(*tdb));
  tdb = get_irt_tdb(irt_tp);
  __nc_initialize_unjoinable_thread(tdb);
  tdb->tdb.irt_thread_data = combined_area;
  /*
   * We overload the libpthread start_func field to store a function
   * of a different type.
   */
  tdb->tdb.start_func = (void *(*)(void *)) start_func;

  int error = -NACL_SYSCALL(thread_create)(
      (void *) (uintptr_t) &irt_start_thread, stack, thread_ptr, irt_tp);
  if (error != 0)
    free(combined_area);
  return error;
}
Ejemplo n.º 17
0
static void SyscallInvokerThread(struct SuspendTestShm *test_shm) {
  uint32_t next_val = 0;
  while (!test_shm->should_exit) {
    NACL_SYSCALL(null)();
    test_shm->var = next_val++;
  }
}
Ejemplo n.º 18
0
static int nacl_irt_seek(int fd, off_t offset, int whence, off_t *new_offset) {
  int rv = NACL_SYSCALL(lseek)(fd, &offset, whence);
  if (rv < 0)
    return -rv;
  *new_offset = offset;
  return 0;
}
Ejemplo n.º 19
0
static int nacl_irt_cond_create(int *cond_handle) {
  int rv = NACL_SYSCALL(cond_create)();
  if (rv < 0)
    return -rv;
  *cond_handle = rv;
  return 0;
}
Ejemplo n.º 20
0
static int nacl_irt_write(int fd, const void *buf, size_t count,
                          size_t *nwrote) {
  int rv = NACL_GC_WRAP_SYSCALL(NACL_SYSCALL(write)(fd, buf, count));
  if (rv < 0)
    return -rv;
  *nwrote = rv;
  return 0;
}
Ejemplo n.º 21
0
int imc_connect(int d) {
  int retval = NACL_SYSCALL(imc_connect)(d);
  if (retval < 0) {
    errno = -retval;
    return -1;
  }
  return retval;
}
Ejemplo n.º 22
0
static int nacl_irt_getdents(int fd, struct dirent *buf, size_t count,
                             size_t *nread) {
  int rv = NACL_GC_WRAP_SYSCALL(NACL_SYSCALL(getdents)(fd, buf, count));
  if (rv < 0)
    return -rv;
  *nread = rv;
  return 0;
}
Ejemplo n.º 23
0
int imc_makeboundsock(int *dp) {
  int retval = NACL_SYSCALL(imc_makeboundsock)(dp);
  if (retval < 0) {
    errno = -retval;
    return -1;
  }
  return retval;
}
Ejemplo n.º 24
0
int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <crash-type>\n", argv[0]);
    return 1;
  }
  char *crash_type = argv[1];
  if (strcmp(crash_type, "NACL_TEST_CRASH_JUMP_TO_ZERO") == 0) {
    register_exception_handler();
    NACL_SYSCALL(test_syscall_1)();
  } else if (strcmp(crash_type, "NACL_TEST_CRASH_JUMP_INTO_SANDBOX") == 0) {
    register_exception_handler();
    NACL_SYSCALL(test_syscall_2)();
  } else {
    NACL_SYSCALL(test_crash)(look_up_crash_type(crash_type));
  }
  return 1;
}
Ejemplo n.º 25
0
int getdents(int desc, struct dirent *dirp, size_t count) {
  int retval = NACL_SYSCALL(getdents)(desc, dirp, count);
  if (retval < 0) {
    errno = -retval;
    return -1;
  }
  return retval;
}
Ejemplo n.º 26
0
int munmap(void *start, size_t length) {
  int retval = NACL_SYSCALL(munmap)(start, length);
  if (retval < 0) {
    errno = -retval;
    return -1;
  }
  return retval;
}
int nacl_dyncode_delete(void *dest, size_t size) {
  int error = -NACL_SYSCALL(dyncode_delete)(dest, size);
  if (error) {
    errno = error;
    return -1;
  }
  return 0;
}
int nacl_dyncode_modify(void *dest, const void *src, size_t size) {
  int error = -NACL_SYSCALL(dyncode_modify)(dest, src, size);
  if (error) {
    errno = error;
    return -1;
  }
  return 0;
}
Ejemplo n.º 29
0
int imc_sendmsg(int desc, struct NaClAbiNaClImcMsgHdr const *nmhp, int flags) {
  int retval = NACL_SYSCALL(imc_sendmsg)(desc, nmhp, flags);
  if (retval < 0) {
    errno = -retval;
    return -1;
  }
  return retval;
}
Ejemplo n.º 30
0
int write(int desc, void const *buf, size_t count) {
  int retval = NACL_GC_WRAP_SYSCALL(NACL_SYSCALL(write)(desc, buf, count));
  if (retval < 0) {
    errno = -retval;
    return -1;
  }
  return retval;
}