| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include <assert.h> | 7 #include <assert.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdio.h> | 9 #include <stdio.h> |
| 10 #include <stdlib.h> | 10 #include <stdlib.h> |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 action rel16_operand { | 81 action rel16_operand { |
| 82 assert(FALSE); | 82 assert(FALSE); |
| 83 } | 83 } |
| 84 action rel32_operand { | 84 action rel32_operand { |
| 85 int32_t offset = | 85 int32_t offset = |
| 86 (uint32_t) (p[-3] + 256U * (p[-2] + 256U * (p[-1] + 256U * (p[0])))); | 86 (uint32_t) (p[-3] + 256U * (p[-2] + 256U * (p[-1] + 256U * (p[0])))); |
| 87 size_t jump_dest = offset + (p - data); | 87 size_t jump_dest = offset + (p - data); |
| 88 check_jump_dest; | 88 check_jump_dest; |
| 89 } | 89 } |
| 90 | 90 |
| 91 include decode_x86_64 "validator-x86_64-instruction.rl"; | 91 action process_0_operands { |
| 92 | |
| 93 action process_normal_instruction { | |
| 94 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special | 92 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 95 instruction, not with regular instruction. */ | 93 instruction, not with regular instruction. */ |
| 96 if (restricted_register == REG_RSP) { | 94 if (restricted_register == REG_RSP) { |
| 95 PrintError("Incorrectly modified register %%rsp\n", begin - data); |
| 96 result = 1; |
| 97 goto error_detected; |
| 98 } else if (restricted_register == REG_RBP) { |
| 99 PrintError("Incorrectly modified register %%rbp\n", begin - data); |
| 100 result = 1; |
| 101 goto error_detected; |
| 102 } |
| 103 restricted_register = kNoRestrictedReg; |
| 104 } |
| 105 |
| 106 action process_1_operands { |
| 107 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 108 instruction, not with regular instruction. */ |
| 109 if (restricted_register == REG_RSP) { |
| 97 PrintError("Incorrectly modified register %%rsp\n", begin - data); | 110 PrintError("Incorrectly modified register %%rsp\n", begin - data); |
| 98 result = 1; | 111 result = 1; |
| 99 goto error_detected; | 112 goto error_detected; |
| 100 } else if (restricted_register == REG_RBP) { | 113 } else if (restricted_register == REG_RBP) { |
| 101 PrintError("Incorrectly modified register %%rbp\n", begin - data); | 114 PrintError("Incorrectly modified register %%rbp\n", begin - data); |
| 102 result = 1; | 115 result = 1; |
| 103 goto error_detected; | 116 goto error_detected; |
| 104 } | 117 } |
| 105 /* If Sandboxed Rsi is destroyed then we must note that. */ | 118 /* If Sandboxed Rsi is destroyed then we must detect that. */ |
| 119 if (restricted_register == kSandboxedRsi) { |
| 120 if (CHECK_OPERAND(0, REG_RSI, OperandSandboxRestricted) || |
| 121 CHECK_OPERAND(0, REG_RSI, OperandSandboxUnrestricted)) { |
| 122 restricted_register = kNoRestrictedReg; |
| 123 } |
| 124 } |
| 125 if (restricted_register == kSandboxedRsi) { |
| 126 if (CHECK_OPERAND(0, REG_RDI, OperandSandboxRestricted)) { |
| 127 sandboxed_rsi_restricted_rdi = begin; |
| 128 restricted_register = kSandboxedRsiRestrictedRdi; |
| 129 } |
| 130 } |
| 131 if (restricted_register != kSandboxedRsiRestrictedRdi) { |
| 132 restricted_register = kNoRestrictedReg; |
| 133 if (CHECK_OPERAND(0, REG_R15, OperandSandbox8bit) || |
| 134 CHECK_OPERAND(0, REG_R15, OperandSandboxRestricted) || |
| 135 CHECK_OPERAND(0, REG_R15, OperandSandboxUnrestricted)) { |
| 136 PrintError("Incorrectly modified register %%r15\n", begin - data); |
| 137 result = 1; |
| 138 goto error_detected; |
| 139 } else if ((CHECK_OPERAND(0, REG_RBP, OperandSandbox8bit) && |
| 140 GET_REX_PREFIX()) || |
| 141 CHECK_OPERAND(0, REG_RBP, OperandSandboxUnrestricted)) { |
| 142 PrintError("Incorrectly modified register %%rbp\n", begin - data); |
| 143 result = 1; |
| 144 goto error_detected; |
| 145 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && |
| 146 GET_REX_PREFIX()) || |
| 147 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted)) { |
| 148 PrintError("Incorrectly modified register %%rsp\n", begin - data); |
| 149 result = 1; |
| 150 goto error_detected; |
| 151 /* |
| 152 * Take 2 bits of operand type from operand_states as restricted_register, |
| 153 * make sure operand_states denotes a register (4th bit == 0). |
| 154 */ |
| 155 } else if ((operand_states & 0x70) == (OperandSandboxRestricted << 5)) { |
| 156 restricted_register = operand_states & 0x0f; |
| 157 } |
| 158 } |
| 159 } |
| 160 |
| 161 action process_2_operands { |
| 162 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 163 instruction, not with regular instruction. */ |
| 164 if (restricted_register == REG_RSP) { |
| 165 PrintError("Incorrectly modified register %%rsp\n", begin - data); |
| 166 result = 1; |
| 167 goto error_detected; |
| 168 } else if (restricted_register == REG_RBP) { |
| 169 PrintError("Incorrectly modified register %%rbp\n", begin - data); |
| 170 result = 1; |
| 171 goto error_detected; |
| 172 } |
| 173 /* If Sandboxed Rsi is destroyed then we must detect that. */ |
| 106 if (restricted_register == kSandboxedRsi) { | 174 if (restricted_register == kSandboxedRsi) { |
| 107 if (CHECK_OPERAND(0, REG_RSI, OperandSandboxRestricted) || | 175 if (CHECK_OPERAND(0, REG_RSI, OperandSandboxRestricted) || |
| 108 CHECK_OPERAND(0, REG_RSI, OperandSandboxUnrestricted) || | 176 CHECK_OPERAND(0, REG_RSI, OperandSandboxUnrestricted) || |
| 109 CHECK_OPERAND(1, REG_RSI, OperandSandboxRestricted) || | 177 CHECK_OPERAND(1, REG_RSI, OperandSandboxRestricted) || |
| 110 CHECK_OPERAND(1, REG_RSI, OperandSandboxUnrestricted)) { | 178 CHECK_OPERAND(1, REG_RSI, OperandSandboxUnrestricted)) { |
| 111 restricted_register = kNoRestrictedReg; | 179 restricted_register = kNoRestrictedReg; |
| 112 } | 180 } |
| 113 } | 181 } |
| 114 if (restricted_register == kSandboxedRsi) { | 182 if (restricted_register == kSandboxedRsi) { |
| 115 if (CHECK_OPERAND(0, REG_RDI, OperandSandboxRestricted) || | 183 if (CHECK_OPERAND(0, REG_RDI, OperandSandboxRestricted) || |
| (...skipping 24 matching lines...) Expand all Loading... |
| 140 goto error_detected; | 208 goto error_detected; |
| 141 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && | 209 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && |
| 142 GET_REX_PREFIX()) || | 210 GET_REX_PREFIX()) || |
| 143 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted) || | 211 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted) || |
| 144 (CHECK_OPERAND(1, REG_RSP, OperandSandbox8bit) && | 212 (CHECK_OPERAND(1, REG_RSP, OperandSandbox8bit) && |
| 145 GET_REX_PREFIX()) || | 213 GET_REX_PREFIX()) || |
| 146 CHECK_OPERAND(1, REG_RSP, OperandSandboxUnrestricted)) { | 214 CHECK_OPERAND(1, REG_RSP, OperandSandboxUnrestricted)) { |
| 147 PrintError("Incorrectly modified register %%rsp\n", begin - data); | 215 PrintError("Incorrectly modified register %%rsp\n", begin - data); |
| 148 result = 1; | 216 result = 1; |
| 149 goto error_detected; | 217 goto error_detected; |
| 218 /* |
| 219 * Take 2 bits of operand type from operand_states as restricted_register, |
| 220 * make sure operand_states denotes a register (4th bit == 0). |
| 221 */ |
| 150 } else if ((operand_states & 0x70) == (OperandSandboxRestricted << 5)) { | 222 } else if ((operand_states & 0x70) == (OperandSandboxRestricted << 5)) { |
| 151 restricted_register = operand_states & 0x0f; | 223 restricted_register = operand_states & 0x0f; |
| 224 /* |
| 225 * Take 2 bits of operand type from operand_states as restricted_register, |
| 226 * make sure operand_states denotes a register (12th bit == 0). |
| 227 */ |
| 152 } else if ((operand_states & 0x7000) == | 228 } else if ((operand_states & 0x7000) == |
| 153 (OperandSandboxRestricted << (5 + 8))) { | 229 (OperandSandboxRestricted << (5 + 8))) { |
| 154 restricted_register = (operand_states & 0x0f00) >> 8; | 230 restricted_register = (operand_states & 0x0f00) >> 8; |
| 155 } | 231 } |
| 156 } | 232 } |
| 157 } | 233 } |
| 158 | 234 |
| 235 include decode_x86_64 "validator-x86_64-instruction.rl"; |
| 236 |
| 159 # Remove special instructions which are only allowed in special cases. | 237 # Remove special instructions which are only allowed in special cases. |
| 160 normal_instruction = (one_instruction - ( | 238 normal_instruction = one_instruction - ( |
| 161 (0x48 0x89 0xe5) | # mov %rsp,%rbp | 239 (0x48 0x89 0xe5) | # mov %rsp,%rbp |
| 162 (0x48 0x89 0xec) | # mov %rbp,%rsp | 240 (0x48 0x89 0xec) | # mov %rbp,%rsp |
| 163 (0x48 0x81 0xe4 any{4}) | # and $XXX,%rsp | 241 (0x48 0x81 0xe4 any{4}) | # and $XXX,%rsp |
| 164 (0x48 0x83 0xe4 any) | # and $XXX,%rsp | 242 (0x48 0x83 0xe4 any) | # and $XXX,%rsp |
| 165 (0x4c 0x01 0xfd) | # add %r15,%rbp | 243 (0x4c 0x01 0xfd) | # add %r15,%rbp |
| 166 (0x49 0x8d 0x2c 0x2f) | # lea (%r15,%rbp,1),%rbp | 244 (0x49 0x8d 0x2c 0x2f) | # lea (%r15,%rbp,1),%rbp |
| 167 (0x4a 0x8d 0x6c 0x3d any) | # lea 0x0(%rbp,%r15,1),%rbp | 245 (0x4a 0x8d 0x6c 0x3d any) | # lea 0x0(%rbp,%r15,1),%rbp |
| 168 (0x48 0x81 0xe5 any{4}) | # and $XXX,%rsp | 246 (0x48 0x81 0xe5 any{4}) | # and $XXX,%rsp |
| 169 (0x48 0x83 0xe5 any) | # and $XXX,%rsp | 247 (0x48 0x83 0xe5 any) | # and $XXX,%rsp |
| 170 (0x4c 0x01 0xfc) | # add %r15,%rsp | 248 (0x4c 0x01 0xfc) | # add %r15,%rsp |
| 171 (0x4a 0x8d 0x24 0x3c) | # lea (%rsp,%r15,1),%rsp | 249 (0x4a 0x8d 0x24 0x3c) | # lea (%rsp,%r15,1),%rsp |
| 172 (0x49 0x8d 0x34 0x37) | # lea (%r15,%rsi,1),%rsi | 250 (0x49 0x8d 0x34 0x37) | # lea (%r15,%rsi,1),%rsi |
| 173 (0x49 0x8d 0x3c 0x3f) # lea (%r15,%rdi,1),%rdi | 251 (0x49 0x8d 0x3c 0x3f) # lea (%r15,%rdi,1),%rdi |
| 174 )) @process_normal_instruction; | 252 ); |
| 175 | 253 |
| 176 data16condrep = (data16 | condrep data16 | data16 condrep); | 254 data16condrep = (data16 | condrep data16 | data16 condrep); |
| 177 data16rep = (data16 | rep data16 | data16 rep); | 255 data16rep = (data16 | rep data16 | data16 rep); |
| 178 | 256 |
| 179 special_instruction = | 257 special_instruction = |
| 180 (0x48 0x89 0xe5) | # mov %rsp,%rbp | 258 (0x48 0x89 0xe5) | # mov %rsp,%rbp |
| 181 (0x48 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp | 259 (0x48 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp |
| 182 (0x48 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp | 260 (0x48 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp |
| 183 @{ if (restricted_register == REG_RSP) { | 261 @{ if (restricted_register == REG_RSP) { |
| 184 PrintError("Incorrectly modified register %%rsp\n", begin - data); | 262 PrintError("Incorrectly modified register %%rsp\n", begin - data); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 * OperandSandboxUnrestricted to match the behavior of the old validator. | 450 * OperandSandboxUnrestricted to match the behavior of the old validator. |
| 373 * | 451 * |
| 374 * 8bit operands must be distinguished from other types because the REX prefix | 452 * 8bit operands must be distinguished from other types because the REX prefix |
| 375 * regulates the choice between %ah and %spl, as well as %ch and %bpl. | 453 * regulates the choice between %ah and %spl, as well as %ch and %bpl. |
| 376 */ | 454 */ |
| 377 OperandSandbox8bit, | 455 OperandSandbox8bit, |
| 378 OperandSandboxRestricted, | 456 OperandSandboxRestricted, |
| 379 OperandSandboxUnrestricted | 457 OperandSandboxUnrestricted |
| 380 }; | 458 }; |
| 381 | 459 |
| 382 /* Define SET_OPERAND_NAME as SET_OPERAND_NAME_0, SET_OPERAND_NAME_1 to detect | 460 #define SET_OPERAND_NAME(N, S) operand_states |= ((S) << ((N) << 3)) |
| 383 * cases where more than two general purpose registers are affected. This will | |
| 384 * produce a compile-time error if an operand with unexpected number is | |
| 385 * encountered. */ | |
| 386 #define SET_OPERAND_NAME(N, S) SET_OPERAND_NAME_ ## N(S) | |
| 387 #define SET_OPERAND_NAME_0(S) operand_states |= (S) | |
| 388 #define SET_OPERAND_NAME_1(S) operand_states |= ((S) << 8) | |
| 389 #define SET_OPERAND_TYPE(N, T) SET_OPERAND_TYPE_ ## T(N) | 461 #define SET_OPERAND_TYPE(N, T) SET_OPERAND_TYPE_ ## T(N) |
| 390 #define SET_OPERAND_TYPE_OperandSize8bit(N) \ | 462 #define SET_OPERAND_TYPE_OperandSize8bit(N) \ |
| 391 operand_states |= OperandSandbox8bit << (5 + ((N) << 3)) | 463 operand_states |= OperandSandbox8bit << (5 + ((N) << 3)) |
| 392 #define SET_OPERAND_TYPE_OperandSize16bit(N) \ | 464 #define SET_OPERAND_TYPE_OperandSize16bit(N) \ |
| 393 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) | 465 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) |
| 394 #define SET_OPERAND_TYPE_OperandSize32bit(N) \ | 466 #define SET_OPERAND_TYPE_OperandSize32bit(N) \ |
| 395 operand_states |= OperandSandboxRestricted << (5 + ((N) << 3)) | 467 operand_states |= OperandSandboxRestricted << (5 + ((N) << 3)) |
| 396 #define SET_OPERAND_TYPE_OperandSize64bit(N) \ | 468 #define SET_OPERAND_TYPE_OperandSize64bit(N) \ |
| 397 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) | 469 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) |
| 398 #define CHECK_OPERAND(N, S, T) \ | 470 #define CHECK_OPERAND(N, S, T) \ |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 } | 644 } |
| 573 } | 645 } |
| 574 | 646 |
| 575 if (CheckJumpTargets(valid_targets, jump_dests, size)) { | 647 if (CheckJumpTargets(valid_targets, jump_dests, size)) { |
| 576 return 1; | 648 return 1; |
| 577 } | 649 } |
| 578 | 650 |
| 579 error_detected: | 651 error_detected: |
| 580 return result; | 652 return result; |
| 581 } | 653 } |
| OLD | NEW |