Index: src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.c |
diff --git a/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.c b/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.c |
deleted file mode 100644 |
index d3a800e0172e14e0a3004746e574cb5139c8fc77..0000000000000000000000000000000000000000 |
--- a/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.c |
+++ /dev/null |
@@ -1,449 +0,0 @@ |
-/* |
- * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
- * Use of this source code is governed by a BSD-style license that can be |
- * found in the LICENSE file. |
- */ |
- |
-/* Validator to check that instructions are in the legal subset. */ |
- |
-#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.h" |
- |
-#include "native_client/src/shared/platform/nacl_log.h" |
-#include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" |
-#include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" |
-#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h" |
-#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h" |
-#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.h" |
-#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_internal.h" |
-#include "native_client/src/trusted/validator/x86/decoder/generator/gen/nacl_disallows.h" |
- |
-/* To turn on debugging of instruction decoding, change value of |
- * DEBUGGING to 1. |
- */ |
-#define DEBUGGING 0 |
- |
-#include "native_client/src/shared/utils/debugging.h" |
- |
-/* Message to use if we don't have a more precise reason why the instruction |
- * is illegal. |
- */ |
-static const char* kNaClGenericReasonDisallowed = |
- "Illegal native client instruction"; |
- |
-/* This function returns a printable description of the reason an instruction |
- * is disallowed, or NULL if the reason is not understood. |
- */ |
-static const char* NaClReasonWhyDisallowed(NaClDisallowsFlag flag) { |
- switch (flag) { |
- case NaClTooManyPrefixBytes: |
- return "More than one (non-REX) prefix byte specified"; |
- case NaClMarkedIllegal: |
- return "This instruction has been marked illegal by Native Client"; |
- case NaClMarkedInvalid: |
- return "Opcode sequence doesn't define a valid x86 instruction"; |
- case NaClMarkedSystem: |
- return "System instructions are not allowed by Native Client"; |
- case NaClHasBadSegmentPrefix: |
- return "Uses a segment prefix byte not allowed by Native Client"; |
- case NaClCantUsePrefix67: |
- return "Use of 67 (ADDR16) prefix not allowed by Native Client"; |
- case NaClMultipleRexPrefix: |
- return "Multiple use of REX prefix not allowed"; |
- case NaClRepDisallowed: |
- return |
- "Use of REP (F3) prefix for instruction not allowed by " |
- "Native Client"; |
- case NaClRepneDisallowed: |
- return |
- "Use of REPNE (F2) prefix for instruction not allowed by " |
- "Native Client"; |
- case NaClData16Disallowed: |
- return |
- "Use of DATA16 (66) prefix for instruction not allowed by " |
- "Native Client"; |
- case NaClHasDuplicatePrefix: |
- return |
- "Duplicating a prefix byte is not allowed by Native Client"; |
- case NaClHasAmbigSegmentPrefixes: |
- return |
- "Specifying different segment registers using prefix bytes " |
- "is not allowed by Native Client"; |
- case NaClRexPrefixNotLast: |
- return "REX prefix byte must appear last"; |
- default: |
- return NULL; |
- } |
-} |
- |
-/* Same as NaClReasonWhyDisallowed, except that the unknown value (NULL) |
- * is replaced by a useful print error message. |
- */ |
-static const char* NaClGetReasonWhyDisallowed(NaClDisallowsFlag flag) { |
- const char* why = NaClReasonWhyDisallowed(flag); |
- if (NULL == why) { |
- /* If reached, we don't understand the flag. Non the less, we should |
- * return a message explaining that the instruction is illegal, so |
- * that an appropriate error message can be printed. |
- */ |
- why = kNaClGenericReasonDisallowed; |
- } |
- return why; |
-} |
- |
-/* A mask of possible segment prefixes. */ |
-static const uint32_t kNaClSegmentPrefixMask = |
- kPrefixSEGES | kPrefixSEGFS | kPrefixSEGGS | kPrefixSEGSS | |
- kPrefixSEGCS | kPrefixSEGDS; |
- |
-/* |
- * A mask for prefixes that can't appear with any jump instruction. |
- * Note: We rule these out because of Intel's Software Developer's |
- * Manual (volume 2a) documents in section 2.1.1 that such uses may |
- * cause unpredictable behaviour. |
- */ |
-static const uint32_t kNaClUnsafeJumpPrefixes = |
- kPrefixSEGES | kPrefixSEGFS | kPrefixSEGGS | kPrefixSEGSS; |
- |
-/* |
- * A mask for prefixes that can only appear with conditional jump |
- * instructions with branch hints. |
- */ |
-static const uint32_t kNaClBranchHintJumpPrefixes = |
- kPrefixSEGCS | kPrefixSEGDS; |
- |
-/* This function checks properties about segment registers on an |
- * instruction, reporting issues not allowed by native client. |
- */ |
-static void NaClCheckSegmentPrefixes(NaClValidatorState* state, |
- Bool* is_legal, |
- NaClDisallowsFlags* disallows_flags) { |
- NaClInstState* inst_state = state->cur_inst_state; |
- Bool segment_prefixes_ok = TRUE; |
- |
- if (0 == (inst_state->prefix_mask & kNaClSegmentPrefixMask)) return; |
- |
- if (state->cur_inst->flags & |
- (NACL_IFLAG(JumpInstruction) | NACL_IFLAG(ConditionalJump))) { |
- if (inst_state->prefix_mask & kNaClUnsafeJumpPrefixes) { |
- segment_prefixes_ok = FALSE; |
- } |
- if (NaClExcludesBit(state->cur_inst->flags, NACL_IFLAG(BranchHints)) && |
- NaClHasBit(inst_state->prefix_mask, kNaClBranchHintJumpPrefixes)) { |
- segment_prefixes_ok = FALSE; |
- } |
- } else { |
- /* We don't allow any prefix masks on data accesses. */ |
- segment_prefixes_ok = FALSE; |
- } |
- |
- if (!segment_prefixes_ok) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasBadSegmentPrefix); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClHasBadSegmentPrefix))); |
- } |
- |
- /* Don't allow ambiguous prefix forms. */ |
- if (inst_state->has_ambig_segment_prefixes) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasAmbigSegmentPrefixes); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClHasAmbigSegmentPrefixes))); |
- } |
- |
-} |
- |
-/* This function checks properties of prefix bytes on an instruction, |
- * reporting issues not allowed by native client. |
- * |
- * Parameters are: |
- * state : The current validator state to check. |
- * is_legal: Flag set to FALSE if any prefix problems are found. |
- * disallows_flags : Set of flags, describing the reason(s) the |
- * current instruction in the validator state is not |
- * legal in native client. Updated as appropriate. |
- */ |
-static void NaClCheckForPrefixIssues(NaClValidatorState* state, |
- Bool* is_legal, |
- NaClDisallowsFlags* disallows_flags) { |
- NaClInstState* inst_state = state->cur_inst_state; |
- const NaClInst* inst = state->cur_inst; |
- /* Don't allow more than one (non-REX) prefix. */ |
- int num_prefix_bytes = inst_state->num_prefix_bytes; |
- if (inst_state->rexprefix) --num_prefix_bytes; |
- |
- /* Don't allow an invalid instruction. */ |
- if (!NaClInstStateIsValid(inst_state)) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedInvalid); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClMarkedInvalid))); |
- } |
- |
- /* If there aren't prefix bytes, there isn't anything to check. */ |
- if (num_prefix_bytes == 0) return; |
- |
- /* Don't allow multiple prefix bytes, except for the special |
- * case of the pair DATA16 and LOCK (allowed so that one can |
- * lock short integers). |
- * |
- * Note: Explicit NOP sequences that use multiple 66 values are |
- * recognized as special cases, and need not be processed here. |
- */ |
- if (num_prefix_bytes > 1) { |
- if ((num_prefix_bytes == 2) && |
- (inst_state->prefix_mask & kPrefixDATA16) && |
- (inst_state->prefix_mask & kPrefixLOCK)) { |
- /* Allow data prefix if lock prefix also given. */ |
- } else { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClTooManyPrefixBytes); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClTooManyPrefixBytes))); |
- } |
- } |
- |
- /* Only allow REP/REPE/REPZ (F3) prefix if flag specifies it is allowed. */ |
- if ((inst_state->prefix_mask & kPrefixREP) && |
- (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsRep)))) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRepDisallowed); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClRepDisallowed))); |
- } |
- |
- /* Only allow REPNE/REPNZ (F2) prefix if flag specifies it is allowed. */ |
- if ((inst_state->prefix_mask & kPrefixREPNE) && |
- (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsRepne)))) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRepneDisallowed); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClRepneDisallowed))); |
- } |
- |
- /* Only allow Data16 (66) prefix if flag specifies it is allowed. */ |
- if ((inst_state->prefix_mask & kPrefixDATA16) && |
- (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsData16)))) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClData16Disallowed); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClData16Disallowed))); |
- } |
- |
- /* Don't allow more than one REX prefix. */ |
- if (inst_state->num_rex_prefixes > 1) { |
- /* NOTE: does not apply to NOP, since they are parsed using |
- * special handling (i.e. explicit byte sequence matches) that |
- * doesn't explicitly define prefix bytes. |
- * |
- * NOTE: We don't disallow this while decoding, since xed doesn't |
- * disallow this, and we want to be able to compare our tool |
- * to xed. |
- */ |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMultipleRexPrefix); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClMultipleRexPrefix))); |
- } |
- |
- /* Don't allow shortened address sizes. That is prefix ADDR16. */ |
- if (inst_state->prefix_mask & kPrefixADDR16) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClCantUsePrefix67); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClCantUsePrefix67))); |
- } |
- |
- NaClCheckSegmentPrefixes(state, is_legal, disallows_flags); |
- |
- /* Don't allow duplicated prefixes. Note: Don't report if multiple |
- * REX prefixes has been reported, since we don't know what duplicates |
- * caused the problem, and an error has already been reported. |
- */ |
- if (inst_state->has_prefix_duplicates && |
- (NACL_EMPTY_DISALLOWS_FLAGS == |
- (*disallows_flags & NACL_DISALLOWS_FLAG(NaClMultipleRexPrefix)))) { |
- /* NOTE: does not apply to NOP, since they are parsed using |
- * special handling (i.e. explicit byte sequence matches) that |
- * doesn't explicitly define prefix bytes. |
- * |
- * NOTE: We don't disallow this while decoding, since xed doesn't |
- * disallow this, and we want to be able to compare our tool |
- * to xed. |
- */ |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasDuplicatePrefix); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClHasDuplicatePrefix))); |
- } |
- |
- /* Check the location of the REX prefix, if one is specified.. */ |
- if (inst_state->prefix_mask & kPrefixREX) { |
- /* First find the locations of the REX prefix. */ |
- int i; |
- int rex_index = -1; |
- for (i = 0; i < inst_state->num_prefix_bytes; ++i) { |
- char prefix = inst_state->bytes.byte[i]; |
- switch (prefix) { |
- case 0x40: |
- case 0x41: |
- case 0x42: |
- case 0x43: |
- case 0x44: |
- case 0x45: |
- case 0x46: |
- case 0x47: |
- case 0x48: |
- case 0x49: |
- case 0x4a: |
- case 0x4b: |
- case 0x4c: |
- case 0x4d: |
- case 0x4e: |
- case 0x4f: |
- rex_index = i; |
- break; |
- default: |
- break; |
- } |
- } |
- /* NOTE: REX prefix must be last, unless FO exists. If FO |
- * exists, it must be after REX (Intel Manual). |
- * |
- * NOTE: (karl) It appears that this constraint is violated |
- * with compiled code of /bin/ld_static. According to AMD, |
- * the rex prefix must be last. |
- * |
- * For now, we will follow the convention of gcc, which places |
- * the LOCK byte in front of the REX byte. |
- */ |
- if (rex_index >= 0) { |
- if ((rex_index + 1) != inst_state->num_prefix_bytes) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRexPrefixNotLast); |
- } |
- } |
- } |
-} |
- |
-/* Checks instruction details of the current instruction to see if there |
- * are any red flags that make the instruction illegal. |
- * |
- * Parameters are: |
- * state : The current validator state to check. |
- * is_legal: Flag set to FALSE if any prefix problems are found. |
- * disallows_flags : Set of flags, describing the reason(s) the |
- * current instruction in the validator state is not |
- * legal in native client. Updated as appropriate. |
- */ |
-static void NaClCheckIfMarkedIllegal(NaClValidatorState* state, |
- Bool* is_legal, |
- NaClDisallowsFlags* disallows_flags) { |
- if (NACL_IFLAG(NaClIllegal) & state->cur_inst->flags) { |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedIllegal); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClMarkedIllegal))); |
- } |
- |
- /* Check other forms to disallow. |
- * TODO(karl): Move these checks into the model generator, setting the |
- * NaClIllegal flag. Once that is completed, this switch statement can |
- * can be removed. |
- */ |
- switch (state->cur_inst->insttype) { |
- case NACLi_RETURN: |
- case NACLi_EMMX: |
- /* EMMX needs to be supported someday but isn't ready yet. */ |
- case NACLi_ILLEGAL: |
- case NACLi_SYSTEM: |
- case NACLi_RDMSR: |
- case NACLi_RDTSCP: |
- case NACLi_LONGMODE: |
- case NACLi_SVM: |
- case NACLi_3BYTE: |
- case NACLi_UNDEFINED: |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedIllegal); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClMarkedIllegal))); |
- break; |
- case NACLi_INVALID: |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedInvalid); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClMarkedInvalid))); |
- break; |
- case NACLi_SYSCALL: |
- case NACLi_SYSENTER: |
- *is_legal = FALSE; |
- *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedSystem); |
- DEBUG(NaClLog(LOG_INFO, "%s\n", |
- NaClGetReasonWhyDisallowed(NaClMarkedSystem))); |
- break; |
- default: |
- break; |
- } |
-} |
- |
-/* Prints out error messages describing why the current instruction |
- * in the given validator state is not legal in native client. |
- * |
- * Parameters are: |
- * state : The current validator state to check. |
- * disallows_flags : Set of flags, describing the reason(s) the |
- * current instruction in the validator state is not |
- * legal in native client. Updated as appropriate. |
- */ |
-static void NaClReportWhyNaClIllegal(NaClValidatorState* state, |
- NaClDisallowsFlags disallows_flags) { |
- if (NACL_EMPTY_DISALLOWS_FLAGS != disallows_flags) { |
- int i; |
- Bool printed_reason = FALSE; |
- NaClInstState* inst_state = state->cur_inst_state; |
- /* Print out error message for each reason the instruction is disallowed. */ |
- for (i = 0; i < NaClDisallowsFlagEnumSize; ++i) { |
- if (disallows_flags & NACL_DISALLOWS_FLAG(i)) { |
- const char* why_disallowed = NaClReasonWhyDisallowed(i); |
- if (NULL != why_disallowed) { |
- printed_reason = TRUE; |
- NaClValidatorInstMessage( |
- LOG_ERROR, state, inst_state, "%s\n", why_disallowed); |
- } |
- } |
- /* Stop looking if we should quit reporting errors. */ |
- if (state->quit) break; |
- } |
- /* Be sure we print a reason (in case the switch isn't complete). */ |
- if (!printed_reason) { |
- disallows_flags = NACL_EMPTY_DISALLOWS_FLAGS; |
- } |
- } |
- if (NACL_EMPTY_DISALLOWS_FLAGS == disallows_flags) { |
- /* No known reason was recorded, but the instruction was recorded as illegal. |
- * Report that the instruction is not acceptable. |
- */ |
- NaClValidatorInstMessage(LOG_ERROR, state, state->cur_inst_state, |
- "%s\n", kNaClGenericReasonDisallowed); |
- } |
-} |
- |
-void NaClValidateInstructionLegal(NaClValidatorState* state) { |
- Bool is_legal = TRUE; |
- NaClDisallowsFlags disallows_flags = NACL_EMPTY_DISALLOWS_FLAGS; |
- DEBUG_OR_ERASE({ |
- struct Gio* g = NaClLogGetGio(); |
- NaClLog(LOG_INFO, "->NaClValidateInstructionLegal\n"); |
- NaClInstPrint(g, state->decoder_tables, |
- NaClInstStateInst(state->cur_inst_state)); |
- NaClExpVectorPrint(g, state); |
- }); |
- NaClCheckForPrefixIssues(state, &is_legal, &disallows_flags); |
- NaClCheckIfMarkedIllegal(state, &is_legal, &disallows_flags); |
- if (!is_legal) { |
- NaClReportWhyNaClIllegal(state, disallows_flags); |
- } |
- DEBUG(NaClLog(LOG_INFO, |
- "<-NaClValidateInstructionLegal: is_legal = %"NACL_PRIdBool"\n", |
- is_legal)); |
-} |