/* Record that the given address of the given instruction is the beginning of * a disassembled instruction. * Parameters: * vstate - The state of the validator. * inst - The instruction. */ static void NaClRememberInstructionBoundary(NaClValidatorState* vstate, NaClInstState* inst) { if (!NaClInstructionInCodeSegment(vstate, inst)) { NaClValidatorInstMessage(LOG_ERROR, vstate, inst, "Instruction pc out of range\n"); } else { DEBUG(NaClLog(LOG_INFO, "Add possible jump address: %"NACL_PRIxNaClPcAddress"\n", inst->inst_addr)); NaClAddressSetAddInline(vstate->jump_sets.possible_targets, inst->inst_addr, vstate); } }
static INLINE void NaClMarkInstructionJumpIllegalInline( struct NaClValidatorState* vstate, struct NaClInstState* inst) { if (!NaClInstructionInCodeSegment(vstate, inst)) { /* ERROR instruction out of range. * Note: Not reported here, because this will already be reported by * the call to NaClRememberIp in JumpValidator. */ } else { DEBUG(NaClLog(LOG_INFO, "Mark instruction as jump illegal: %"NACL_PRIxNaClPcAddress "\n", inst->inst_addr)); NaClAddressSetAddInline(vstate->jump_sets.removed_targets, inst->inst_addr, vstate); } }
/* Record that there is an explicit jump from the from_address to the * to_address, for the validation defined by the validator state. * Parameters: * vstate - The state of the validator. * inst - The instruction that does the jump. * jump_offset - The jump offset, relative to the end of the instruction. */ static void NaClAddJumpToJumpSets(NaClValidatorState* vstate, NaClInstState* inst, NaClPcNumber jump_offset) { NaClPcAddress to_address = inst->inst_addr + inst->bytes.length + jump_offset; /* If the address is in the code segment, assume good (unless we later find it * jumping into a pseudo instruction). Otherwise, only allow if 0 mod 32. */ DEBUG(NaClLog(LOG_INFO, "Add jump to jump sets: %" NACL_PRIxNaClPcAddress" -> %"NACL_PRIxNaClPcAddress"\n", inst->inst_addr, to_address)); if (to_address < vstate->codesize) { /* Remember address for checking later. */ DEBUG(NaClLog(LOG_INFO, "Add jump to target: %"NACL_PRIxNaClPcAddress " -> %"NACL_PRIxNaClPcAddress"\n", inst->inst_addr, to_address)); NaClAddressSetAddInline(vstate->jump_sets.actual_targets, to_address, vstate); } else if ((to_address & vstate->bundle_mask) == 0) { /* Allow bundle-aligned jump. If the jump overflows or underflows the * 4GB untrusted address space it will hit the guard regions. The largest * potential jump offset is +/-2GB. We could allow direct jumps only within * the 4GB untrusted address space, but there is no need for this * restriction and it would make validation judgements position-dependent. */ } else if (inst->unchanged) { /* If we are replacing this instruction during dynamic code modification * and it has not changed, the jump target must be valid because the * instruction has been previously validated. However, we may be only * replacing a subsection of the code segment and therefore may not have * information about instruction boundaries outside of the code being * replaced. Therefore, we allow unaligned direct jumps outside of the code * being validated if and only if the instruction is unchanged. * If dynamic code replacement is not being performed, inst->unchanged * should always be false. */ } else { if (!NACL_FLAGS_unsafe_single_inst_mode) { NaClValidatorInstMessage(LOG_ERROR, vstate, inst, "Instruction jumps to bad address\n"); } } }
void NaClAddressSetAdd(NaClAddressSet set, NaClPcAddress address, NaClValidatorState* state) { NaClAddressSetAddInline(set, address, state); }