Example #1
0
/* Given a jump statement, add the corresponding (explicit) jump value
 * to the set of actual jump targets.
 * Parameters:
 *   vstate - The state of the validator.
 */
static void NaClAddExprJumpTarget(NaClValidatorState* vstate) {
  uint32_t i;
  NaClInstState* inst_state = vstate->cur_inst_state;
  NaClExpVector* vector = vstate->cur_inst_vector;
  DEBUG(NaClLog(LOG_INFO, "jump checking: ");
        NaClInstStateInstPrint(NaClLogGetGio(), inst_state));
  for (i = 0; i < vector->number_expr_nodes; ++i) {
    NaClExp* node = &vector->node[i];
    if (!NaClHasBit(node->flags, NACL_EFLAG(ExprJumpTarget)))
      continue;
    switch (node->kind) {
      case ExprRegister:
        if (64 == NACL_TARGET_SUBARCH) {
          NaClAddRegisterJumpIndirect64(vstate, node);
        } else {
          NaClAddRegisterJumpIndirect32(vstate, node);
        }
        break;
      case ExprConstant:
        /* Direct jump. */
        NaClAddJumpToJumpSets(vstate, inst_state,
                              (NaClPcNumber) NaClGetExprSignedValue(node));
        break;
      default:
        NaClValidatorInstMessage(
            LOG_ERROR, vstate, inst_state,
            "Jump not native client compliant\n");
    }
  }
}
Example #2
0
/* Print out the given constant expression node to the given file. */
static void NaClPrintDisassembledConst(
    struct Gio* file, NaClInstState* state, NaClExp* node) {
  assert(node->kind == ExprConstant);
  if (node->flags & NACL_EFLAG(ExprJumpTarget)) {
    NaClPcAddress target = NaClInstStatePrintableAddress(state)
        + state->bytes.length + (NaClPcNumber) NaClGetExprSignedValue(node);
    gprintf(file, "0x%"NACL_PRIxNaClPcAddress, target);
  }else if (node->flags & NACL_EFLAG(ExprUnsignedHex)) {
    gprintf(file, "0x%"NACL_PRIx64, NaClGetExprUnsignedValue(node));
  } else if (node->flags & NACL_EFLAG(ExprSignedHex)) {
    int64_t val = NaClGetExprSignedValue(node);
    if (val < 0) {
      val = -val;
      gprintf(file, "-0x%"NACL_PRIx64, val);
    } else {
      gprintf(file, "0x%"NACL_PRIx64, val);
    }
  } else if (node->flags & NACL_EFLAG(ExprUnsignedInt)) {
    gprintf(file, "%"NACL_PRIu64, NaClGetExprUnsignedValue(node));
  } else {
    /* Assume ExprSignedInt. */
    gprintf(file, "%"NACL_PRId64, NaClGetExprSignedValue(node));
  }
}
Example #3
0
Bool NaClIsExpNegativeConstant(NaClExpVector* vector, int index) {
  NaClExp* node = &vector->node[index];
  switch (node->kind) {
    case ExprConstant:
      if (node->flags & NACL_EFLAG(ExprUnsignedHex) ||
          node->flags & NACL_EFLAG(ExprUnsignedInt)) {
        return FALSE;
      } else {
        /* Assume signed value. */
        return NaClGetExprSignedValue(node) < 0;
      }
      break;
    default:
      break;
  }
  return FALSE;
}
Example #4
0
/* Print out the given (memory offset) expression node to the given file.
 * Returns the index of the node following the given (indexed) memory offset.
 */
static int NaClPrintDisassembledMemOffset(struct Gio* file,
                                      NaClInstState *state,
                                      int index) {
  NaClExpVector* vector = NaClInstStateExpVector(state);
  int r1_index = index + 1;
  int r2_index = r1_index + NaClExpWidth(vector, r1_index);
  int scale_index = r2_index + NaClExpWidth(vector, r2_index);
  int disp_index = scale_index + NaClExpWidth(vector, scale_index);
  NaClOpKind r1 = NaClGetExpVectorRegister(vector, r1_index);
  NaClOpKind r2 = NaClGetExpVectorRegister(vector, r2_index);
  uint64_t scale = NaClGetExprUnsignedValue(&vector->node[scale_index]);
  int64_t disp = NaClGetExprSignedValue(&vector->node[disp_index]);
  assert(ExprMemOffset == vector->node[index].kind);
  gprintf(file,"[");
  if (r1 != RegUnknown) {
    NaClPrintDisassembledRegKind(file, r1);
  }
  if (r2 != RegUnknown) {
    if (r1 != RegUnknown) {
      gprintf(file, "+");
    }
    NaClPrintDisassembledRegKind(file, r2);
    gprintf(file, "*%d", (uint32_t) scale);
  }
  if (disp != 0) {
    if ((r1 != RegUnknown || r2 != RegUnknown) &&
        !NaClIsExpNegativeConstant(vector, disp_index)) {
      gprintf(file, "+");
    }
    /* Recurse to handle print using format flags. */
    NaClPrintDisassembledExp(file, state, disp_index);
  } else if (r1 == RegUnknown && r2 == RegUnknown) {
    /* be sure to generate case: [0x0]. */
    NaClPrintDisassembledExp(file, state, disp_index);
  }
  gprintf(file, "]");
  return disp_index + NaClExpWidth(vector, disp_index);
}
static void NaClInstLayoutCheck(NaClValidatorState* vstate) {
  NaClPcAddress start;
  NaClPcAddress end;
  NaClPcAddress i;
  if (NULL == vstate->cur_inst_state) return;

  DEBUG(NaClLog(LOG_INFO, "Jump layout check: ");
        NaClInstStateInstPrint(NaClLogGetGio(), vstate->cur_inst_state));

  /* Check basic block boundaries. */
  start = vstate->cur_inst_state->inst_addr;

  /* Check that if first instruction in a basic block, it isn't in the
   * middle of a pattern.
   */
  if ((0 == (start & vstate->bundle_mask)) &&
      NaClAddressSetContains(vstate->jump_sets.removed_targets,
                             start, vstate)) {
    NaClValidatorInstMessage(
        LOG_ERROR, vstate, vstate->cur_inst_state,
        "Instruction begins basic block, but in middle of nacl pattern\n");
  }

  /* Check that instruction doesn't cross block boundaries. */
  end = (NaClPcAddress) (start + vstate->cur_inst_state->bytes.length);
  for (i = start + 1; i < end; ++i) {
    if (0 == (i & vstate->bundle_mask)) {
      NaClValidatorInstMessage(
          LOG_ERROR, vstate, vstate->cur_inst_state,
          "Instruction crosses basic block alignment\n");
    }
  }

  /* Check jump targets. */
  if (NaClHasBit(vstate->cur_inst_state->inst->flags,
                 NACL_IFLAG(JumpInstruction) | NACL_IFLAG(ConditionalJump))) {
    uint32_t i;
    NaClExpVector* vector = NaClInstStateExpVector(vstate->cur_inst_state);
    for (i = 0; i < vector->number_expr_nodes; ++i) {
      NaClExp* node = &vector->node[i];
      if (NaClHasBit(node->flags, NACL_EFLAG(ExprJumpTarget))
          && node->kind == ExprConstant) {
        /* Explicit jump value. Check if legal! */
        NaClPcAddress target = end +
            (NaClPcNumber) NaClGetExprSignedValue(node);
        /* Don't report targets that are out of range. They should have
         * been reported in the first pass!
         */
        if (NaClCheckAddressRange(target, vstate)) {
          if (NaClAddressSetContains(vstate->jump_sets.possible_targets,
                                     target, vstate)) {
            if (NaClAddressSetContains(vstate->jump_sets.removed_targets,
                                       target, vstate)) {
              NaClValidatorInstMessage(
                  LOG_ERROR, vstate, vstate->cur_inst_state,
                  "Jumps into middle of nacl pattern\n");
            }
          } else {
            NaClValidatorInstMessage(
                LOG_ERROR, vstate, vstate->cur_inst_state,
                "Doesn't jump to instruction address\n");
          }
        }
      }
    }
  }
}