static NaClValidationStatus ApplyDfaValidator_x86_64(
    uintptr_t guest_addr,
    uint8_t *data,
    size_t size,
    int stubout_mode,
    uint32_t flags,
    int readonly_text,
    const NaClCPUFeatures *f,
    const struct NaClValidationMetadata *metadata,
    struct NaClValidationCache *cache) {
  /* TODO(jfb) Use a safe cast here. */
  NaClCPUFeaturesX86 *cpu_features = (NaClCPUFeaturesX86 *) f;
  enum NaClValidationStatus status = NaClValidationFailed;
  void *query = NULL;
  struct StubOutCallbackData callback_data;
  callback_data.flags = flags;
  callback_data.did_rewrite = 0;
  UNREFERENCED_PARAMETER(guest_addr);

  if (stubout_mode)
    return NaClValidationFailedNotImplemented;
  if (!NaClArchSupportedX86(cpu_features))
    return NaClValidationFailedCpuNotSupported;
  if (size & kBundleMask)
    return NaClValidationFailed;

  /*
   * If the validation caching interface is available and it would be
   * inexpensive to do so, perform a query.
   */
  if (cache != NULL && NaClCachingIsInexpensive(cache, metadata))
    query = cache->CreateQuery(cache->handle);
  if (query != NULL) {
    const char validator_id[] = "x86-64 dfa";
    cache->AddData(query, (uint8_t *) validator_id, sizeof(validator_id));
    cache->AddData(query, (uint8_t *) cpu_features, sizeof(*cpu_features));
    NaClAddCodeIdentity(data, size, metadata, cache, query);
    if (cache->QueryKnownToValidate(query)) {
      cache->DestroyQuery(query);
      return NaClValidationSucceeded;
    }
  }

  if (readonly_text) {
    if (ValidateChunkAMD64(data, size, 0 /*options*/, cpu_features,
                           NaClDfaProcessValidationError,
                           NULL))
      status = NaClValidationSucceeded;
  } else {
    if (ValidateChunkAMD64(data, size, 0 /*options*/, cpu_features,
                           NaClDfaStubOutUnsupportedInstruction,
                           &callback_data))
      status = NaClValidationSucceeded;
  }

  if (status != NaClValidationSucceeded && errno == ENOMEM)
    status = NaClValidationFailedOutOfMemory;

  /* Cache the result if validation succeeded and the code was not modified. */
  if (query != NULL) {
    if (status == NaClValidationSucceeded && callback_data.did_rewrite == 0)
      cache->SetKnownToValidate(query);
    cache->DestroyQuery(query);
  }

  return status;
}
Esempio n. 2
0
static NaClValidationStatus ApplyValidator_x86_32(
    uintptr_t guest_addr,
    uint8_t *data,
    size_t size,
    int stubout_mode,
    int readonly_text,
    const NaClCPUFeatures *f,
    const struct NaClValidationMetadata *metadata,
    struct NaClValidationCache *cache) {
  /* TODO(jfb) Use a safe cast here. */
  const NaClCPUFeaturesX86 *cpu_features = (NaClCPUFeaturesX86 *) f;
  struct NCValidatorState *vstate;
  int validator_result = 0;
  void *query = NULL;

  /* Check that the given parameter values are supported. */
  if (stubout_mode && readonly_text)
    return NaClValidationFailedNotImplemented;

  if (!NaClArchSupportedX86(cpu_features))
    return NaClValidationFailedCpuNotSupported;

  /* Don't cache in stubout mode. */
  if (stubout_mode)
    cache = NULL;

  /* If the validation caching interface is available, perform a query. */
  if (cache != NULL)
    query = cache->CreateQuery(cache->handle);
  if (query != NULL) {
    const char validator_id[] = "x86-32";
    cache->AddData(query, (uint8_t *) validator_id, sizeof(validator_id));
    cache->AddData(query, (uint8_t *) cpu_features, sizeof(*cpu_features));
    NaClAddCodeIdentity(data, size, metadata, cache, query);
    if (cache->QueryKnownToValidate(query)) {
      cache->DestroyQuery(query);
      return NaClValidationSucceeded;
    }
  }

  /* Init then validator state. */
  /* TODO(ncbray) make "detailed" a parameter. */
  if (stubout_mode) {
    vstate = NCValidateInitDetailed(guest_addr, size, cpu_features);
  } else {
    vstate = NCValidateInit(guest_addr, size, readonly_text, cpu_features);
  }
  if (vstate == NULL) {
    if (query != NULL)
      cache->DestroyQuery(query);
    return NaClValidationFailedOutOfMemory;
  }
  NCValidateSetStubOutMode(vstate, stubout_mode);

  /* Validate. */
  NCValidateSegment(data, guest_addr, size, vstate);
  validator_result = NCValidateFinish(vstate);

  /* Cache the result if validation succeeded and the code was not modified. */
  if (query != NULL) {
    if (validator_result == 0 && !NCValidatorDidStubOut(vstate))
      cache->SetKnownToValidate(query);
    cache->DestroyQuery(query);
  }

  NCValidateFreeState(&vstate);
  return (validator_result == 0 || stubout_mode)
      ? NaClValidationSucceeded : NaClValidationFailed;
}