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

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: 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 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 Bool NaClDfaProcessPostRewriteValidationError(const uint8_t *begin,
38 const uint8_t *end,
39 uint32_t info,
40 void *callback_data) {
41 UNREFERENCED_PARAMETER(begin);
42 UNREFERENCED_PARAMETER(end);
43 UNREFERENCED_PARAMETER(callback_data);
44
45 if ((info & VALIDATION_ERRORS_MASK) == DIRECT_JUMP_OUT_OF_RANGE)
46 return TRUE;
47 else
48 return FALSE;
49 }
50
51 #if NACL_BUILD_SUBARCH == 64
52 static Bool IsREX(uint8_t byte) {
53 return byte >= 0x40 && byte <= 0x4f;
54 }
55 #endif
56
57 static Bool NaClDfaRewriteUnsupportedInstruction(const uint8_t *begin,
58 const uint8_t *end,
59 uint32_t info,
60 void *callback_data) {
61 uint8_t *ptr = (uint8_t *) begin;
62 struct StubOutCallbackData *data = callback_data;
63 /* Clear DIRECT_JUMP_OUT_OF_RANGE error, because it may be introduced by
64 * validating a bundle which is smaller than the original chunk size. Even if
65 * the orignal chunk has this error, it can be detected when validating the
66 * whole chunk.
67 */
68 info &= ~DIRECT_JUMP_OUT_OF_RANGE;
69 if ((info & VALIDATION_ERRORS_MASK) == 0) {
70 return TRUE;
71 } else if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) {
72 /* Stub-out instructions unsupported on this CPU, but valid on other CPUs.*/
73 data->did_rewrite = 1;
74 memset((uint8_t *)begin, NACL_HALT_OPCODE, end - begin);
75 return TRUE;
76 } else if ((info & VALIDATION_ERRORS_MASK) != UNSUPPORTED_INSTRUCTION) {
77 return FALSE;
78 }
79 /* We usually only check and rewrite the first few bytes without examining
80 * further because this function is only called when the validator tells us
81 * that it is an 'unsupported instruction' and there are no other validation
82 * failures.
83 */
84 #if NACL_BUILD_SUBARCH == 32
85 UNREFERENCED_PARAMETER(end);
86 if (memcmp(begin, "\x0f\xe7", 2) == 0) {
87 /* movntq => movq */
88 ptr[1] = 0x7f;
89 data->did_rewrite = 1;
90 return TRUE;
91 } else if (memcmp(begin, "\x66\x0f\xe7", 3) == 0) {
92 /* movntdq => movdqa */
93 ptr[2] = 0x7f;
94 data->did_rewrite = 1;
95 return TRUE;
96 }
97 #elif NACL_BUILD_SUBARCH == 64
98 if (IsREX(begin[0]) && (begin[1] == 0x0f)) {
99 uint8_t opcode_byte2 = begin[2];
100 switch (opcode_byte2) {
101 case 0x2b:
102 /* movntps => movaps */
103 ptr[2] = 0x29;
104 data->did_rewrite = 1;
105 return TRUE;
106 case 0xc3:
107 /* movnti => mov */
108 if (info & RESTRICTED_REGISTER_USED) {
109 ptr[1] = 0x89;
110 memmove(ptr + 2, ptr + 3, end - begin - 3);
111 ptr[end - begin - 1] = 0x90;
112 } else {
113 ptr[2] = 0x89;
114 ptr[1] = ptr[0];
115 ptr[0] = 0x90;
116 }
117 data->did_rewrite = 1;
118 return TRUE;
119 case 0x18:
120 /* prefetchnta => nop */
121 memset(ptr, 0x90, end - begin);
122 data->did_rewrite = 1;
123 return TRUE;
124 default:
125 return FALSE;
126 }
127 } else if (begin[0] == 0x66 && IsREX(begin[1]) &&
128 memcmp(begin + 2, "\x0f\xe7", 2) == 0) {
129 /* movntdq => movdqa */
130 ptr[3] = 0x7f;
131 data->did_rewrite = 1;
132 return TRUE;
133 }
134 #endif
135 return FALSE;
136 }
137
36 Bool NaClDfaStubOutUnsupportedInstruction(const uint8_t *begin, 138 Bool NaClDfaStubOutUnsupportedInstruction(const uint8_t *begin,
37 const uint8_t *end, 139 const uint8_t *end,
38 uint32_t info, 140 uint32_t info,
39 void *callback_data) { 141 void *callback_data) {
40 struct StubOutCallbackData *data = callback_data; 142 struct StubOutCallbackData *data = callback_data;
41 /* Stub-out instructions unsupported on this CPU, but valid on other CPUs. */ 143 intptr_t addr;
42 if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) { 144 uint8_t *bundle_begin;
43 data->did_rewrite = 1; 145 Bool rc, rc2;
44 memset((uint8_t *)begin, NACL_HALT_OPCODE, end - begin); 146 UNREFERENCED_PARAMETER(end);
45 return TRUE; 147
46 } else if ((info & VALIDATION_ERRORS_MASK) == UNSUPPORTED_INSTRUCTION) { 148 if ((info & VALIDATION_ERRORS_MASK) != CPUID_UNSUPPORTED_INSTRUCTION &&
47 if (data->flags & NACL_DISABLE_NONTEMPORALS_X86) { 149 (info & VALIDATION_ERRORS_MASK) != UNSUPPORTED_INSTRUCTION)
48 return FALSE;
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; 150 return FALSE;
58 } 151 if ((info & VALIDATION_ERRORS_MASK) == UNSUPPORTED_INSTRUCTION &&
152 (data->flags & NACL_DISABLE_NONTEMPORALS_X86))
153 return FALSE;
154
155 CHECK(!data->chunk_processed_as_a_contiguous_stream);
156 addr = ((intptr_t) begin & ~(kBundleMask)) + data->bundle_begin_offset;
157 if (addr > (intptr_t) begin)
158 bundle_begin = (uint8_t *) (addr - kBundleSize);
159 else
160 bundle_begin = (uint8_t *) addr;
161 /* Rewrite a bundle at a time. */
162 #if NACL_BUILD_SUBARCH == 32
163 rc = ValidateChunkIA32(bundle_begin, kBundleSize, 0 /*options*/,
164 (NaClCPUFeaturesX86 *) data->cpu_features,
165 NaClDfaRewriteUnsupportedInstruction,
166 callback_data);
167 #elif NACL_BUILD_SUBARCH == 64
168 rc = ValidateChunkAMD64(bundle_begin, kBundleSize, 0 /*options*/,
169 (NaClCPUFeaturesX86 *) data->cpu_features,
170 NaClDfaRewriteUnsupportedInstruction,
171 callback_data);
172 #endif
173
174 if (!rc)
175 return FALSE;
176
177 /* Revalidate the bundle after rewriting. */
178 #if NACL_BUILD_SUBARCH == 32
179 rc2 = ValidateChunkIA32(bundle_begin, kBundleSize, 0 /*options*/,
180 (NaClCPUFeaturesX86 *) data->cpu_features,
181 NaClDfaProcessPostRewriteValidationError,
182 NULL);
183 #elif NACL_BUILD_SUBARCH == 64
184 rc2 = ValidateChunkAMD64(bundle_begin, kBundleSize, 0 /*options*/,
185 (NaClCPUFeaturesX86 *) data->cpu_features,
186 NaClDfaProcessPostRewriteValidationError,
187 NULL);
188 #endif
189 if (!rc2)
190 return FALSE;
191 return TRUE;
59 } 192 }
60 193
61 Bool NaClDfaProcessCodeCopyInstruction(const uint8_t *begin_new, 194 Bool NaClDfaProcessCodeCopyInstruction(const uint8_t *begin_new,
62 const uint8_t *end_new, 195 const uint8_t *end_new,
63 uint32_t info_new, 196 uint32_t info_new,
64 void *callback_data) { 197 void *callback_data) {
65 struct CodeCopyCallbackData *data = callback_data; 198 struct CodeCopyCallbackData *data = callback_data;
66 size_t instruction_length = end_new - begin_new; 199 size_t instruction_length = end_new - begin_new;
67 200
68 /* Sanity check: instruction must be no longer than 17 bytes. */ 201 /* Sanity check: instruction must be no longer than 17 bytes. */
69 CHECK(instruction_length <= MAX_INSTRUCTION_LENGTH); 202 CHECK(instruction_length <= MAX_INSTRUCTION_LENGTH);
70 203
71 return data->copy_func( 204 return data->copy_func(
72 (uint8_t *)begin_new + data->existing_minus_new, /* begin_existing */ 205 (uint8_t *)begin_new + data->existing_minus_new, /* begin_existing */
73 (info_new & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION ? 206 (info_new & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION ?
74 (uint8_t *)kStubOutMem : 207 (uint8_t *)kStubOutMem :
75 (uint8_t *)begin_new, 208 (uint8_t *)begin_new,
76 (uint8_t)instruction_length); 209 (uint8_t)instruction_length);
77 } 210 }
78 211
79 Bool NaClDfaCodeReplacementIsStubouted(const uint8_t *begin_existing, 212 Bool NaClDfaCodeReplacementIsStubouted(const uint8_t *begin_existing,
80 size_t instruction_length) { 213 size_t instruction_length) {
81 214
82 /* Unsupported instruction must have been replaced with HLTs. */ 215 /* Unsupported instruction must have been replaced with HLTs. */
83 if (memcmp(kStubOutMem, begin_existing, instruction_length) == 0) 216 if (memcmp(kStubOutMem, begin_existing, instruction_length) == 0)
84 return TRUE; 217 return TRUE;
85 else 218 else
86 return FALSE; 219 return FALSE;
87 } 220 }
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