| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 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 /* nc_protect_base.h - For 64-bit mode, verifies that no instruction | 7 /* nc_protect_base.h - For 64-bit mode, verifies that no instruction |
| 8 * changes the value of the base register, that the invariant between | 8 * changes the value of the base register, that the invariant between |
| 9 * RSP and RBP is maintained, and that segment registers are not set. | 9 * RSP and RBP is maintained, and that segment registers are not set. |
| 10 */ | 10 */ |
| 11 #include <assert.h> | 11 #include <assert.h> |
| 12 | 12 |
| 13 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_protect_base.
h" | 13 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_protect_base.
h" |
| 14 | 14 |
| 15 #include "native_client/src/shared/platform/nacl_log.h" | 15 #include "native_client/src/shared/platform/nacl_log.h" |
| 16 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" | |
| 17 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" | |
| 18 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | 16 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" |
| 19 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h" | 17 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h" |
| 20 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.
h" | 18 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.
h" |
| 21 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_
internal.h" | 19 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_
internal.h" |
| 22 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_utils
.h" | 20 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_utils
.h" |
| 23 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h" | 21 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h" |
| 24 | 22 |
| 25 /* To turn on debugging of instruction decoding, change value of | 23 /* To turn on debugging of instruction decoding, change value of |
| 26 * DEBUGGING to 1. | 24 * DEBUGGING to 1. |
| 27 */ | 25 */ |
| 28 #define DEBUGGING 0 | 26 #define DEBUGGING 0 |
| 29 | 27 |
| 30 #include "native_client/src/shared/utils/debugging.h" | 28 #include "native_client/src/shared/utils/debugging.h" |
| 31 | 29 |
| 30 #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c" |
| 31 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c" |
| 32 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter_inl.c" |
| 33 |
| 32 /* Defines locals used by the NaClBaseRegisterValidator to | 34 /* Defines locals used by the NaClBaseRegisterValidator to |
| 33 * record registers set in the current instruction, that are | 35 * record registers set in the current instruction, that are |
| 34 * a problem if not used correctly in the next instruction. | 36 * a problem if not used correctly in the next instruction. |
| 35 */ | 37 */ |
| 36 typedef struct NaClRegisterLocals { | 38 typedef struct NaClRegisterLocals { |
| 37 /* Points to an instruction that contains an assignment to register ESP, | 39 /* Points to an instruction that contains an assignment to register ESP, |
| 38 * or NULL if the instruction doesn't set ESP. This is done so that we | 40 * or NULL if the instruction doesn't set ESP. This is done so that we |
| 39 * can check if the next instruction uses the value of ESP to update RSP | 41 * can check if the next instruction uses the value of ESP to update RSP |
| 40 * (if not, we need to report that ESP is incorrectly assigned). | 42 * (if not, we need to report that ESP is incorrectly assigned). |
| 41 */ | 43 */ |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 } | 136 } |
| 135 | 137 |
| 136 /* Returns true if the instruction is of the form | 138 /* Returns true if the instruction is of the form |
| 137 * OP %esp, C | 139 * OP %esp, C |
| 138 * where OP in { add , sub } and C is a 32 bit constant. | 140 * where OP in { add , sub } and C is a 32 bit constant. |
| 139 */ | 141 */ |
| 140 static Bool NaClIsAddOrSubBoundedConstFromEsp(NaClInstState* state) { | 142 static Bool NaClIsAddOrSubBoundedConstFromEsp(NaClInstState* state) { |
| 141 const NaClInst* inst = NaClInstStateInst(state); | 143 const NaClInst* inst = NaClInstStateInst(state); |
| 142 NaClExpVector* vector = NaClInstStateExpVector(state); | 144 NaClExpVector* vector = NaClInstStateExpVector(state); |
| 143 return (InstAdd == inst->name || InstSub == inst->name) && | 145 return (InstAdd == inst->name || InstSub == inst->name) && |
| 144 2 == NaClGetInstNumberOperands(inst) && | 146 2 == NaClGetInstNumberOperandsInline(inst) && |
| 145 /* Note: Since the vector contains a list of operand expressions, the | 147 /* Note: Since the vector contains a list of operand expressions, the |
| 146 * first operand reference is always at index zero, and its first child | 148 * first operand reference is always at index zero, and its first child |
| 147 * (where the register would be defined) is at index 1. | 149 * (where the register would be defined) is at index 1. |
| 148 */ | 150 */ |
| 149 ExprRegister == vector->node[1].kind && | 151 ExprRegister == vector->node[1].kind && |
| 150 RegESP == NaClGetExpRegister(&vector->node[1]) && | 152 RegESP == NaClGetExpRegisterInline(&vector->node[1]) && |
| 151 /* Note: Since the first subtree is a register operand, it uses | 153 /* Note: Since the first subtree is a register operand, it uses |
| 152 * nodes 0 and 1 in the vector (node 0 is the operand reference, and | 154 * nodes 0 and 1 in the vector (node 0 is the operand reference, and |
| 153 * node 1 is its child defining a register value). The second operand | 155 * node 1 is its child defining a register value). The second operand |
| 154 * reference therefore lies at node 2, and if the operand is defined by | 156 * reference therefore lies at node 2, and if the operand is defined by |
| 155 * a 32 bit constant, it is the first kid of node 2, which is node 3. | 157 * a 32 bit constant, it is the first kid of node 2, which is node 3. |
| 156 */ | 158 */ |
| 157 ExprConstant == vector->node[3].kind; | 159 ExprConstant == vector->node[3].kind; |
| 158 } | 160 } |
| 159 | 161 |
| 160 /* Returns true iff the instruction of form "lea _, [%reg+%rbase*1]" */ | 162 /* Returns true iff the instruction of form "lea _, [%reg+%rbase*1]" */ |
| 161 static Bool NaClIsLeaAddressRegPlusRbase(NaClValidatorState* state, | 163 static Bool NaClIsLeaAddressRegPlusRbase(NaClValidatorState* state, |
| 162 NaClInstState* inst_state, | 164 NaClInstState* inst_state, |
| 163 NaClOpKind reg) { | 165 NaClOpKind reg) { |
| 164 const NaClInst* inst = NaClInstStateInst(inst_state); | 166 const NaClInst* inst = NaClInstStateInst(inst_state); |
| 165 assert((RegRSP == reg) || (RegRBP == reg)); | 167 assert((RegRSP == reg) || (RegRBP == reg)); |
| 166 if (InstLea == inst->name && | 168 if (InstLea == inst->name && |
| 167 2 == NaClGetInstNumberOperands(inst)) { | 169 2 == NaClGetInstNumberOperandsInline(inst)) { |
| 168 NaClExpVector* vector = NaClInstStateExpVector(inst_state); | 170 NaClExpVector* vector = NaClInstStateExpVector(inst_state); |
| 169 int op2_index = | 171 int op2_index = |
| 170 NaClGetExpKidIndex(vector, | 172 NaClGetExpKidIndex(vector, |
| 171 NaClGetNthExpKind(vector, OperandReference, 2), | 173 NaClGetNthExpKind(vector, OperandReference, 2), |
| 172 0); | 174 0); |
| 173 NaClExp* op2 = &(vector->node[op2_index]); | 175 NaClExp* op2 = &(vector->node[op2_index]); |
| 174 /* Only allow memory offset nodes with address size 64. */ | 176 /* Only allow memory offset nodes with address size 64. */ |
| 175 if (ExprMemOffset == op2->kind && | 177 if (ExprMemOffset == op2->kind && |
| 176 NACL_EMPTY_EFLAGS != (op2->flags & NACL_EFLAG(ExprSize64))) { | 178 NACL_EMPTY_EFLAGS != (op2->flags & NACL_EFLAG(ExprSize64))) { |
| 177 int base_reg_index = op2_index + 1; | 179 int base_reg_index = op2_index + 1; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 208 * the corresponding 32-bit retister. | 210 * the corresponding 32-bit retister. |
| 209 */ | 211 */ |
| 210 | 212 |
| 211 static Bool NaClAcceptRegMoveLea32To64(struct NaClValidatorState* state, | 213 static Bool NaClAcceptRegMoveLea32To64(struct NaClValidatorState* state, |
| 212 struct NaClInstIter* iter, | 214 struct NaClInstIter* iter, |
| 213 const NaClInst* inst, | 215 const NaClInst* inst, |
| 214 NaClOpKind reg) { | 216 NaClOpKind reg) { |
| 215 NaClInstState* inst_state = state->cur_inst_state; | 217 NaClInstState* inst_state = state->cur_inst_state; |
| 216 assert((RegRSP == reg) || (RegRBP == reg)); | 218 assert((RegRSP == reg) || (RegRBP == reg)); |
| 217 if (NaClOperandOneIsRegisterSet(inst_state, reg) && | 219 if (NaClOperandOneIsRegisterSet(inst_state, reg) && |
| 218 NaClInstIterHasLookbackState(iter, 1)) { | 220 NaClInstIterHasLookbackStateInline(iter, 1)) { |
| 219 NaClInstState* prev_inst = NaClInstIterGetLookbackState(iter, 1); | 221 NaClInstState* prev_inst = NaClInstIterGetLookbackStateInline(iter, 1); |
| 220 if (NaClAssignsRegisterWithZeroExtends( | 222 if (NaClAssignsRegisterWithZeroExtends( |
| 221 prev_inst, NaClGet32For64BitReg(reg)) && | 223 prev_inst, NaClGet32For64BitReg(reg)) && |
| 222 NaClIsLeaAddressRegPlusRbase(state, inst_state, reg)) { | 224 NaClIsLeaAddressRegPlusRbase(state, inst_state, reg)) { |
| 223 DEBUG(const char* reg_name = NaClOpKindName(reg); | 225 DEBUG(const char* reg_name = NaClOpKindName(reg); |
| 224 printf("nc protect base for 'lea %s. [%s, rbase]'\n", | 226 printf("nc protect base for 'lea %s. [%s, rbase]'\n", |
| 225 reg_name, reg_name)); | 227 reg_name, reg_name)); |
| 226 NaClMarkInstructionJumpIllegal(state, inst_state); | 228 NaClMarkInstructionJumpIllegal(state, inst_state); |
| 227 return TRUE; | 229 return TRUE; |
| 228 } | 230 } |
| 229 } | 231 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 if (i == 3) return; | 318 if (i == 3) return; |
| 317 break; | 319 break; |
| 318 case InstOr: | 320 case InstOr: |
| 319 case InstAdd: | 321 case InstAdd: |
| 320 { | 322 { |
| 321 /* case 2/4 (depending on instruction name). */ | 323 /* case 2/4 (depending on instruction name). */ |
| 322 if (NaClIsBinarySetUsingRegisters( | 324 if (NaClIsBinarySetUsingRegisters( |
| 323 state->decoder_tables, | 325 state->decoder_tables, |
| 324 inst, inst_name, vector, RegRSP, | 326 inst, inst_name, vector, RegRSP, |
| 325 state->base_register) && | 327 state->base_register) && |
| 326 NaClInstIterHasLookbackState(iter, 1)) { | 328 NaClInstIterHasLookbackStateInline(iter, 1)) { |
| 327 NaClInstState* prev_inst = | 329 NaClInstState* prev_inst = |
| 328 NaClInstIterGetLookbackState(iter, 1); | 330 NaClInstIterGetLookbackStateInline(iter, 1); |
| 329 if (NaClAssignsRegisterWithZeroExtends(prev_inst, RegESP) | 331 if (NaClAssignsRegisterWithZeroExtends(prev_inst, RegESP) |
| 330 || (inst_name == InstAdd && | 332 || (inst_name == InstAdd && |
| 331 NaClIsAddOrSubBoundedConstFromEsp(prev_inst))) { | 333 NaClIsAddOrSubBoundedConstFromEsp(prev_inst))) { |
| 332 /* Found that the assignment to ESP in previous instruction | 334 /* Found that the assignment to ESP in previous instruction |
| 333 * is legal, so long as the two instructions are atomic. | 335 * is legal, so long as the two instructions are atomic. |
| 334 */ | 336 */ |
| 335 DEBUG(printf("nc protect esp for zero extend, or or/add " | 337 DEBUG(printf("nc protect esp for zero extend, or or/add " |
| 336 "constant\n")); | 338 "constant\n")); |
| 337 NaClMarkInstructionJumpIllegal(state, inst_state); | 339 NaClMarkInstructionJumpIllegal(state, inst_state); |
| 338 locals->buffer[locals->previous_index].esp_set_inst = NULL; | 340 locals->buffer[locals->previous_index].esp_set_inst = NULL; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 * | 416 * |
| 415 * Note: We require the scale to be 1, and rbase be in | 417 * Note: We require the scale to be 1, and rbase be in |
| 416 * the index position. | 418 * the index position. |
| 417 */ | 419 */ |
| 418 NaClInstState* inst_state = state->cur_inst_state; | 420 NaClInstState* inst_state = state->cur_inst_state; |
| 419 const NaClInst* inst = state->cur_inst; | 421 const NaClInst* inst = state->cur_inst; |
| 420 NaClMnemonic inst_name = inst->name; | 422 NaClMnemonic inst_name = inst->name; |
| 421 NaClExpVector* vector = state->cur_inst_vector; | 423 NaClExpVector* vector = state->cur_inst_vector; |
| 422 switch (inst_name) { | 424 switch (inst_name) { |
| 423 case InstAdd: | 425 case InstAdd: |
| 424 if (NaClInstIterHasLookbackState(iter, 1)) { | 426 if (NaClInstIterHasLookbackStateInline(iter, 1)) { |
| 425 NaClInstState* prev_state = | 427 NaClInstState* prev_state = |
| 426 NaClInstIterGetLookbackState(iter, 1); | 428 NaClInstIterGetLookbackStateInline(iter, 1); |
| 427 if (NaClIsBinarySetUsingRegisters( | 429 if (NaClIsBinarySetUsingRegisters( |
| 428 state->decoder_tables, | 430 state->decoder_tables, |
| 429 inst, InstAdd, vector, | 431 inst, InstAdd, vector, |
| 430 RegRBP, state->base_register) && | 432 RegRBP, state->base_register) && |
| 431 NaClAssignsRegisterWithZeroExtends( | 433 NaClAssignsRegisterWithZeroExtends( |
| 432 prev_state, RegEBP)) { | 434 prev_state, RegEBP)) { |
| 433 /* case 2. */ | 435 /* case 2. */ |
| 434 NaClMarkInstructionJumpIllegal(state, inst_state); | 436 NaClMarkInstructionJumpIllegal(state, inst_state); |
| 435 locals->buffer[locals->previous_index].ebp_set_inst = NULL; | 437 locals->buffer[locals->previous_index].ebp_set_inst = NULL; |
| 436 return; | 438 return; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 NaClExpVector* vector = state->cur_inst_vector; | 495 NaClExpVector* vector = state->cur_inst_vector; |
| 494 | 496 |
| 495 DEBUG(NaClValidatorInstMessage( | 497 DEBUG(NaClValidatorInstMessage( |
| 496 LOG_INFO, state, inst_state, "Checking base registers...\n")); | 498 LOG_INFO, state, inst_state, "Checking base registers...\n")); |
| 497 | 499 |
| 498 /* Look for assignments to registers. */ | 500 /* Look for assignments to registers. */ |
| 499 for (i = 0; i < vector->number_expr_nodes; ++i) { | 501 for (i = 0; i < vector->number_expr_nodes; ++i) { |
| 500 NaClExp* node = &vector->node[i]; | 502 NaClExp* node = &vector->node[i]; |
| 501 if (ExprRegister == node->kind) { | 503 if (ExprRegister == node->kind) { |
| 502 if (node->flags & NACL_EFLAG(ExprSet)) { | 504 if (node->flags & NACL_EFLAG(ExprSet)) { |
| 503 NaClOpKind reg_name = NaClGetExpRegister(node); | 505 NaClOpKind reg_name = NaClGetExpRegisterInline(node); |
| 504 | 506 |
| 505 /* If reached, found an assignment to a register. | 507 /* If reached, found an assignment to a register. |
| 506 * Check if its one that we care about (i.e. | 508 * Check if its one that we care about (i.e. |
| 507 * the base register (RBASE), RSP, RBP, or segment register). | 509 * the base register (RBASE), RSP, RBP, or segment register). |
| 508 */ | 510 */ |
| 509 if (reg_name == state->base_register) { | 511 if (reg_name == state->base_register) { |
| 510 NaClValidatorInstMessage( | 512 NaClValidatorInstMessage( |
| 511 LOG_ERROR, state, inst_state, | 513 LOG_ERROR, state, inst_state, |
| 512 "Illegal to change the value of register %s\n", | 514 "Illegal to change the value of register %s\n", |
| 513 NaClOpKindName(state->base_register)); | 515 NaClOpKindName(state->base_register)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 */ | 557 */ |
| 556 NaClMaybeReportPreviousBad(state, locals); | 558 NaClMaybeReportPreviousBad(state, locals); |
| 557 } | 559 } |
| 558 | 560 |
| 559 void NaClBaseRegisterSummarize(struct NaClValidatorState* state, | 561 void NaClBaseRegisterSummarize(struct NaClValidatorState* state, |
| 560 struct NaClInstIter* iter, | 562 struct NaClInstIter* iter, |
| 561 struct NaClBaseRegisterLocals* locals) { | 563 struct NaClBaseRegisterLocals* locals) { |
| 562 /* Check if problems in last instruction of segment. */ | 564 /* Check if problems in last instruction of segment. */ |
| 563 NaClMaybeReportPreviousBad(state, locals); | 565 NaClMaybeReportPreviousBad(state, locals); |
| 564 } | 566 } |
| OLD | NEW |