/* Checks if an indirect jump (in 64-bit mode) is native client compliant. * * Expects pattern: * * and %REG32, MASK * add %REG64, %RBASE * jmp %REG64 * * where MASK is all 1/s except for the alignment mask bits, which must be zero. * * REG32 is the corresponding 32-bit register that whose value will get zero * extended by the AND operation into the corresponding 64-bit register REG64. * * It is assumed that opcode 0x83 is used for the AND operation, and hence, the * mask is a single byte. * * Note: applies to all kinds of jumps and calls. * * Parameters: * vstate - The state of the validator. * reg - The register used in the jump instruction. */ static void NaClAddRegisterJumpIndirect64(NaClValidatorState* vstate, NaClExp* reg) { NaClOpKind jump_reg, and_reg32, and_reg64; /* Do the following block exactly once. Use loop so that "break" can * be used for premature exit of block. */ do { /* Check that jump register is 64-bit. */ if (!NaClHasBit(reg->flags, NACL_EFLAG(ExprSize64))) break; jump_reg = NaClGetExpRegisterInline(reg); if (RegUnknown == jump_reg) break; DEBUG(NaClLog(LOG_INFO, "checking indirect jump: "); NaClInstStateInstPrint(NaClLogGetGio(), vstate->cur_inst_state); gprintf(NaClLogGetGio(), "jump_reg = %s\n", NaClOpKindName(jump_reg))); /* Check that sequence begins with an appropriate and instruction. */ and_reg32 = NaClGetAndMaskReg32(vstate, 2); if (RegUnknown == and_reg32) break; /* Get corresponding 64-bit register for 32-bit result of 'and', * and make sure it matches the jump register. */ and_reg64 = NaClGet64For32BitReg(and_reg32); if (and_reg64 != jump_reg) break; /* Check that the middle instruction is an appropriate add instruction. */ if (!NaClIsAddRbaseToReg64(vstate, 1, and_reg64)) break; /* If reached, indirect jump is properly masked. */ DEBUG(NaClLog(LOG_INFO, "Protect indirect jump instructions\n")); NaClMarkInstructionJumpIllegal( vstate, NaClInstIterGetLookbackStateInline(vstate->cur_iter, 1)); NaClMarkInstructionJumpIllegal(vstate, vstate->cur_inst_state); return; } while(0); /* If reached, mask was not found. */ NaClValidatorInstMessage(LOG_ERROR, vstate, vstate->cur_inst_state, "Invalid indirect jump\n"); }
Bool NaClIs32To64RegPair(NaClOpKind reg32, NaClOpKind reg64) { return reg64 == NaClGet64For32BitReg(reg32); }