Example #1
0
NaClErrorCode NaClValidateImage(struct NaClApp  *nap) {
  uintptr_t               memp;
  uintptr_t               endp;
  size_t                  regionsize;
  NaClErrorCode           rcode;

  memp = nap->mem_start + NACL_TRAMPOLINE_END;
  endp = nap->mem_start + nap->static_text_end;
  regionsize = endp - memp;
  if (endp < memp) {
    return LOAD_NO_MEMORY;
  }

  if (nap->skip_validator) {
    NaClLog(LOG_ERROR, "VALIDATION SKIPPED.\n");
    return LOAD_OK;
  } else {
    rcode = NaClValidateCode(nap, NACL_TRAMPOLINE_END,
                             (uint8_t *) memp, regionsize);
    if (LOAD_OK != rcode) {
      if (nap->ignore_validator_result) {
        NaClLog(LOG_ERROR, "VALIDATION FAILED: continuing anyway...\n");
        rcode = LOAD_OK;
      } else {
        NaClLog(LOG_ERROR, "VALIDATION FAILED.\n");
        NaClLog(LOG_ERROR,
                "Run sel_ldr in debug mode to ignore validation failure.\n");
        NaClLog(LOG_ERROR,
                "Run ncval <module-name> for validation error details.\n");
        rcode = LOAD_VALIDATION_FAILED;
      }
    }
  }
  return rcode;
}
Example #2
0
int32_t NaClTextDyncodeCreate(struct NaClApp *nap,
                              uint32_t       dest,
                              void           *code_copy,
                              uint32_t       size,
                              const struct NaClValidationMetadata *metadata) {
  uintptr_t                   dest_addr;
  uint8_t                     *mapped_addr;
  int32_t                     retval = -NACL_ABI_EINVAL;
  int                         validator_result;
  struct NaClPerfCounter      time_dyncode_create;
  NaClPerfCounterCtor(&time_dyncode_create, "NaClTextDyncodeCreate");

  if (NULL == nap->text_shm) {
    NaClLog(1, "NaClTextDyncodeCreate: Dynamic loading not enabled\n");
    return -NACL_ABI_EINVAL;
  }
  if (0 != (dest & (nap->bundle_size - 1)) ||
      0 != (size & (nap->bundle_size - 1))) {
    NaClLog(1, "NaClTextDyncodeCreate: Non-bundle-aligned address or size\n");
    return -NACL_ABI_EINVAL;
  }
  dest_addr = NaClUserToSysAddrRange(nap, dest, size);
  if (kNaClBadAddress == dest_addr) {
    NaClLog(1, "NaClTextDyncodeCreate: Dest address out of range\n");
    return -NACL_ABI_EFAULT;
  }
  if (dest < nap->dynamic_text_start) {
    NaClLog(1, "NaClTextDyncodeCreate: Below dynamic code area\n");
    return -NACL_ABI_EFAULT;
  }
  /*
   * We ensure that the final HLTs of the dynamic code region cannot
   * be overwritten, just in case of CPU bugs.
   */
  if (dest + size > nap->dynamic_text_end - NACL_HALT_SLED_SIZE) {
    NaClLog(1, "NaClTextDyncodeCreate: Above dynamic code area\n");
    return -NACL_ABI_EFAULT;
  }
  if (0 == size) {
    /* Nothing to load.  Succeed trivially. */
    return 0;
  }

  NaClXMutexLock(&nap->dynamic_load_mutex);

  /*
   * Validate the code before trying to create the region.  This avoids the need
   * to delete the region if validation fails.
   * See: http://code.google.com/p/nativeclient/issues/detail?id=2566
   */
  if (!nap->skip_validator) {
    validator_result = NaClValidateCode(nap, dest, code_copy, size, metadata);
  } else {
    NaClLog(LOG_ERROR, "VALIDATION SKIPPED.\n");
    validator_result = LOAD_OK;
  }

  NaClPerfCounterMark(&time_dyncode_create,
                      NACL_PERF_IMPORTANT_PREFIX "DynRegionValidate");
  NaClPerfCounterIntervalLast(&time_dyncode_create);

  if (validator_result != LOAD_OK
      && nap->ignore_validator_result) {
    NaClLog(LOG_ERROR, "VALIDATION FAILED for dynamically-loaded code: "
            "continuing anyway...\n");
    validator_result = LOAD_OK;
  }

  if (validator_result != LOAD_OK) {
    NaClLog(1, "NaClTextDyncodeCreate: "
            "Validation of dynamic code failed\n");
    retval = -NACL_ABI_EINVAL;
    goto cleanup_unlock;
  }

  if (NaClDynamicRegionCreate(nap, dest_addr, size, 0) != 1) {
    /* target addr is in use */
    NaClLog(1, "NaClTextDyncodeCreate: Code range already allocated\n");
    retval = -NACL_ABI_EINVAL;
    goto cleanup_unlock;
  }

  if (!NaClTextMapWrapper(nap, dest, size, &mapped_addr)) {
    retval = -NACL_ABI_ENOMEM;
    goto cleanup_unlock;
  }

  CopyCodeSafelyInitial(mapped_addr, code_copy, size, nap->bundle_size);
  /*
   * Flush the processor's instruction cache.  This is not necessary
   * for security, because any old cached instructions will just be
   * safe halt instructions.  It is only necessary to ensure that
   * untrusted code runs correctly when it tries to execute the
   * dynamically-loaded code.
   */
  NaClFlushCacheForDoublyMappedCode(mapped_addr, (uint8_t *) dest_addr, size);

  retval = 0;

  NaClTextMapClearCacheIfNeeded(nap, dest, size);

 cleanup_unlock:
  NaClXMutexUnlock(&nap->dynamic_load_mutex);
  return retval;
}