예제 #1
0
void _start(uintptr_t info[]) {
  Elf_auxv_t* auxv = nacl_startup_auxv(info);
  grok_auxv(auxv);
  DO_QUERY(NACL_IRT_BASIC_v0_1, __libnacl_irt_basic);

  struct nacl_irt_ppapihook ppapihook;
  DO_QUERY(NACL_IRT_PPAPIHOOK_v0_1, ppapihook);

  /* This is local as a workaround to avoid having to apply
   * relocations to global variables. */
  struct PP_StartFunctions start_funcs = {
    MyPPP_InitializeModule,
    MyPPP_ShutdownModule,
    MyPPP_GetInterface,
  };
  /* Similarly, initialise some global variables, avoiding relocations. */
  struct PPP_Instance_1_0 local_ppp_instance = {
    DidCreate,
    DidDestroy,
    DidChangeView,
    DidChangeFocus,
    HandleDocumentLoad,
  };
  ppp_instance = local_ppp_instance;
  struct PPP_Messaging_1_0 local_ppp_messaging = {
    HandleMessage,
  };
  ppp_messaging = local_ppp_messaging;

  ppapihook.ppapi_start(&start_funcs);

  __libnacl_irt_basic.exit(0);
}
예제 #2
0
void _start(uintptr_t info[]) {
  Elf_auxv_t* auxv = nacl_startup_auxv(info);
  grok_auxv(auxv);
  DO_QUERY(NACL_IRT_BASIC_v0_1, __libnacl_irt_basic);
  DO_QUERY(NACL_IRT_RANDOM_v0_1, __libnacl_irt_random);

  struct nacl_irt_ppapihook ppapihook;
  DO_QUERY(NACL_IRT_PPAPIHOOK_v0_1, ppapihook);

  /* This is local as a workaround to avoid having to apply
   * relocations to global variables. */
  struct PP_StartFunctions start_funcs;
  start_funcs.PPP_InitializeModule = MyPPP_InitializeModule;
  start_funcs.PPP_ShutdownModule = MyPPP_ShutdownModule;
  start_funcs.PPP_GetInterface = MyPPP_GetInterface;
  /* Similarly, initialize some global variables, avoiding relocations. */
  ppp_instance.DidCreate = DidCreate;
  ppp_instance.DidDestroy = DidDestroy;
  ppp_instance.DidChangeView = DidChangeView;
  ppp_instance.DidChangeFocus = DidChangeFocus;
  ppp_instance.HandleDocumentLoad = HandleDocumentLoad;
  ppp_messaging.HandleMessage = HandleMessage;

  ppapihook.ppapi_start(&start_funcs);

  __libnacl_irt_basic.exit(0);
}
예제 #3
0
/*
 * This is the true entry point for untrusted code.
 * See nacl_startup.h for the layout at the argument pointer.
 */
void _start(uint32_t *info) {
  Elf32_auxv_t *auxv = nacl_startup_auxv(info);

  __libnacl_irt_init(auxv);

  _exit(PpapiPluginStart(ih.__nacl_irt_query));

  /*NOTREACHED*/
  while (1) *(volatile int *) 0;  /* Crash.  */
}
예제 #4
0
void _pnacl_wrapper_start(uint32_t *info) {
  Elf32_auxv_t *auxv = nacl_startup_auxv(info);

  Elf32_auxv_t *entry = NULL;
  for (Elf32_auxv_t *av = auxv; av->a_type != AT_NULL; ++av) {
    if (av->a_type == AT_SYSINFO) {
      entry = av;
      break;
    }
  }

  if (entry != NULL) {
    __pnacl_real_irt_interface = (TYPE_nacl_irt_query) entry->a_un.a_val;

    entry->a_type = AT_SYSINFO;
    entry->a_un.a_val = (uintptr_t) __pnacl_irt_interface_wrapper;
  }


  _start(info);
}
예제 #5
0
/*
 * This is the true entry point for untrusted code.
 * See nacl_startup.h for the layout at the argument pointer.
 */
void _pnacl_wrapper_start(uint32_t *info) {
  Elf32_auxv_t *auxv = nacl_startup_auxv(info);

  Elf32_auxv_t *entry = NULL;
  for (Elf32_auxv_t *av = auxv; av->a_type != AT_NULL; ++av) {
    if (av->a_type == AT_SYSINFO) {
      entry = av;
      break;
    }
  }

  if (entry != NULL) {
    /*
     * Save the real irt interface query function.
     */
    __pnacl_real_irt_query_func = (TYPE_nacl_irt_query) entry->a_un.a_val;

    /*
     * Overwrite the auxv slot with the pnacl IRT shim query function.
     */
    entry->a_type = AT_SYSINFO;
    entry->a_un.a_val = (uintptr_t) __pnacl_wrap_irt_query_func;
  }

  /* If entry is NULL still allow startup to continue.  It may be the case
   * that the IRT was not actually used (e.g., for some commandline tests).
   * For newlib, we can tell that the IRT isn't used when libnacl_sys_private.a
   * is in the bitcode link line. However, glibc does not use
   * libnacl_sys_private, so that would not work. We could look for -lppapi
   * in the bitcode link line, but looking at the bitcode link line
   * seems brittle (what if the bitcode link was separated from translation).
   * Thus we always wrap _start, even if there is no IRT auxv entry.
   */

  /*
   * Call the user entry point function.  It should not return.
   * TODO(sehr): Find a way to ensure this is invoked via a tail call.
   */
  _start(info);
}
예제 #6
0
/*
 * This is the true entry point for untrusted code.
 * See nacl_startup.h for the layout at the argument pointer.
 */
void _start(uint32_t *info) {
  void (*fini)(void) = nacl_startup_fini(info);
  int argc = nacl_startup_argc(info);
  char **argv = nacl_startup_argv(info);
  char **envp = nacl_startup_envp(info);
  Elf32_auxv_t *auxv = nacl_startup_auxv(info);

  environ = envp;

  /*
   * Record the approximate address from which the stack grows
   * (usually downwards) so that libpthread can report it.  Taking the
   * address of any stack-allocated variable will work here.
   */
  __nacl_initial_thread_stack_end = &info;

  __libnacl_irt_init(auxv);

  /*
   * If we were started by a dynamic linker, then it passed its finalizer
   * function here.  For static linking, this is always NULL.
   */
  if (fini != NULL)
    atexit(fini);

  atexit(&__libc_fini_array);

  __pthread_initialize();

  __libc_init_array();

  int (*main_ptr)(int argc, char **argv, char **envp) = &__nacl_main;
  if (main_ptr == NULL)
    main_ptr = &main;

  exit(main_ptr(argc, argv, envp));

  /*NOTREACHED*/
  __builtin_trap();
}
예제 #7
0
void nacl_irt_enter_user_code(uint32_t *info,
                              nacl_irt_query_func_t query_func) {
  Elf32_auxv_t *auxv = nacl_startup_auxv(info);
  Elf32_auxv_t *entry = NULL;
  for (Elf32_auxv_t *av = auxv; av->a_type != AT_NULL; ++av) {
    if (av->a_type == AT_ENTRY) {
      entry = av;
      break;
    }
  }
  if (entry == NULL) {
    static const char fatal_msg[] =
        "irt_entry: No AT_ENTRY item found in auxv.  "
        "Is there no user executable loaded?\n";
    write(2, fatal_msg, sizeof(fatal_msg) - 1);
    _exit(-1);
  }
  void (*user_start)(uint32_t *) = (void (*)(uint32_t *)) entry->a_un.a_val;

  /*
   * The user application does not need to see the AT_ENTRY item.
   * Reuse the auxv slot and overwrite it with the IRT query function.
   */
  entry->a_type = AT_SYSINFO;
  entry->a_un.a_val = (uintptr_t) query_func;

  /*
   * Call the user entry point function.  It should not return.
   */
  (*user_start)(info);

  /*
   * But just in case it does...
   */
  _exit(0);
}
예제 #8
0
static void chainload(const char *program, const char *interp_prefix,
                      int argc, char **argv, int envc, char **envp) {
  if (nacl_interface_query(NACL_IRT_RESOURCE_OPEN_v0_1, &resource_open,
                           sizeof(resource_open)) != sizeof(resource_open))
    resource_open.open_resource = NULL;
  if (nacl_interface_query(NACL_IRT_CODE_DATA_ALLOC_v0_1, &code_data_alloc,
                           sizeof(code_data_alloc)) !=
      sizeof(code_data_alloc)) {
    fprintf(stderr, "Failed to find necessary IRT interface %s!\n",
            NACL_IRT_CODE_DATA_ALLOC_v0_1);
    exit(1);
  }

  const size_t pagesize = NACL_MAP_PAGESIZE;
  const TYPE_nacl_irt_query irt_query = __nacl_irt_query;

  /*
   * Populate our own info array on the stack.  We do not assume that the
   * argv and envp arrays are in their usual layout, since the caller could
   * be passing different values.
   */
  uint32_t info[NACL_STARTUP_ARGV + argc + 1 + envc + 1 + (kAuxvCount * 2)];
  info[NACL_STARTUP_FINI] = 0;
  info[NACL_STARTUP_ENVC] = envc;
  info[NACL_STARTUP_ARGC] = argc;
  memcpy(nacl_startup_argv(info), argv, (argc + 1) * sizeof(argv[0]));
  memcpy(nacl_startup_envp(info), envp, (envc + 1) * sizeof(envp[0]));
  Elf32_auxv_t *auxv = nacl_startup_auxv(info);

  /*
   * Populate the auxiliary vector with the values dynamic linkers expect.
   */
  auxv[kPhdr].a_type = AT_PHDR;
  auxv[kPhent].a_type = AT_PHENT;
  auxv[kPhent].a_un.a_val = sizeof(Elf32_Phdr);
  auxv[kPhnum].a_type = AT_PHNUM;
  auxv[kBase].a_type = AT_BASE;
  auxv[kEntry].a_type = AT_ENTRY;
  auxv[kSysinfo].a_type = AT_SYSINFO;
  auxv[kSysinfo].a_un.a_val = (uint32_t) irt_query;
  auxv[kNull].a_type = AT_NULL;
  auxv[kNull].a_un.a_val = 0;

  /*
   * Load the program and point the auxv elements at its phdrs and entry.
   */
  const char *interp = NULL;
  uint32_t entry = load_elf_file(program,
                                 pagesize,
                                 &auxv[kBase].a_un.a_val,
                                 &auxv[kPhdr].a_un.a_val,
                                 &auxv[kPhnum].a_un.a_val,
                                 &interp);
  auxv[kEntry].a_un.a_val = entry;

  if (auxv[kPhdr].a_un.a_val == 0)
    auxv[kPhdr].a_type = AT_IGNORE;

  DEBUG_PRINTF("XXX loaded %s, entry %#x, interp %s\n", program, entry, interp);

  if (interp != NULL) {
    /*
     * There was a PT_INTERP, so we have a dynamic linker to load.
     */

    char interp_buf[PATH_MAX];
    if (interp_prefix != NULL) {
      /*
       * Apply the command-line-specified prefix to the embedded file name.
       */
      snprintf(interp_buf, sizeof(interp_buf), "%s%s", interp_prefix, interp);
      interp = interp_buf;
    }

    entry = load_elf_file(interp, pagesize, NULL, NULL, NULL, NULL);

    DEBUG_PRINTF("XXX loaded PT_INTERP %s, entry %#x\n", interp, entry);
  }

  for (uint32_t *p = info; p < (uint32_t *) &auxv[kNull + 1]; ++p)
    DEBUG_PRINTF("XXX info[%d] = %#x\n", p - info, *p);

  /*
   * Off to the races!
   * The application's entry point should not return.  Crash if it does.
   */
  DEBUG_PRINTF("XXX user entry point: %#x(%#x)\n", entry, (uintptr_t) info);
  (*(void (*)(uint32_t[])) entry)(info);
  while (1)
    __builtin_trap();
}