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

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 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 NaClValidatorState* state, 234 NaClValidatorState* state,
235 NaClInstState* inst, 235 NaClInstState* inst,
236 const char* format, 236 const char* format,
237 ...) { 237 ...) {
238 level = NaClRecordIfValidatorError(state, level); 238 level = NaClRecordIfValidatorError(state, level);
239 if (NaClPrintValidatorMessages(state, level)) { 239 if (NaClPrintValidatorMessages(state, level)) {
240 va_list ap; 240 va_list ap;
241 struct Gio* g = NaClLogGetGio(); 241 struct Gio* g = NaClLogGetGio();
242 242
243 NaClLogLock(); 243 NaClLogLock();
244 /* TODO(karl): empty fmt strings not allowed */ 244 /* TODO(karl): empty fmt strings not allowed */
bsy 2010/11/11 21:27:21 is this TODO still valid, given the check below?
petr 2010/11/12 18:11:06 I rolled back the check below, so it is valid On
245 NaClLog_mu(level, "VALIDATOR: %s", ""); 245 NaClLog_mu(level, "VALIDATOR: %s", "");
246 /* TODO(karl) - Make printing of instruction state possible via format. */ 246 /* TODO(karl) - Make printing of instruction state possible via format. */
247 NaClInstStateInstPrint(g, inst); 247 NaClInstStateInstPrint(g, inst);
248 248
249 va_start(ap, format); 249 if (format != NULL) {
bsy 2010/11/11 21:27:21 when do we get NULL format strings? this sounds l
petr 2010/11/12 18:11:06 I use this to print two instructions in a row, see
250 NaClLog_mu(level, "VALIDATOR: %s", NaClLogLevelLabel(level)); 250 va_start(ap, format);
251 NaClLogV_mu(level, format, ap); 251 NaClLog_mu(level, "VALIDATOR: %s", NaClLogLevelLabel(level));
252 va_end(ap); 252 NaClLogV_mu(level, format, ap);
253 va_end(ap);
254 }
253 NaClLogUnlock(); 255 NaClLogUnlock();
254 NaClRecordErrorReported(state, level); 256 NaClRecordErrorReported(state, level);
255 } 257 }
256 if (state->do_stub_out && (level <= LOG_ERROR)) { 258 if (state->do_stub_out && (level <= LOG_ERROR)) {
257 memset(inst->mpc, kNaClFullStop, inst->length); 259 memset(inst->mpc, kNaClFullStop, inst->length);
258 } 260 }
259 } 261 }
260 262
261 Bool NaClValidatorQuit(NaClValidatorState* state) { 263 Bool NaClValidatorQuit(NaClValidatorState* state) {
262 return !state->validates_ok && (state->quit_after_error_count == 0); 264 return !state->validates_ok && (state->quit_after_error_count == 0);
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 void* NaClGetValidatorLocalMemory(NaClValidator validator, 444 void* NaClGetValidatorLocalMemory(NaClValidator validator,
443 const NaClValidatorState* state) { 445 const NaClValidatorState* state) {
444 int i; 446 int i;
445 for (i = 0; i < state->number_validators; ++i) { 447 for (i = 0; i < state->number_validators; ++i) {
446 if (state->validators[i].validator == validator) { 448 if (state->validators[i].validator == validator) {
447 return state->local_memory[i]; 449 return state->local_memory[i];
448 } 450 }
449 } 451 }
450 return NULL; 452 return NULL;
451 } 453 }
454
455 /*
456 * Check that iter_new is a valid replacement for iter_old.
457 * If a validation error occurs, state->validates_ok will be set to false by
458 * NaClValidatorInstMessage when it is given LOG_ERROR, see the end of this
459 * function.
460 */
461 static void NaClValidateInstReplacement(NaClInstIter* iter_old,
462 NaClInstIter* iter_new,
463 struct NaClValidatorState* state) {
464 NaClInstState *istate_old, *istate_new;
465 NaClExpVector *exp_old, *exp_new;
466 uint32_t i;
467
468 istate_old = NaClInstIterGetState(iter_old);
469 istate_new = NaClInstIterGetState(iter_new);
470
471 /* Location/length must match */
472 if (istate_new->vpc != istate_old->vpc ||
473 istate_new->length != istate_old->length) {
474 NaClValidatorMessage(LOG_ERROR, state,
475 "Code modification: instructions length/addresses do not match\n");
476 NaClValidatorInstMessage(LOG_ERROR, state, istate_old, NULL);
477 NaClValidatorInstMessage(LOG_ERROR, state, istate_new, NULL);
478 return;
479 }
480
481
482 do {
483 /* fast check if the replacement is identical */
484 if (!memcmp(istate_old->mpc, istate_new->mpc, istate_old->length))
485 return;
486
487 if (istate_old->num_prefix_bytes != istate_new->num_prefix_bytes)
488 break;
489 if (istate_old->num_rex_prefixes != istate_new->num_rex_prefixes)
490 break;
491 if (istate_old->rexprefix != istate_new->rexprefix)
492 break;
493 if (istate_old->modrm != istate_new->modrm)
494 break;
495 if (istate_old->has_sib != istate_new->has_sib)
496 break;
497 if (istate_old->has_sib && istate_old->sib != istate_new->sib)
498 break;
499 if (istate_old->operand_size != istate_new->operand_size)
500 break;
501 if (istate_old->address_size != istate_new->address_size)
502 break;
503 if (istate_old->prefix_mask != istate_new->prefix_mask)
504 break;
505
506 /*
507 * these are pointers, but they reference entries in a static table,
508 * so if the two instructions are the same, then these pointers must
509 * reference the same entry
510 */
511 if (istate_old->inst != istate_new->inst)
512 break;
513
514 exp_old = NaClInstStateExpVector(istate_old);
515 exp_new = NaClInstStateExpVector(istate_new);
516
517 /* check if the instruction operands are identical */
518 if (exp_old->number_expr_nodes != exp_new->number_expr_nodes)
519 break;
520
521 for (i = 0; i < exp_old->number_expr_nodes; i++) {
522 if (exp_old->node[i].kind != exp_new->node[i].kind)
523 break;
524 if (exp_old->node[i].flags != exp_new->node[i].flags)
525 break;
526
527 /*
528 * allow some constants to be different; however it is important not to
529 * allow modification of sandboxing instructions. Note nether of the
530 * instructions allowed for modification is used for sandboxing
531 */
532 if (exp_old->node[i].value != exp_new->node[i].value) {
533 if (exp_old->node[i].kind == ExprConstant) {
534
535 /* allow different constants in direct calls */
536 if (istate_old->inst->name == InstCall)
537 if (exp_old->node[i].flags & NACL_EFLAG(ExprJumpTarget))
538 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
539 == OperandReference)
540 continue;
541
542 /*
543 * allow different constants in operand of mov
544 * e.g. mov $rax, 0xdeadbeef
545 */
546 if (istate_old->inst->name == InstMov)
547 if (exp_old->node[i].flags & NACL_EFLAG(ExprUsed))
548 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
549 == OperandReference)
550 continue;
551 /*
552 * allow different displacements in memory reference of mov
553 * instructions e.g. mov $rax, [$r15+$rbx*2+0x7fff]
554 */
555 if (istate_old->inst->name == InstMov)
556 if (exp_old->node[NaClGetExpParentIndex(exp_old, i)].kind
557 == ExprMemOffset)
558 /* displacement is the fourth node after ExprMemOffset node */
559 if (i - NaClGetExpParentIndex(exp_old, i) == 4)
560 continue;
561 }
562 break;
563 }
564 }
565
566 return;
567 } while (0);
568
569 NaClValidatorMessage(LOG_ERROR, state,
570 "Code modification: failed to modify instructions\n");
571 NaClValidatorInstMessage(LOG_ERROR, state, istate_old, NULL);
bsy 2010/11/11 21:27:21 are these two lines the only places where the form
Karl 2010/11/11 22:45:41 I think that you may just want to add a new "messa
petr 2010/11/12 18:11:06 Yes, they are On 2010/11/11 21:27:21, bsy wrote:
petr 2010/11/12 18:11:06 Yes, I will do this On 2010/11/11 22:45:41, Karl
572 NaClValidatorInstMessage(LOG_ERROR, state, istate_new, NULL);
573 }
574
575 void NaClValidateSegmentPair(uint8_t* mbase_old, uint8_t* mbase_new,
576 NaClPcAddress vbase, size_t size,
577 struct NaClValidatorState* state) {
578 NaClSegment segment_old, segment_new;
579 NaClInstIter *iter_old, *iter_new;
580
581 NaClValidatorStateInitializeValidators(state);
582 NaClSegmentInitialize(mbase_old, vbase, size, &segment_old);
583 NaClSegmentInitialize(mbase_new, vbase, size, &segment_new);
584 iter_old = NaClInstIterCreateWithLookback(&segment_old, kLookbackSize);
585 iter_new = NaClInstIterCreateWithLookback(&segment_new, kLookbackSize);
586 while (NaClInstIterHasNext(iter_old) &&
587 NaClInstIterHasNext(iter_new)) {
588 state->cur_inst_state = NaClInstIterGetState(iter_new);
589 state->cur_inst = NaClInstStateInst(state->cur_inst_state);
590 state->cur_inst_vector = NaClInstStateExpVector(state->cur_inst_state);
591 NaClApplyValidators(state, iter_new);
592 NaClValidateInstReplacement(iter_old, iter_new, state);
593 if (state->quit) break;
594 NaClInstIterAdvance(iter_old);
595 NaClInstIterAdvance(iter_new);
596 }
597
598 if (NaClInstIterHasNext(iter_old) ||
599 NaClInstIterHasNext(iter_new)) {
600 NaClValidatorMessage(LOG_ERROR, state,
601 "Code modification: code segments have different number of instructions\n");
602 }
603
604 state->cur_inst_state = NULL;
605 state->cur_inst = NULL;
606 state->cur_inst_vector = NULL;
607 NaClApplyPostValidators(state, iter_new);
608 NaClInstIterDestroy(iter_old);
609 NaClInstIterDestroy(iter_new);
610 NaClValidatorStatePrintStats(state);
611 }
612
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698