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

Side by Side 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: Cleanup 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 unified diff | Download patch
« no previous file with comments | « src/trusted/validator_ragel/dfa_validate_common.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 /* Implement the functions common for ia32 and x86-64 architectures. */ 7 /* Implement the functions common for ia32 and x86-64 architectures. */
8 #include "native_client/src/trusted/validator_ragel/dfa_validate_common.h" 8 #include "native_client/src/trusted/validator_ragel/dfa_validate_common.h"
9 9
10 #include <string.h> 10 #include <string.h>
11 11
12 #include "native_client/src/shared/platform/nacl_check.h" 12 #include "native_client/src/shared/platform/nacl_check.h"
13 #include "native_client/src/trusted/service_runtime/nacl_config.h" 13 #include "native_client/src/trusted/service_runtime/nacl_config.h"
14 #include "native_client/src/trusted/validator_ragel/validator.h" 14 #include "native_client/src/trusted/validator_ragel/validator.h"
15 #include "native_client/src/include/build_config.h"
15 16
16 /* Used as an argument to copy_func when unsupported instruction must be 17 /* Used as an argument to copy_func when unsupported instruction must be
17 replaced with HLTs. */ 18 replaced with HLTs. */
18 static const uint8_t kStubOutMem[MAX_INSTRUCTION_LENGTH] = { 19 static const uint8_t kStubOutMem[MAX_INSTRUCTION_LENGTH] = {
19 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, 20 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE,
20 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, 21 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE,
21 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, 22 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE,
22 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, 23 NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE, NACL_HALT_OPCODE,
23 NACL_HALT_OPCODE 24 NACL_HALT_OPCODE
24 }; 25 };
25 26
26 Bool NaClDfaProcessValidationError(const uint8_t *begin, const uint8_t *end, 27 Bool NaClDfaProcessValidationError(const uint8_t *begin, const uint8_t *end,
27 uint32_t info, void *callback_data) { 28 uint32_t info, void *callback_data) {
28 UNREFERENCED_PARAMETER(begin); 29 UNREFERENCED_PARAMETER(begin);
29 UNREFERENCED_PARAMETER(end); 30 UNREFERENCED_PARAMETER(end);
30 UNREFERENCED_PARAMETER(info); 31 UNREFERENCED_PARAMETER(info);
31 UNREFERENCED_PARAMETER(callback_data); 32 UNREFERENCED_PARAMETER(callback_data);
32 33
33 return FALSE; 34 return FALSE;
34 } 35 }
35 36
37 #if NACL_BUILD_SUBARCH == 64
38 static Bool IsREX(uint8_t byte) {
39 return byte >= 0x40 && byte <= 0x4f;
40 }
41 #endif
42
43 static Bool NaClRewriteUnsupportedInstruction(const uint8_t *begin,
44 const uint8_t *end,
45 uint32_t info,
46 void *callback_data) {
47 uint8_t *ptr = (uint8_t *) begin;
48 struct StubOutCallbackData *data = callback_data;
49 if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) {
khimg 2015/08/10 00:51:43 Instead of VALIDATION_ERRORS_MASK we must use (VAL
50 /* Stub-out instructions unsupported on this CPU, but valid on other CPUs.*/
51 data->did_rewrite = 1;
52 memset((uint8_t *)begin, NACL_HALT_OPCODE, end - begin);
53 return TRUE;
54 } else if ((info & VALIDATION_ERRORS_MASK) != UNSUPPORTED_INSTRUCTION) {
55 return FALSE;
56 }
57 /* We usually only check and rewrite the first few bytes without examining
58 * further because this function is only called when the validator tells us
59 * that it is an 'unsupported instruction' and there are no other validation
60 * failures.
61 */
62 #if NACL_BUILD_SUBARCH == 32
63 UNREFERENCED_PARAMETER(end);
64 if (memcmp(begin, "\x0f\xe7", 2) == 0) {
65 /* movntq => movq */
66 ptr[1] = 0x7f;
67 data->did_rewrite = 1;
68 return TRUE;
69 } else if (memcmp(begin, "\x66\x0f\xe7", 3) == 0) {
70 /* movntdq => movdqa */
71 ptr[2] = 0x7f;
72 data->did_rewrite = 1;
73 return TRUE;
74 }
75 #elif NACL_BUILD_SUBARCH == 64
76 if (IsREX(begin[0]) && (begin[1] == 0x0f)) {
77 uint8_t opcode_byte2 = begin[2];
78 switch (opcode_byte2) {
79 case 0x2b:
80 /* movntps => movaps */
81 ptr[2] = 0x29;
82 data->did_rewrite = 1;
83 return TRUE;
84 case 0xc3:
85 /* movnti => mov */
86 ptr[1] = 0x89;
87 memmove(ptr + 2, ptr + 3, end - begin - 3);
88 ptr[end - begin - 1] = 0x90;
khimg 2015/08/10 00:51:43 Please insert NOP before mov, not after! Think abo
89 data->did_rewrite = 1;
90 return TRUE;
91 case 0x18:
92 /* prefetchnta => nop */
93 memset(ptr, 0x90, end - begin);
94 data->did_rewrite = 1;
95 return TRUE;
96 default:
97 return FALSE;
98 }
99 } else if (begin[0] == 0x66 && IsREX(begin[1]) &&
100 memcmp(begin + 2, "\x0f\xe7", 2) == 0) {
101 /* movntdq => movdqa */
102 ptr[3] = 0x7f;
103 data->did_rewrite = 1;
104 return TRUE;
105 }
106 #endif
107 return FALSE;
108 }
109
36 Bool NaClDfaStubOutUnsupportedInstruction(const uint8_t *begin, 110 Bool NaClDfaStubOutUnsupportedInstruction(const uint8_t *begin,
37 const uint8_t *end, 111 const uint8_t *end,
38 uint32_t info, 112 uint32_t info,
39 void *callback_data) { 113 void *callback_data) {
40 struct StubOutCallbackData *data = callback_data; 114 struct StubOutCallbackData *data = callback_data;
41 /* Stub-out instructions unsupported on this CPU, but valid on other CPUs. */ 115 struct StubOutCallbackData reval_data = *data;
42 if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) { 116 intptr_t addr;
43 data->did_rewrite = 1; 117 uint8_t *bundle_begin;
44 memset((uint8_t *)begin, NACL_HALT_OPCODE, end - begin); 118 Bool rc, rc2;
45 return TRUE; 119 UNREFERENCED_PARAMETER(end);
46 } else if ((info & VALIDATION_ERRORS_MASK) == UNSUPPORTED_INSTRUCTION) { 120
47 if (data->flags & NACL_DISABLE_NONTEMPORALS_X86) { 121 if ((info & VALIDATION_ERRORS_MASK) != CPUID_UNSUPPORTED_INSTRUCTION &&
48 return FALSE; 122 (info & VALIDATION_ERRORS_MASK) != UNSUPPORTED_INSTRUCTION)
49 } else {
50 /* TODO(ruiq): rewrite instruction. For now, we keep the original
51 * instruction and indicate validation success, which is consistent
52 * with current validation results. */
53 data->did_rewrite = 0;
54 return TRUE;
55 }
56 } else {
57 return FALSE; 123 return FALSE;
58 } 124 if ((info & VALIDATION_ERRORS_MASK) == UNSUPPORTED_INSTRUCTION &&
125 (data->flags & NACL_DISABLE_NONTEMPORALS_X86))
126 return FALSE;
127
128 CHECK(!data->chunk_processed_as_a_contiguous_stream);
129 addr = ((intptr_t) begin & ~(kBundleMask)) + data->bundle_begin_offset;
130 if (addr > (intptr_t) begin)
131 bundle_begin = (uint8_t *) (addr - kBundleSize);
132 else
133 bundle_begin = (uint8_t *) addr;
ruiq 2015/08/10 00:26:08 We need to compute bundle_begin this way because t
134 /* Rewrite a bundle at a time. */
135 #if NACL_BUILD_SUBARCH == 32
136 rc = ValidateChunkIA32(bundle_begin, kBundleSize, 0 /*options*/,
137 (NaClCPUFeaturesX86 *) data->cpu_features,
138 NaClRewriteUnsupportedInstruction,
139 callback_data);
140 #elif NACL_BUILD_SUBARCH == 64
141 rc = ValidateChunkAMD64(bundle_begin, kBundleSize, 0 /*options*/,
142 (NaClCPUFeaturesX86 *) data->cpu_features,
143 NaClRewriteUnsupportedInstruction,
144 callback_data);
145 #endif
146
147 if (!rc)
148 return FALSE;
149
150 /* Revalidate the bundle after rewriting. */
151 #if NACL_BUILD_SUBARCH == 32
152 rc2 = ValidateChunkIA32(bundle_begin, kBundleSize, 0 /*options*/,
153 (NaClCPUFeaturesX86 *) data->cpu_features,
154 NaClRewriteUnsupportedInstruction,
155 &reval_data);
156 #elif NACL_BUILD_SUBARCH == 64
157 rc2 = ValidateChunkAMD64(bundle_begin, kBundleSize, 0 /*options*/,
158 (NaClCPUFeaturesX86 *) data->cpu_features,
159 NaClRewriteUnsupportedInstruction,
160 &reval_data);
161 #endif
162 if (!rc2 || reval_data.did_rewrite)
163 return FALSE;
164 return TRUE;
59 } 165 }
60 166
61 Bool NaClDfaProcessCodeCopyInstruction(const uint8_t *begin_new, 167 Bool NaClDfaProcessCodeCopyInstruction(const uint8_t *begin_new,
62 const uint8_t *end_new, 168 const uint8_t *end_new,
63 uint32_t info_new, 169 uint32_t info_new,
64 void *callback_data) { 170 void *callback_data) {
65 struct CodeCopyCallbackData *data = callback_data; 171 struct CodeCopyCallbackData *data = callback_data;
66 size_t instruction_length = end_new - begin_new; 172 size_t instruction_length = end_new - begin_new;
67 173
68 /* Sanity check: instruction must be no longer than 17 bytes. */ 174 /* Sanity check: instruction must be no longer than 17 bytes. */
69 CHECK(instruction_length <= MAX_INSTRUCTION_LENGTH); 175 CHECK(instruction_length <= MAX_INSTRUCTION_LENGTH);
70 176
71 return data->copy_func( 177 return data->copy_func(
72 (uint8_t *)begin_new + data->existing_minus_new, /* begin_existing */ 178 (uint8_t *)begin_new + data->existing_minus_new, /* begin_existing */
73 (info_new & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION ? 179 (info_new & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION ?
74 (uint8_t *)kStubOutMem : 180 (uint8_t *)kStubOutMem :
75 (uint8_t *)begin_new, 181 (uint8_t *)begin_new,
76 (uint8_t)instruction_length); 182 (uint8_t)instruction_length);
77 } 183 }
78 184
79 Bool NaClDfaCodeReplacementIsStubouted(const uint8_t *begin_existing, 185 Bool NaClDfaCodeReplacementIsStubouted(const uint8_t *begin_existing,
80 size_t instruction_length) { 186 size_t instruction_length) {
81 187
82 /* Unsupported instruction must have been replaced with HLTs. */ 188 /* Unsupported instruction must have been replaced with HLTs. */
83 if (memcmp(kStubOutMem, begin_existing, instruction_length) == 0) 189 if (memcmp(kStubOutMem, begin_existing, instruction_length) == 0)
84 return TRUE; 190 return TRUE;
85 else 191 else
86 return FALSE; 192 return FALSE;
87 } 193 }
OLDNEW
« 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