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

Side by Side Diff: src/trusted/validator_x86/nccopycode.c

Issue 10134056: Refactor the process of choosing validators. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: tweaks for win64 Created 8 years, 6 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 | Annotate | Revision Log
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 /* 7 /*
8 * nccopycode.c 8 * nccopycode.c
9 * Copies two code streams in a thread-safe way 9 * Copies two code streams in a thread-safe way
10 * 10 *
11 */ 11 */
12 12
13 #include "native_client/src/include/portability.h" 13 #include "native_client/src/include/portability.h"
14 14
15 #if NACL_WINDOWS == 1 15 #if NACL_WINDOWS == 1
16 #include <windows.h> 16 #include <windows.h>
17 #else 17 #else
18 #include <sys/mman.h> 18 #include <sys/mman.h>
19 #endif 19 #endif
20 20
21 #include <stdio.h> 21 #include <stdio.h>
22 #include <stdlib.h> 22 #include <stdlib.h>
23 #include <errno.h> 23 #include <errno.h>
24 #include <string.h> 24 #include <string.h>
25 #include <assert.h> 25 #include <assert.h>
26
26 #include "native_client/src/include/nacl_platform.h" 27 #include "native_client/src/include/nacl_platform.h"
27 #include "native_client/src/shared/platform/nacl_check.h" 28 #include "native_client/src/shared/platform/nacl_check.h"
29 #include "native_client/src/shared/utils/types.h"
28 #include "native_client/src/trusted/service_runtime/sel_ldr.h" 30 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
29 #include "native_client/src/trusted/service_runtime/sel_memory.h" 31 #include "native_client/src/trusted/service_runtime/sel_memory.h"
30 #include "native_client/src/trusted/validator/ncvalidate.h" 32 #include "native_client/src/trusted/validator/ncvalidate.h"
31 33
32 #if NACL_ARCH(NACL_TARGET_ARCH) == NACL_x86
33 # if NACL_TARGET_SUBARCH == 32
34 # include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode.h"
35 # include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.h"
36 # elif NACL_TARGET_SUBARCH == 64
37 # include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h"
38 # include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_intern al.h"
39 # include "native_client/src/trusted/validator/x86/nacl_cpuid.h"
40 # include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncval_decode_t ables.h"
41 # include "native_client/src/trusted/validator/x86/nc_segment.h"
42 # else
43 # error "Unknown Platform"
44 # endif
45 #else
46 # error "Unknown Platform"
47 #endif
48
49 /* x86 HALT opcode */ 34 /* x86 HALT opcode */
50 static const uint8_t kNaClFullStop = 0xf4; 35 static const uint8_t kNaClFullStop = 0xf4;
51 36
52 /* 37 /*
53 * Max size of aligned writes we may issue to code without syncing. 38 * Max size of aligned writes we may issue to code without syncing.
54 * 8 is a safe value according to: 39 * 8 is a safe value according to:
55 * [1] Advance Micro Devices Inc. AMD64 Architecture Program- 40 * [1] Advance Micro Devices Inc. AMD64 Architecture Program-
56 * mers Manual Volume 1: Application Programming, 2009. 41 * mers Manual Volume 1: Application Programming, 2009.
57 * [2] Intel Inc. Intel 64 and IA-32 Architectures Software Developers 42 * [2] Intel Inc. Intel 64 and IA-32 Architectures Software Developers
58 * Manual Volume 3A: System Programming Guide, Part 1, 2010. 43 * Manual Volume 3A: System Programming Guide, Part 1, 2010.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 */ 160 */
176 if (0 != NaCl_mprotect(g_squashybuffer, size, PROT_READ)) { 161 if (0 != NaCl_mprotect(g_squashybuffer, size, PROT_READ)) {
177 NaClLog(0, 162 NaClLog(0,
178 ("SerializeAllProcessors: interprocessor interrupt" 163 ("SerializeAllProcessors: interprocessor interrupt"
179 " generation failed: could not reverse shield polarity (3)\n")); 164 " generation failed: could not reverse shield polarity (3)\n"));
180 return FALSE; 165 return FALSE;
181 } 166 }
182 return TRUE; 167 return TRUE;
183 } 168 }
184 169
185 /* 170 int NaClCopyInstructionX86(uint8_t *dst, uint8_t *src, uint8_t sz) {
186 * Copy a single instruction, avoiding the possibility of other threads
187 * executing a partially changed instruction.
188 */
189 static Bool CopyInstructionInternal(uint8_t *dst,
190 uint8_t *src,
191 uint8_t sz) {
192 intptr_t offset = 0; 171 intptr_t offset = 0;
193 uint8_t *firstbyte_p = dst; 172 uint8_t *firstbyte_p = dst;
194 173
195 while (sz > 0 && dst[0] == src[0]) { 174 while (sz > 0 && dst[0] == src[0]) {
196 /* scroll to first changed byte */ 175 /* scroll to first changed byte */
197 dst++, src++, sz--; 176 dst++, src++, sz--;
198 } 177 }
199 178
200 if (sz == 0) { 179 if (sz == 0) {
201 /* instructions are identical, we are done */ 180 /* instructions are identical, we are done */
202 return TRUE; 181 return 1;
203 } 182 }
204 183
205 while (sz > 0 && dst[sz-1] == src[sz-1]) { 184 while (sz > 0 && dst[sz-1] == src[sz-1]) {
206 /* trim identical bytes at end */ 185 /* trim identical bytes at end */
207 sz--; 186 sz--;
208 } 187 }
209 188
210 if (sz == 1) { 189 if (sz == 1) {
211 /* we assume a 1-byte change is atomic */ 190 /* we assume a 1-byte change is atomic */
212 *dst = *src; 191 *dst = *src;
213 } else if (IsTrustedWrite(dst, sz, 4, &offset)) { 192 } else if (IsTrustedWrite(dst, sz, 4, &offset)) {
214 uint8_t tmp[4]; 193 uint8_t tmp[4];
215 memcpy(tmp, dst-offset, sizeof tmp); 194 memcpy(tmp, dst-offset, sizeof tmp);
216 memcpy(tmp+offset, src, sz); 195 memcpy(tmp+offset, src, sz);
217 onestore_memmove4(dst-offset, tmp); 196 onestore_memmove4(dst-offset, tmp);
218 } else if (IsTrustedWrite(dst, sz, 8, &offset)) { 197 } else if (IsTrustedWrite(dst, sz, 8, &offset)) {
219 uint8_t tmp[8]; 198 uint8_t tmp[8];
220 memcpy(tmp, dst-offset, sizeof tmp); 199 memcpy(tmp, dst-offset, sizeof tmp);
221 memcpy(tmp+offset, src, sz); 200 memcpy(tmp+offset, src, sz);
222 onestore_memmove8(dst-offset, tmp); 201 onestore_memmove8(dst-offset, tmp);
223 } else { 202 } else {
224 /* the slow path, first flip first byte to halt*/ 203 /* the slow path, first flip first byte to halt*/
225 uint8_t firstbyte = firstbyte_p[0]; 204 uint8_t firstbyte = firstbyte_p[0];
226 firstbyte_p[0] = kNaClFullStop; 205 firstbyte_p[0] = kNaClFullStop;
227 206
228 if (!SerializeAllProcessors()) return FALSE; 207 if (!SerializeAllProcessors()) return 0;
229 208
230 /* copy the rest of instruction */ 209 /* copy the rest of instruction */
231 if (dst == firstbyte_p) { 210 if (dst == firstbyte_p) {
232 /* but not the first byte! */ 211 /* but not the first byte! */
233 firstbyte = *src; 212 firstbyte = *src;
234 dst++, src++, sz--; 213 dst++, src++, sz--;
235 } 214 }
236 memcpy(dst, src, sz); 215 memcpy(dst, src, sz);
237 216
238 if (!SerializeAllProcessors()) return FALSE; 217 if (!SerializeAllProcessors()) return 0;
239 218
240 /* flip first byte back */ 219 /* flip first byte back */
241 firstbyte_p[0] = firstbyte; 220 firstbyte_p[0] = firstbyte;
242 } 221 }
243 return TRUE; 222 return 1;
244 } 223 }
245
246 #if NACL_TARGET_SUBARCH == 32
247
248 /*
249 * Copy a single instruction, avoiding the possibility of other threads
250 * executing a partially changed instruction.
251 */
252 static Bool CopyInstruction(NCDecoderStatePair* tthis,
253 NCDecoderInst *dinst_old,
254 NCDecoderInst *dinst_new) {
255 NCRemainingMemory* mem_old = &dinst_old->dstate->memory;
256 NCRemainingMemory* mem_new = &dinst_new->dstate->memory;
257
258 return CopyInstructionInternal(mem_old->mpc,
259 mem_new->mpc,
260 mem_old->read_length);
261 }
262
263 int NCCopyCode(uint8_t *dst, uint8_t *src, NaClPcAddress vbase,
264 size_t sz) {
265 NCDecoderState dst_dstate;
266 NCDecoderInst dst_inst;
267 NCDecoderState src_dstate;
268 NCDecoderInst src_inst;
269 NCDecoderStatePair pair;
270 int result = 0;
271
272 NCDecoderStateConstruct(&dst_dstate, dst, vbase, sz, &dst_inst, 1);
273 NCDecoderStateConstruct(&src_dstate, src, vbase, sz, &src_inst, 1);
274 NCDecoderStatePairConstruct(&pair, &dst_dstate, &src_dstate);
275 pair.action_fn = CopyInstruction;
276 if (NCDecoderStatePairDecode(&pair)) result = 1;
277 NCDecoderStatePairDestruct(&pair);
278 NCDecoderStateDestruct(&src_dstate);
279 NCDecoderStateDestruct(&dst_dstate);
280
281 return result;
282 }
283
284 NaClValidationStatus NACL_SUBARCH_NAME(ApplyValidatorCopy,
285 NACL_TARGET_ARCH,
286 NACL_TARGET_SUBARCH)
287 (uintptr_t guest_addr,
288 uint8_t *data_old,
289 uint8_t *data_new,
290 size_t size,
291 const NaClCPUFeaturesX86 *cpu_features) {
292 if (!NaClArchSupported(cpu_features))
293 return NaClValidationFailedCpuNotSupported;
294
295 return ((0 == NCCopyCode(data_old, data_new, guest_addr,
296 size))
297 ? NaClValidationFailed : NaClValidationSucceeded);
298 }
299
300 #elif NACL_TARGET_SUBARCH == 64
301
302 int NaClCopyCodeIter(uint8_t *dst, uint8_t *src,
303 NaClPcAddress vbase, size_t size) {
304 NaClSegment segment_old, segment_new;
305 NaClInstIter *iter_old, *iter_new;
306 NaClInstState *istate_old, *istate_new;
307 int still_good = 1;
308
309 NaClSegmentInitialize(dst, vbase, size, &segment_old);
310 NaClSegmentInitialize(src, vbase, size, &segment_new);
311
312 iter_old = NaClInstIterCreate(kNaClValDecoderTables, &segment_old);
313 if (NULL == iter_old) return 0;
314 iter_new = NaClInstIterCreate(kNaClValDecoderTables, &segment_new);
315 if (NULL == iter_new) {
316 NaClInstIterDestroy(iter_old);
317 return 0;
318 }
319 while (1) {
320 /* March over every instruction, which means NaCl pseudo-instructions are
321 * treated as multiple instructions. Checks in NaClValidateCodeReplacement
322 * guarantee that only valid replacements will happen, and no pseudo-
323 * instructions should be touched.
324 */
325 if (!(NaClInstIterHasNext(iter_old) && NaClInstIterHasNext(iter_new))) {
326 if (NaClInstIterHasNext(iter_old) || NaClInstIterHasNext(iter_new)) {
327 NaClLog(LOG_ERROR,
328 "Segment replacement: copy failed: iterators "
329 "length mismatch\n");
330 still_good = 0;
331 }
332 break;
333 }
334 istate_old = NaClInstIterGetState(iter_old);
335 istate_new = NaClInstIterGetState(iter_new);
336 if (istate_old->bytes.length != istate_new->bytes.length ||
337 iter_old->memory.read_length != iter_new->memory.read_length ||
338 istate_new->inst_addr != istate_old->inst_addr) {
339 /* Sanity check: this should never happen based on checks in
340 * NaClValidateInstReplacement.
341 */
342 NaClLog(LOG_ERROR,
343 "Segment replacement: copied instructions misaligned\n");
344 still_good = 0;
345 break;
346 }
347 /* Replacing all modified instructions at once could yield a speedup here
348 * as every time we modify instructions we must serialize all processors
349 * twice. Re-evaluate if code modification performance is an issue.
350 */
351 if (!CopyInstructionInternal(iter_old->memory.mpc,
352 iter_new->memory.mpc,
353 iter_old->memory.read_length)) {
354 NaClLog(LOG_ERROR,
355 "Segment replacement: copy failed: unable to copy instruction\n");
356 still_good = 0;
357 break;
358 }
359 NaClInstIterAdvance(iter_old);
360 NaClInstIterAdvance(iter_new);
361 }
362
363 NaClInstIterDestroy(iter_old);
364 NaClInstIterDestroy(iter_new);
365 return still_good;
366 }
367
368 NaClValidationStatus NACL_SUBARCH_NAME(ApplyValidatorCopy,
369 NACL_TARGET_ARCH,
370 NACL_TARGET_SUBARCH)
371 (uintptr_t guest_addr,
372 uint8_t *data_old,
373 uint8_t *data_new,
374 size_t size,
375 const NaClCPUFeaturesX86 *cpu_features) {
376 if (!NaClArchSupported(cpu_features))
377 return NaClValidationFailedCpuNotSupported;
378
379 return (0 == NaClCopyCodeIter(data_old, data_new, guest_addr, size))
380 ? NaClValidationFailed : NaClValidationSucceeded;
381 }
382
383 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698