Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1287)

Unified Diff: src/trusted/validator_ragel/dfa_validate_common.c

Issue 1276543006: Experimental: Bundle revalidation inside user callback Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Fix error checking Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/trusted/validator_ragel/dfa_validate_common.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/trusted/validator_ragel/dfa_validate_common.c
diff --git a/src/trusted/validator_ragel/dfa_validate_common.c b/src/trusted/validator_ragel/dfa_validate_common.c
index 4972cbd654b3fcd0d884dec0099db63750991802..3a4c96c623e989559e56b24ed292935e889eb6fd 100644
--- a/src/trusted/validator_ragel/dfa_validate_common.c
+++ b/src/trusted/validator_ragel/dfa_validate_common.c
@@ -12,6 +12,7 @@
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/service_runtime/nacl_config.h"
#include "native_client/src/trusted/validator_ragel/validator.h"
+#include "native_client/src/include/build_config.h"
/* Used as an argument to copy_func when unsupported instruction must be
replaced with HLTs. */
@@ -33,29 +34,161 @@ Bool NaClDfaProcessValidationError(const uint8_t *begin, const uint8_t *end,
return FALSE;
}
-Bool NaClDfaStubOutUnsupportedInstruction(const uint8_t *begin,
+Bool NaClDfaProcessPostRewriteValidationError(const uint8_t *begin,
+ const uint8_t *end,
+ uint32_t info,
+ void *callback_data) {
+ UNREFERENCED_PARAMETER(begin);
+ UNREFERENCED_PARAMETER(end);
+ UNREFERENCED_PARAMETER(callback_data);
+
+ if ((info & VALIDATION_ERRORS_MASK) == DIRECT_JUMP_OUT_OF_RANGE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+#if NACL_BUILD_SUBARCH == 64
+static Bool IsREX(uint8_t byte) {
+ return byte >= 0x40 && byte <= 0x4f;
+}
+#endif
+
+static Bool NaClDfaRewriteUnsupportedInstruction(const uint8_t *begin,
const uint8_t *end,
uint32_t info,
void *callback_data) {
+ uint8_t *ptr = (uint8_t *) begin;
struct StubOutCallbackData *data = callback_data;
- /* Stub-out instructions unsupported on this CPU, but valid on other CPUs. */
- if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) {
+ /* Clear DIRECT_JUMP_OUT_OF_RANGE error, because it may be introduced by
+ * validating a bundle which is smaller than the original chunk size. Even if
+ * the orignal chunk has this error, it can be detected when validating the
+ * whole chunk.
+ */
+ info &= ~DIRECT_JUMP_OUT_OF_RANGE;
+ if ((info & VALIDATION_ERRORS_MASK) == 0) {
+ return TRUE;
+ } else if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) {
+ /* Stub-out instructions unsupported on this CPU, but valid on other CPUs.*/
data->did_rewrite = 1;
memset((uint8_t *)begin, NACL_HALT_OPCODE, end - begin);
return TRUE;
- } else if ((info & VALIDATION_ERRORS_MASK) == UNSUPPORTED_INSTRUCTION) {
- if (data->flags & NACL_DISABLE_NONTEMPORALS_X86) {
- return FALSE;
- } else {
- /* TODO(ruiq): rewrite instruction. For now, we keep the original
- * instruction and indicate validation success, which is consistent
- * with current validation results. */
- data->did_rewrite = 0;
- return TRUE;
- }
- } else {
+ } else if ((info & VALIDATION_ERRORS_MASK) != UNSUPPORTED_INSTRUCTION) {
return FALSE;
}
+ /* We usually only check and rewrite the first few bytes without examining
+ * further because this function is only called when the validator tells us
+ * that it is an 'unsupported instruction' and there are no other validation
+ * failures.
+ */
+#if NACL_BUILD_SUBARCH == 32
+ UNREFERENCED_PARAMETER(end);
+ if (memcmp(begin, "\x0f\xe7", 2) == 0) {
+ /* movntq => movq */
+ ptr[1] = 0x7f;
+ data->did_rewrite = 1;
+ return TRUE;
+ } else if (memcmp(begin, "\x66\x0f\xe7", 3) == 0) {
+ /* movntdq => movdqa */
+ ptr[2] = 0x7f;
+ data->did_rewrite = 1;
+ return TRUE;
+ }
+#elif NACL_BUILD_SUBARCH == 64
+ if (IsREX(begin[0]) && (begin[1] == 0x0f)) {
+ uint8_t opcode_byte2 = begin[2];
+ switch (opcode_byte2) {
+ case 0x2b:
+ /* movntps => movaps */
+ ptr[2] = 0x29;
+ data->did_rewrite = 1;
+ return TRUE;
+ case 0xc3:
+ /* movnti => mov */
+ if (info & RESTRICTED_REGISTER_USED) {
+ ptr[1] = 0x89;
+ memmove(ptr + 2, ptr + 3, end - begin - 3);
+ ptr[end - begin - 1] = 0x90;
+ } else {
+ ptr[2] = 0x89;
+ ptr[1] = ptr[0];
+ ptr[0] = 0x90;
+ }
+ data->did_rewrite = 1;
+ return TRUE;
+ case 0x18:
+ /* prefetchnta => nop */
+ memset(ptr, 0x90, end - begin);
+ data->did_rewrite = 1;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ } else if (begin[0] == 0x66 && IsREX(begin[1]) &&
+ memcmp(begin + 2, "\x0f\xe7", 2) == 0) {
+ /* movntdq => movdqa */
+ ptr[3] = 0x7f;
+ data->did_rewrite = 1;
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+Bool NaClDfaStubOutUnsupportedInstruction(const uint8_t *begin,
+ const uint8_t *end,
+ uint32_t info,
+ void *callback_data) {
+ struct StubOutCallbackData *data = callback_data;
+ intptr_t addr;
+ uint8_t *bundle_begin;
+ Bool rc, rc2;
+ UNREFERENCED_PARAMETER(end);
+
+ if ((info & VALIDATION_ERRORS_MASK) != CPUID_UNSUPPORTED_INSTRUCTION &&
+ (info & VALIDATION_ERRORS_MASK) != UNSUPPORTED_INSTRUCTION)
+ return FALSE;
+ if ((info & VALIDATION_ERRORS_MASK) == UNSUPPORTED_INSTRUCTION &&
+ (data->flags & NACL_DISABLE_NONTEMPORALS_X86))
+ return FALSE;
+
+ CHECK(!data->chunk_processed_as_a_contiguous_stream);
+ addr = ((intptr_t) begin & ~(kBundleMask)) + data->bundle_begin_offset;
+ if (addr > (intptr_t) begin)
+ bundle_begin = (uint8_t *) (addr - kBundleSize);
+ else
+ bundle_begin = (uint8_t *) addr;
+ /* Rewrite a bundle at a time. */
+#if NACL_BUILD_SUBARCH == 32
+ rc = ValidateChunkIA32(bundle_begin, kBundleSize, 0 /*options*/,
+ (NaClCPUFeaturesX86 *) data->cpu_features,
+ NaClDfaRewriteUnsupportedInstruction,
+ callback_data);
+#elif NACL_BUILD_SUBARCH == 64
+ rc = ValidateChunkAMD64(bundle_begin, kBundleSize, 0 /*options*/,
+ (NaClCPUFeaturesX86 *) data->cpu_features,
+ NaClDfaRewriteUnsupportedInstruction,
+ callback_data);
+#endif
+
+ if (!rc)
+ return FALSE;
+
+ /* Revalidate the bundle after rewriting. */
+#if NACL_BUILD_SUBARCH == 32
+ rc2 = ValidateChunkIA32(bundle_begin, kBundleSize, 0 /*options*/,
+ (NaClCPUFeaturesX86 *) data->cpu_features,
+ NaClDfaProcessPostRewriteValidationError,
+ NULL);
+#elif NACL_BUILD_SUBARCH == 64
+ rc2 = ValidateChunkAMD64(bundle_begin, kBundleSize, 0 /*options*/,
+ (NaClCPUFeaturesX86 *) data->cpu_features,
+ NaClDfaProcessPostRewriteValidationError,
+ NULL);
+#endif
+ if (!rc2)
+ return FALSE;
+ return TRUE;
}
Bool NaClDfaProcessCodeCopyInstruction(const uint8_t *begin_new,
« no previous file with comments | « src/trusted/validator_ragel/dfa_validate_common.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698