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

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

Issue 3975001: Dynamic code modification support for x64 NaCl modules... (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 10 years, 1 month 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 2009 The Native Client Authors. All rights reserved. 2 * Copyright 2009 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can 3 * Use of this source code is governed by a BSD-style license that can
4 * be found in the LICENSE file. 4 * be found in the LICENSE file.
5 */ 5 */
6 6
7 /* 7 /*
8 * ncvalidate_iter.c 8 * ncvalidate_iter.c
9 * Validate x86 instructions for Native Client 9 * Validate x86 instructions for Native Client
10 * 10 *
11 */ 11 */
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <string.h> 14 #include <string.h>
15 15
16 #include "native_client/src/trusted/validator_x86/ncvalidate_iter.h" 16 #include "native_client/src/trusted/validator_x86/ncvalidate_iter.h"
17 17 #include "native_client/src/shared/platform/nacl_check.h"
18 #include "native_client/src/shared/platform/nacl_log.h" 18 #include "native_client/src/shared/platform/nacl_log.h"
19 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h" 19 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h"
20 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h" 20 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h"
21 #include "native_client/src/trusted/validator_x86/nc_segment.h" 21 #include "native_client/src/trusted/validator_x86/nc_segment.h"
22 #include "native_client/src/trusted/validator_x86/ncop_exps.h" 22 #include "native_client/src/trusted/validator_x86/ncop_exps.h"
23 #include "native_client/src/trusted/validator_x86/ncvalidate_iter_internal.h" 23 #include "native_client/src/trusted/validator_x86/ncvalidate_iter_internal.h"
24 #include "native_client/src/trusted/validator_x86/ncvalidator_registry.h" 24 #include "native_client/src/trusted/validator_x86/ncvalidator_registry.h"
25 25
26 /* To turn on debugging of instruction decoding, change value of 26 /* To turn on debugging of instruction decoding, change value of
27 * DEBUGGING to 1. 27 * DEBUGGING to 1.
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 NaClLogV_mu(level, format, ap); 251 NaClLogV_mu(level, format, ap);
252 va_end(ap); 252 va_end(ap);
253 NaClLogUnlock(); 253 NaClLogUnlock();
254 NaClRecordErrorReported(state, level); 254 NaClRecordErrorReported(state, level);
255 } 255 }
256 if (state->do_stub_out && (level <= LOG_ERROR)) { 256 if (state->do_stub_out && (level <= LOG_ERROR)) {
257 memset(inst->mpc, kNaClFullStop, inst->length); 257 memset(inst->mpc, kNaClFullStop, inst->length);
258 } 258 }
259 } 259 }
260 260
261 void NaClValidatorTwoInstMessage(int level,
262 NaClValidatorState* state,
263 NaClInstState* inst1,
264 NaClInstState* inst2,
265 const char* format,
266 ...) {
267 level = NaClRecordIfValidatorError(state, level);
268 if (NaClPrintValidatorMessages(state, level)) {
269 va_list ap;
270 struct Gio* g = NaClLogGetGio();
271
272 NaClLogLock();
273 /* TODO(karl) - Make printing of instruction state possible via format. */
274 va_start(ap, format);
275 NaClLog_mu(level, "VALIDATOR: %s", NaClLogLevelLabel(level));
276 NaClLogV_mu(level, format, ap);
277 va_end(ap);
278
279 /* TODO(karl): empty fmt strings not allowed */
280 NaClLog_mu(level, "\n%45s ", "VALIDATOR:");
281 NaClInstStateInstPrint(g, inst1);
282 /* TODO(karl): empty fmt strings not allowed */
283 NaClLog_mu(level, "%45s ", "VALIDATOR:");
284 NaClInstStateInstPrint(g, inst2);
285
286 NaClLogUnlock();
287 NaClRecordErrorReported(state, level);
288 }
289 if (state->do_stub_out && (level <= LOG_ERROR)) {
290 memset(inst1->mpc, kNaClFullStop, inst1->length);
291 memset(inst2->mpc, kNaClFullStop, inst2->length);
292 }
293 }
294
261 Bool NaClValidatorQuit(NaClValidatorState* state) { 295 Bool NaClValidatorQuit(NaClValidatorState* state) {
262 return !state->validates_ok && (state->quit_after_error_count == 0); 296 return !state->validates_ok && (state->quit_after_error_count == 0);
263 } 297 }
264 298
265 void NaClRegisterValidator( 299 void NaClRegisterValidator(
266 NaClValidatorState* state, 300 NaClValidatorState* state,
267 NaClValidator validator, 301 NaClValidator validator,
268 NaClValidatorPostValidate post_validate, 302 NaClValidatorPostValidate post_validate,
269 NaClValidatorPrintStats print_stats, 303 NaClValidatorPrintStats print_stats,
270 NaClValidatorMemoryCreate create_memory, 304 NaClValidatorMemoryCreate create_memory,
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 void* NaClGetValidatorLocalMemory(NaClValidator validator, 476 void* NaClGetValidatorLocalMemory(NaClValidator validator,
443 const NaClValidatorState* state) { 477 const NaClValidatorState* state) {
444 int i; 478 int i;
445 for (i = 0; i < state->number_validators; ++i) { 479 for (i = 0; i < state->number_validators; ++i) {
446 if (state->validators[i].validator == validator) { 480 if (state->validators[i].validator == validator) {
447 return state->local_memory[i]; 481 return state->local_memory[i];
448 } 482 }
449 } 483 }
450 return NULL; 484 return NULL;
451 } 485 }
486
487 /*
488 * Check that iter_new is a valid replacement for iter_old.
489 * If a validation error occurs, state->validates_ok will be set to false by
490 * NaClValidatorInstMessage when it is given LOG_ERROR, see the end of this
491 * function.
492 */
493 static void NaClValidateInstReplacement(NaClInstIter* iter_old,
494 NaClInstIter* iter_new,
495 struct NaClValidatorState* state) {
496 NaClInstState *istate_old, *istate_new;
497 NaClExpVector *exp_old, *exp_new;
498 uint32_t i;
499
500 istate_old = NaClInstIterGetState(iter_old);
501 istate_new = NaClInstIterGetState(iter_new);
502
503 /* Location/length must match */
504 if (istate_new->vpc != istate_old->vpc ||
505 istate_new->length != istate_old->length) {
506 NaClValidatorTwoInstMessage(LOG_ERROR, state, istate_old, istate_new,
507 "Code modification: instructions length/addresses do not match");
508 return;
509 }
510
511
512 do {
513 /* fast check if the replacement is identical */
514 if (!memcmp(istate_old->mpc, istate_new->mpc, istate_old->length))
515 return;
516
517 if (istate_old->num_prefix_bytes != istate_new->num_prefix_bytes)
518 break;
519 if (istate_old->num_rex_prefixes != istate_new->num_rex_prefixes)
520 break;
521 if (istate_old->rexprefix != istate_new->rexprefix)
522 break;
523 if (istate_old->modrm != istate_new->modrm)
524 break;
525 if (istate_old->has_sib != istate_new->has_sib)
526 break;
527 if (istate_old->has_sib && istate_old->sib != istate_new->sib)
528 break;
529 if (istate_old->operand_size != istate_new->operand_size)
530 break;
531 if (istate_old->address_size != istate_new->address_size)
532 break;
533 if (istate_old->prefix_mask != istate_new->prefix_mask)
534 break;
535
536 /*
537 * these are pointers, but they reference entries in a static table,
538 * so if the two instructions are the same, then these pointers must
539 * reference the same entry
540 */
541 if (istate_old->inst != istate_new->inst)
542 break;
543
544 exp_old = NaClInstStateExpVector(istate_old);
545 exp_new = NaClInstStateExpVector(istate_new);
546
547 /* check if the instruction operands are identical */
548 if (exp_old->number_expr_nodes != exp_new->number_expr_nodes)
549 break;
550
551 for (i = 0; i < exp_old->number_expr_nodes; i++) {
552 if (exp_old->node[i].kind != exp_new->node[i].kind)
553 break;
554 if (exp_old->node[i].flags != exp_new->node[i].flags)
555 break;
556
557 /*
558 * allow some constants to be different; however it is important not to
559 * allow modification of sandboxing instructions. Note nether of the
560 * instructions allowed for modification is used for sandboxing
561 */
562 if (exp_old->node[i].value != exp_new->node[i].value) {
563 if (exp_old->node[i].kind == ExprConstant) {
564
565 /* allow different constants in direct calls */
566 if (istate_old->inst->name == InstCall)
567 if (exp_old->node[i].flags & NACL_EFLAG(ExprJumpTarget))
568 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
569 == OperandReference)
570 continue;
571
572 /*
573 * allow different constants in operand of mov
574 * e.g. mov $rax, 0xdeadbeef
575 */
576 if (istate_old->inst->name == InstMov)
577 if (exp_old->node[i].flags & NACL_EFLAG(ExprUsed))
578 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
579 == OperandReference)
580 continue;
581 /*
582 * allow different displacements in memory reference of mov
583 * instructions e.g. mov $rax, [$r15+$rbx*2+0x7fff]
584 */
585 if (istate_old->inst->name == InstMov)
586 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
587 == ExprMemOffset)
588 /* displacement is the fourth node after ExprMemOffset node */
589 if (i - NaClGetExpParentIndex(exp_old, i) == 4)
590 continue;
591 }
592 break;
593 }
594 }
595
596 return;
597 } while (0);
598
599 NaClValidatorTwoInstMessage(LOG_ERROR, state, istate_old, istate_new,
600 "Code modification: failed to modify instruction");
601 }
602
603 void NaClValidateSegmentPair(uint8_t* mbase_old, uint8_t* mbase_new,
604 NaClPcAddress vbase, size_t size,
605 struct NaClValidatorState* state) {
606 NaClSegment segment_old, segment_new;
607 NaClInstIter *iter_old, *iter_new;
608
609 NaClValidatorStateInitializeValidators(state);
610 NaClSegmentInitialize(mbase_old, vbase, size, &segment_old);
611 NaClSegmentInitialize(mbase_new, vbase, size, &segment_new);
612 iter_old = NaClInstIterCreateWithLookback(&segment_old, kLookbackSize);
613 iter_new = NaClInstIterCreateWithLookback(&segment_new, kLookbackSize);
614 while (NaClInstIterHasNext(iter_old) &&
615 NaClInstIterHasNext(iter_new)) {
616 state->cur_inst_state = NaClInstIterGetState(iter_new);
617 state->cur_inst = NaClInstStateInst(state->cur_inst_state);
618 state->cur_inst_vector = NaClInstStateExpVector(state->cur_inst_state);
619 NaClApplyValidators(state, iter_new);
620 NaClValidateInstReplacement(iter_old, iter_new, state);
621 if (state->quit) break;
622 NaClInstIterAdvance(iter_old);
623 NaClInstIterAdvance(iter_new);
624 }
625
626 if (NaClInstIterHasNext(iter_old) ||
627 NaClInstIterHasNext(iter_new)) {
628 NaClValidatorMessage(LOG_ERROR, state,
629 "Code modification: code segments have different number of instructions\n");
630 }
631
632 state->cur_inst_state = NULL;
633 state->cur_inst = NULL;
634 state->cur_inst_vector = NULL;
635 NaClApplyPostValidators(state, iter_new);
636 NaClInstIterDestroy(iter_old);
637 NaClInstIterDestroy(iter_new);
638 NaClValidatorStatePrintStats(state);
639 }
640
OLDNEW
« no previous file with comments | « src/trusted/validator_x86/ncvalidate_iter.h ('k') | tests/dynamic_code_loading/dynamic_load_test.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698