Example #1
0
/* 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");
}
Example #2
0
Bool NaClIs32To64RegPair(NaClOpKind reg32, NaClOpKind reg64) {
  return reg64 == NaClGet64For32BitReg(reg32);
}