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

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

Issue 5738003: Resurrect Petr's 64-bit dynamic code modification CL:... (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: fix first round of my own feedback Created 10 years 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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 NaClLogV_mu(level, format, ap); 252 NaClLogV_mu(level, format, ap);
253 va_end(ap); 253 va_end(ap);
254 NaClLogUnlock(); 254 NaClLogUnlock();
255 NaClRecordErrorReported(state, level); 255 NaClRecordErrorReported(state, level);
256 } 256 }
257 if (state->do_stub_out && (level <= LOG_ERROR)) { 257 if (state->do_stub_out && (level <= LOG_ERROR)) {
258 memset(inst->mpc, kNaClFullStop, inst->length); 258 memset(inst->mpc, kNaClFullStop, inst->length);
259 } 259 }
260 } 260 }
261 261
262 void NaClValidatorTwoInstMessage(int level,
263 NaClValidatorState* state,
264 NaClInstState* inst1,
265 NaClInstState* inst2,
266 const char* format,
267 ...) {
268 level = NaClRecordIfValidatorError(state, level);
269 if (NaClPrintValidatorMessages(state, level)) {
270 va_list ap;
271 struct Gio* g = NaClLogGetGio();
272
273 NaClLogLock();
274 /* TODO(karl) - Make printing of instruction state possible via format. */
275 va_start(ap, format);
276 NaClLog_mu(level, "VALIDATOR: %s", NaClLogLevelLabel(level));
277 NaClLogV_mu(level, format, ap);
278 va_end(ap);
279
280 /* TODO(karl): empty fmt strings not allowed */
281 NaClLog_mu(level, "\n%45s ", "VALIDATOR:");
282 NaClInstStateInstPrint(g, inst1);
283 /* TODO(karl): empty fmt strings not allowed */
284 NaClLog_mu(level, "%45s ", "VALIDATOR:");
285 NaClInstStateInstPrint(g, inst2);
286
287 NaClLogUnlock();
288 NaClRecordErrorReported(state, level);
289 }
290 if (state->do_stub_out && (level <= LOG_ERROR)) {
bsy 2010/12/15 04:06:50 this appears to be dead code, since do_stub_out mu
elijahtaylor (use chromium) 2010/12/15 21:26:37 I'm very unfamiliar with this, so I haven't done t
291 memset(inst1->mpc, kNaClFullStop, inst1->length);
292 memset(inst2->mpc, kNaClFullStop, inst2->length);
293 }
294 }
295
262 Bool NaClValidatorQuit(NaClValidatorState* state) { 296 Bool NaClValidatorQuit(NaClValidatorState* state) {
263 return !state->validates_ok && (state->quit_after_error_count == 0); 297 return !state->validates_ok && (state->quit_after_error_count == 0);
264 } 298 }
265 299
266 void NaClRegisterValidator( 300 void NaClRegisterValidator(
267 NaClValidatorState* state, 301 NaClValidatorState* state,
268 NaClValidator validator, 302 NaClValidator validator,
269 NaClValidatorPostValidate post_validate, 303 NaClValidatorPostValidate post_validate,
270 NaClValidatorPrintStats print_stats, 304 NaClValidatorPrintStats print_stats,
271 NaClValidatorMemoryCreate create_memory, 305 NaClValidatorMemoryCreate create_memory,
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 void* NaClGetValidatorLocalMemory(NaClValidator validator, 477 void* NaClGetValidatorLocalMemory(NaClValidator validator,
444 const NaClValidatorState* state) { 478 const NaClValidatorState* state) {
445 int i; 479 int i;
446 for (i = 0; i < state->number_validators; ++i) { 480 for (i = 0; i < state->number_validators; ++i) {
447 if (state->validators[i].validator == validator) { 481 if (state->validators[i].validator == validator) {
448 return state->local_memory[i]; 482 return state->local_memory[i];
449 } 483 }
450 } 484 }
451 return NULL; 485 return NULL;
452 } 486 }
487
488 /*
489 * Check that iter_new is a valid replacement for iter_old.
490 * If a validation error occurs, state->validates_ok will be set to false by
491 * NaClValidatorInstMessage when it is given LOG_ERROR, see the end of this
492 * function.
493 */
494 static void NaClValidateInstReplacement(NaClInstIter* iter_old,
495 NaClInstIter* iter_new,
496 struct NaClValidatorState* state) {
497 NaClInstState *istate_old, *istate_new;
498 NaClExpVector *exp_old, *exp_new;
499 uint32_t i;
500 Bool error_in_nodes;
501
502 istate_old = NaClInstIterGetState(iter_old);
503 istate_new = NaClInstIterGetState(iter_new);
504
505 /* Location/length must match */
506 if (istate_new->vpc != istate_old->vpc ||
507 istate_new->length != istate_old->length) {
508 NaClValidatorTwoInstMessage(LOG_ERROR, state, istate_old, istate_new,
509 "Code modification: instructions length/addresses do not match");
510 return;
511 }
512
513
514 do {
515 /* fast check if the replacement is identical */
516 if (!memcmp(istate_old->mpc, istate_new->mpc, istate_old->length))
517 return;
518
519 if (istate_old->num_prefix_bytes != istate_new->num_prefix_bytes)
520 break;
521 if (istate_old->num_rex_prefixes != istate_new->num_rex_prefixes)
522 break;
523 if (istate_old->rexprefix != istate_new->rexprefix)
524 break;
525 if (istate_old->modrm != istate_new->modrm)
526 break;
527 if (istate_old->has_sib != istate_new->has_sib)
528 break;
529 if (istate_old->has_sib && istate_old->sib != istate_new->sib)
530 break;
531 if (istate_old->operand_size != istate_new->operand_size)
532 break;
533 if (istate_old->address_size != istate_new->address_size)
534 break;
535 if (istate_old->prefix_mask != istate_new->prefix_mask)
536 break;
537
538 /*
539 * these are pointers, but they reference entries in a static table,
540 * so if the two instructions are the same, then these pointers must
541 * reference the same entry
542 */
543 if (istate_old->inst != istate_new->inst)
544 break;
545
546 exp_old = NaClInstStateExpVector(istate_old);
547 exp_new = NaClInstStateExpVector(istate_new);
548
549 /* check if the instruction operands are identical */
550 if (exp_old->number_expr_nodes != exp_new->number_expr_nodes)
551 break;
552
553 error_in_nodes = FALSE;
554 for (i = 0; i < exp_old->number_expr_nodes; i++) {
555 if (exp_old->node[i].kind != exp_new->node[i].kind) {
556 error_in_nodes = TRUE;
bsy 2010/12/15 04:06:50 consider using a goto for the double break here an
elijahtaylor (use chromium) 2010/12/15 21:26:37 I am loath to "goto", but I agree that's clearer i
557 break;
558 }
559 if (exp_old->node[i].flags != exp_new->node[i].flags) {
560 error_in_nodes = TRUE;
561 break;
562 }
563
564 /*
565 * allow some constants to be different; however it is important not to
566 * allow modification of sandboxing instructions. Note neither of the
567 * instructions allowed for modification is used for sandboxing
568 */
569 if (exp_old->node[i].value != exp_new->node[i].value) {
570 if (exp_old->node[i].kind == ExprConstant) {
571
572 /* allow different constants in direct calls */
573 if (istate_old->inst->name == InstCall)
574 if (exp_old->node[i].flags & NACL_EFLAG(ExprJumpTarget))
575 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
576 == OperandReference)
577 continue;
578
579 /*
580 * allow different constants in operand of mov
581 * e.g. mov $rax, 0xdeadbeef
582 */
583 if (istate_old->inst->name == InstMov)
584 if (exp_old->node[i].flags & NACL_EFLAG(ExprUsed))
585 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
586 == OperandReference)
587 continue;
588 /*
589 * allow different displacements in memory reference of mov
590 * instructions e.g. mov $rax, [$r15+$rbx*2+0x7fff]
591 */
592 if (istate_old->inst->name == InstMov)
593 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
594 == ExprMemOffset)
595 /* displacement is the fourth node after ExprMemOffset node */
596 if (i - NaClGetExpParentIndex(exp_old, i) == 4)
bsy 2010/12/15 04:06:50 magic number -- do we need/want a kDisplacementNod
elijahtaylor (use chromium) 2010/12/15 21:26:37 Not done. I consider the comment good enough to e
597 continue;
598 }
599 error_in_nodes = TRUE;
600 break;
601 }
602 }
603
604 if (error_in_nodes)
bsy 2010/12/15 04:06:50 good catch! NaClValidatorTwoInstMessage -> NaClRe
elijahtaylor (use chromium) 2010/12/15 21:26:37 Commented both locations (valid return and error r
605 break;
606
607 return;
608 } while (0);
609
610 NaClValidatorTwoInstMessage(LOG_ERROR, state, istate_old, istate_new,
611 "Code modification: failed to modify instruction");
612 }
613
614 void NaClValidateSegmentPair(uint8_t* mbase_old, uint8_t* mbase_new,
bsy 2010/12/15 04:06:50 a comment here about assumptions -- that vbase/siz
elijahtaylor (use chromium) 2010/12/15 21:26:37 Done. On 2010/12/15 04:06:50, bsy wrote:
615 NaClPcAddress vbase, size_t size,
616 struct NaClValidatorState* state) {
617 NaClSegment segment_old, segment_new;
618 NaClInstIter *iter_old, *iter_new;
619
620 NaClValidatorStateInitializeValidators(state);
621 NaClSegmentInitialize(mbase_old, vbase, size, &segment_old);
622 NaClSegmentInitialize(mbase_new, vbase, size, &segment_new);
623 iter_old = NaClInstIterCreateWithLookback(&segment_old, kLookbackSize);
624 iter_new = NaClInstIterCreateWithLookback(&segment_new, kLookbackSize);
625 while (NaClInstIterHasNext(iter_old) &&
626 NaClInstIterHasNext(iter_new)) {
627 state->cur_inst_state = NaClInstIterGetState(iter_new);
628 state->cur_inst = NaClInstStateInst(state->cur_inst_state);
629 state->cur_inst_vector = NaClInstStateExpVector(state->cur_inst_state);
630 NaClApplyValidators(state, iter_new);
631 NaClValidateInstReplacement(iter_old, iter_new, state);
632 if (state->quit) break;
633 NaClInstIterAdvance(iter_old);
634 NaClInstIterAdvance(iter_new);
635 }
636
637 if (NaClInstIterHasNext(iter_old) ||
638 NaClInstIterHasNext(iter_new)) {
639 NaClValidatorMessage(LOG_ERROR, state,
640 "Code modification: code segments have different number of instructions\n");
641 }
642
643 state->cur_inst_state = NULL;
644 state->cur_inst = NULL;
645 state->cur_inst_vector = NULL;
646 NaClApplyPostValidators(state, iter_new);
647 NaClInstIterDestroy(iter_old);
648 NaClInstIterDestroy(iter_new);
649 NaClValidatorStatePrintStats(state);
650 }
651
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698