Ejemplo n.º 1
0
NaClErrorCode NaClAllocateSpace(void **mem, size_t addrsp_size) {
  size_t        mem_sz = 2 * GUARDSIZE + FOURGIG;  /* 40G guard on each side */
  size_t        log_align = ALIGN_BITS;
  void          *mem_ptr;

  NaClLog(4, "NaClAllocateSpace(*, 0x%016"NACL_PRIxS" bytes).\n",
          addrsp_size);

  CHECK(addrsp_size == FOURGIG);

  errno = 0;
  mem_ptr = NaClAllocatePow2AlignedMemory(mem_sz, log_align);
  if (NULL == mem_ptr) {
    if (0 != errno) {
      perror("NaClAllocatePow2AlignedMemory");
    }
    NaClLog(LOG_WARNING, "Memory allocation failed\n");

    return LOAD_NO_MEMORY;
  }
  /*
   * The module lives in the middle FOURGIG of the allocated region --
   * we skip over an initial 40G guard.
   */
  *mem = (void *) (((char *) mem_ptr) + GUARDSIZE);
  NaClLog(4,
          "NaClAllocateSpace: addr space at 0x%016"NACL_PRIxPTR"\n",
          (uintptr_t) *mem);

  return LOAD_OK;
}
Ejemplo n.º 2
0
/*
 * Platform-specific routine to allocate memory space for the NaCl
 * module.  mem is an out argument; addrsp_size is the requested
 * address space size, currently always ((size_t) 1) <<
 * nap->addr_bits.  On x86-64, there's a further requirement that this
 * is 4G.
 *
 * The actual amount of memory allocated is larger than requested on
 * x86-64 and on the ARM, since guard pages are also allocated to be
 * contiguous with the allocated address space.
 *
 * If successful, the guard pages are not yet memory protected.  The
 * function NaClMprotectGuards must be called for the guard pages to
 * be active.
 *
 * update: abort zvm if failed
 */
static void NaClAllocateSpace(void **mem, size_t addrsp_size)
{
  size_t mem_sz = 2 * GUARDSIZE + FOURGIG; /* 40G guard on each side */
  size_t log_align = ALIGN_BITS;
  void *mem_ptr;

  ZLOGS(LOG_INSANE, "NaClAllocateSpace(*, 0x%016lx bytes)", addrsp_size);
  ZLOGFAIL(addrsp_size != FOURGIG, EFAULT, "addrsp_size != FOURGIG");

  errno = 0;
  mem_ptr = NaClAllocatePow2AlignedMemory(mem_sz, log_align);
  ZLOGFAIL(NULL == mem_ptr, errno, "NaClAllocatePow2AlignedMemory failed");

  /*
   * The module lives in the middle FOURGIG of the allocated region --
   * we skip over an initial 40G guard.
   */
  *mem = (void *)(((char *)mem_ptr) + GUARDSIZE);
  ZLOGS(LOG_INSANE, "addr space at 0x%016lx", (uintptr_t)*mem);
}
Ejemplo n.º 3
0
NaClErrorCode NaClAllocateSpaceAslr(void **mem, size_t addrsp_size,
                                    enum NaClAslrMode aslr_mode) {
  /* 40G guard on each side */
  size_t        mem_sz = (NACL_ADDRSPACE_LOWER_GUARD_SIZE + FOURGIG +
                          NACL_ADDRSPACE_UPPER_GUARD_SIZE);
  size_t        log_align = ALIGN_BITS;
  void          *mem_ptr;
#if NACL_LINUX
  struct rlimit rlim;
#endif

  NaClLog(4, "NaClAllocateSpace(*, 0x%016"NACL_PRIxS" bytes).\n",
          addrsp_size);

  CHECK(addrsp_size == FOURGIG);

  if (NACL_X86_64_ZERO_BASED_SANDBOX) {
    mem_sz = 11 * FOURGIG;
    if (getenv("NACL_ENABLE_INSECURE_ZERO_BASED_SANDBOX") != NULL) {
      /*
       * For the zero-based 64-bit sandbox, we want to reserve 44GB of address
       * space: 4GB for the program plus 40GB of guard pages.  Due to a binutils
       * bug (see http://sourceware.org/bugzilla/show_bug.cgi?id=13400), the
       * amount of address space that the linker can pre-reserve is capped
       * at 4GB. For proper reservation, GNU ld version 2.22 or higher
       * needs to be used.
       *
       * Without the bug fix, trying to reserve 44GB will result in
       * pre-reserving the entire capped space of 4GB.  This tricks the run-time
       * into thinking that we can mmap up to 44GB.  This is unsafe as it can
       * overwrite the run-time program itself and/or other programs.
       *
       * For now, we allow a 4GB address space as a proof-of-concept insecure
       * sandboxing model.
       *
       * TODO(arbenson): remove this if block once the binutils bug is fixed
       */
      mem_sz = FOURGIG;
    }

    NaClAddrSpaceBeforeAlloc(mem_sz);
    if (NaClFindPrereservedSandboxMemory(mem, mem_sz)) {
      int result;
      void *tmp_mem = (void *) NACL_TRAMPOLINE_START;
      CHECK(*mem == 0);
      mem_sz -= NACL_TRAMPOLINE_START;
      result = NaClPageAllocAtAddr(&tmp_mem, mem_sz);
      if (0 != result) {
        NaClLog(2,
                "NaClAllocateSpace: NaClPageAlloc 0x%08"NACL_PRIxPTR
                " failed\n",
                (uintptr_t) *mem);
        return LOAD_NO_MEMORY;
      }
      NaClLog(4, "NaClAllocateSpace: %"NACL_PRIxPTR", %"NACL_PRIxS"\n",
              (uintptr_t) *mem,
              mem_sz);
      return LOAD_OK;
    }
    NaClLog(LOG_ERROR, "Failed to find prereserved memory\n");
    return LOAD_NO_MEMORY;
  }

  NaClAddrSpaceBeforeAlloc(mem_sz);

  errno = 0;
  mem_ptr = NaClAllocatePow2AlignedMemory(mem_sz, log_align, aslr_mode);
  if (NULL == mem_ptr) {
    if (0 != errno) {
      perror("NaClAllocatePow2AlignedMemory");
    }
    NaClLog(LOG_WARNING, "Memory allocation failed\n");
#if NACL_LINUX
    /*
     * Check with getrlimit whether RLIMIT_AS was likely to be the
     * problem with an allocation failure.  If so, generate a log
     * message.  Since this is a debugging aid and we don't know about
     * the memory requirement of the code that is embedding native
     * client, there is some slop.
     */
    if (0 != getrlimit(RLIMIT_AS, &rlim)) {
      perror("NaClAllocatePow2AlignedMemory::getrlimit");
    } else {
      if (rlim.rlim_cur < mem_sz) {
        /*
         * Developer hint/warning; this will show up in the crash log
         * and must be brief.
         */
        NaClLog(LOG_INFO,
                "Please run \"ulimit -v unlimited\" (bash)"
                " or \"limit vmemoryuse unlimited\" (tcsh)\n");
        NaClLog(LOG_INFO,
                "and restart the app.  NaCl requires at least %"NACL_PRIdS""
                " kilobytes of virtual\n",
                mem_sz / 1024);
        NaClLog(LOG_INFO,
                "address space. NB: Raising the hard limit requires"
                " root access.\n");
      }
    }
#elif NACL_OSX
    /*
     * In OSX, RLIMIT_AS and RLIMIT_RSS have the same value; i.e., OSX
     * conflates the notion of virtual address space used with the
     * resident set size.  In particular, the way NaCl uses virtual
     * address space is to allocate guard pages so that certain
     * addressing modes will not need to be explicitly masked; the
     * guard pages are allocated but inaccessible, never faulted so
     * not even zero-filled on demand, so they should not count
     * against the resident set -- which is supposed to be only the
     * frequently accessed pages in the first place.
     */
#endif

    return LOAD_NO_MEMORY;
  }
  /*
   * The module lives in the middle FOURGIG of the allocated region --
   * we skip over an initial 40G guard.
   */
  *mem = (void *) (((char *) mem_ptr) + NACL_ADDRSPACE_LOWER_GUARD_SIZE);
  NaClLog(4,
          "NaClAllocateSpace: addr space at 0x%016"NACL_PRIxPTR"\n",
          (uintptr_t) *mem);

  return LOAD_OK;
}