| 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 <elf.h> | |
| 9 #include <inttypes.h> | |
| 10 #include <stddef.h> | 8 #include <stddef.h> |
| 11 #include <stdio.h> | 9 #include <stdio.h> |
| 12 #include <stdlib.h> | 10 #include <stdlib.h> |
| 13 #include <string.h> | 11 #include <string.h> |
| 14 #include "validator.h" | |
| 15 | 12 |
| 16 #undef TRUE | 13 #include "native_client/src/shared/utils/types.h" |
| 17 #define TRUE 1 | 14 #include "native_client/src/trusted/validator_ragel/unreviewed/validator.h" |
| 18 | 15 |
| 19 #undef FALSE | 16 #if defined(_MSC_VER) |
| 20 #define FALSE 0 | 17 #define inline __inline |
| 18 #endif |
| 21 | 19 |
| 22 #include "validator-x86_64-instruction-consts.c" | 20 #include "native_client/src/trusted/validator_ragel/gen/validator-x86_64-instruc
tion-consts.c" |
| 23 | 21 |
| 24 #define check_jump_dest \ | 22 #define check_jump_dest \ |
| 25 if ((jump_dest & bundle_mask) != bundle_mask) { \ | 23 if ((jump_dest & bundle_mask) != bundle_mask) { \ |
| 26 if (jump_dest >= size) { \ | 24 if (jump_dest >= size) { \ |
| 27 printf("direct jump out of range: %zx\n", jump_dest); \ | 25 printf("direct jump out of range: %"NACL_PRIxS"\n", jump_dest); \ |
| 28 result = 1; \ | 26 result = 1; \ |
| 29 goto error_detected; \ | 27 goto error_detected; \ |
| 30 } else { \ | 28 } else { \ |
| 31 BitmapSetBit(jump_dests, jump_dest + 1); \ | 29 BitmapSetBit(jump_dests, jump_dest + 1); \ |
| 32 } \ | 30 } \ |
| 33 } \ | 31 } \ |
| 34 operand0 = JMP_TO; \ | 32 operand0 = JMP_TO; \ |
| 35 base = REG_RIP; \ | 33 base = REG_RIP; \ |
| 36 index = REG_NONE; | 34 index = NO_REG; |
| 37 | 35 |
| 38 static void PrintError(const char* msg, uintptr_t ptr) { | 36 static void PrintError(const char* msg, uintptr_t ptr) { |
| 39 printf("offset 0x%zx: %s", ptr, msg); | 37 printf("offset 0x%"NACL_PRIxS": %s", ptr, msg); |
| 40 } | 38 } |
| 41 | 39 |
| 42 %%{ | 40 %%{ |
| 43 machine x86_64_decoder; | 41 machine x86_64_decoder; |
| 44 alphtype unsigned char; | 42 alphtype unsigned char; |
| 45 | 43 |
| 46 action check_access { | 44 action check_access { |
| 47 if ((base == REG_RIP) || (base == REG_R15) || | 45 if ((base == REG_RIP) || (base == REG_R15) || |
| 48 ((base == REG_RSP) && (restricted_register != REG_RSP)) || | 46 ((base == REG_RSP) && (restricted_register != REG_RSP)) || |
| 49 ((base == REG_RBP) && (restricted_register != REG_RBP))) { | 47 ((base == REG_RBP) && (restricted_register != REG_RBP))) { |
| 50 if ((index == restricted_register) || | 48 if ((index == restricted_register) || |
| 51 ((index == REG_RDI) && | 49 ((index == REG_RDI) && |
| 52 (restricted_register == kSandboxedRsiRestrictedRdi))) { | 50 (restricted_register == kSandboxedRsiRestrictedRdi))) { |
| 53 BitmapClearBit(valid_targets, begin - data); | 51 BitmapClearBit(valid_targets, begin - data); |
| 54 } else if ((index != REG_NONE) && (index != REG_RIZ)) { | 52 } else if ((index != NO_REG) && (index != REG_RIZ)) { |
| 55 PrintError("Improper sandboxing in instruction\n", begin - data); | 53 PrintError("Improper sandboxing in instruction\n", begin - data); |
| 56 result = 1; | 54 result = 1; |
| 57 goto error_detected; | 55 goto error_detected; |
| 58 } | 56 } |
| 59 } else if ((index == REG_RIP) || (index == REG_R15) || | 57 } else if ((index == REG_RIP) || (index == REG_R15) || |
| 60 ((index == REG_RSP) && (restricted_register != REG_RSP)) || | 58 ((index == REG_RSP) && (restricted_register != REG_RSP)) || |
| 61 ((index == REG_RBP) && (restricted_register != REG_RBP))) { | 59 ((index == REG_RBP) && (restricted_register != REG_RBP))) { |
| 62 if ((base == restricted_register) || | 60 if ((base == restricted_register) || |
| 63 ((base == REG_RDI) && | 61 ((base == REG_RDI) && |
| 64 (restricted_register == kSandboxedRsiRestrictedRdi))) { | 62 (restricted_register == kSandboxedRsiRestrictedRdi))) { |
| 65 BitmapClearBit(valid_targets, begin - data); | 63 BitmapClearBit(valid_targets, begin - data); |
| 66 } else if ((base != REG_NONE) && (base != REG_RIZ)) { | 64 } else if ((base != NO_REG) && (base != REG_RIZ)) { |
| 67 PrintError("Improper sandboxing in instruction\n", begin - data); | 65 PrintError("Improper sandboxing in instruction\n", begin - data); |
| 68 result = 1; | 66 result = 1; |
| 69 goto error_detected; | 67 goto error_detected; |
| 70 } | 68 } |
| 71 } else { | 69 } else { |
| 72 PrintError("Improper sandboxing in instruction\n", begin - data); | 70 PrintError("Improper sandboxing in instruction\n", begin - data); |
| 73 result = 1; | 71 result = 1; |
| 74 goto error_detected; | 72 goto error_detected; |
| 75 } | 73 } |
| 76 } | 74 } |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 IMMNONE, | 405 IMMNONE, |
| 408 IMM2, | 406 IMM2, |
| 409 IMM8, | 407 IMM8, |
| 410 IMM16, | 408 IMM16, |
| 411 IMM32, | 409 IMM32, |
| 412 IMM64 | 410 IMM64 |
| 413 }; | 411 }; |
| 414 | 412 |
| 415 static const int kBitsPerByte = 8; | 413 static const int kBitsPerByte = 8; |
| 416 | 414 |
| 417 static inline uint8_t *BitmapAllocate(uint32_t indexes) { | 415 static inline uint8_t *BitmapAllocate(size_t indexes) { |
| 418 uint32_t byte_count = (indexes + kBitsPerByte - 1) / kBitsPerByte; | 416 size_t byte_count = (indexes + kBitsPerByte - 1) / kBitsPerByte; |
| 419 uint8_t *bitmap = malloc(byte_count); | 417 uint8_t *bitmap = malloc(byte_count); |
| 420 if (bitmap != NULL) { | 418 if (bitmap != NULL) { |
| 421 memset(bitmap, 0, byte_count); | 419 memset(bitmap, 0, byte_count); |
| 422 } | 420 } |
| 423 return bitmap; | 421 return bitmap; |
| 424 } | 422 } |
| 425 | 423 |
| 426 static inline int BitmapIsBitSet(uint8_t *bitmap, uint32_t index) { | 424 static inline int BitmapIsBitSet(uint8_t *bitmap, size_t index) { |
| 427 return (bitmap[index / kBitsPerByte] & (1 << (index % kBitsPerByte))) != 0; | 425 return (bitmap[index / kBitsPerByte] & (1 << (index % kBitsPerByte))) != 0; |
| 428 } | 426 } |
| 429 | 427 |
| 430 static inline void BitmapSetBit(uint8_t *bitmap, uint32_t index) { | 428 static inline void BitmapSetBit(uint8_t *bitmap, size_t index) { |
| 431 bitmap[index / kBitsPerByte] |= 1 << (index % kBitsPerByte); | 429 bitmap[index / kBitsPerByte] |= 1 << (index % kBitsPerByte); |
| 432 } | 430 } |
| 433 | 431 |
| 434 static inline void BitmapClearBit(uint8_t *bitmap, uint32_t index) { | 432 static inline void BitmapClearBit(uint8_t *bitmap, size_t index) { |
| 435 bitmap[index / kBitsPerByte] &= ~(1 << (index % kBitsPerByte)); | 433 bitmap[index / kBitsPerByte] &= ~(1 << (index % kBitsPerByte)); |
| 436 } | 434 } |
| 437 | 435 |
| 438 static int CheckJumpTargets(uint8_t *valid_targets, uint8_t *jump_dests, | 436 static int CheckJumpTargets(uint8_t *valid_targets, uint8_t *jump_dests, |
| 439 size_t size) { | 437 size_t size) { |
| 440 size_t i; | 438 size_t i; |
| 441 for (i = 0; i < size / 32; i++) { | 439 for (i = 0; i < size / 32; i++) { |
| 442 uint32_t jump_dest_mask = ((uint32_t *) jump_dests)[i]; | 440 uint32_t jump_dest_mask = ((uint32_t *) jump_dests)[i]; |
| 443 uint32_t valid_target_mask = ((uint32_t *) valid_targets)[i]; | 441 uint32_t valid_target_mask = ((uint32_t *) valid_targets)[i]; |
| 444 if ((jump_dest_mask & ~valid_target_mask) != 0) { | 442 if ((jump_dest_mask & ~valid_target_mask) != 0) { |
| 445 printf("bad jump to around %x\n", (unsigned)(i * 32)); | 443 printf("bad jump to around %x\n", (unsigned)(i * 32)); |
| 446 return 1; | 444 return 1; |
| 447 } | 445 } |
| 448 } | 446 } |
| 449 return 0; | 447 return 0; |
| 450 } | 448 } |
| 451 | 449 |
| 452 int ValidateChunkAMD64(const uint8_t *data, size_t size, | 450 int ValidateChunkAMD64(const uint8_t *data, size_t size, |
| 453 process_error_func process_error, void *userdata) { | 451 process_error_func process_error, void *userdata) { |
| 454 const size_t bundle_size = 32; | 452 const size_t bundle_size = 32; |
| 455 const size_t bundle_mask = bundle_size - 1; | 453 const size_t bundle_mask = bundle_size - 1; |
| 456 | 454 |
| 457 uint8_t *valid_targets = BitmapAllocate(size); | 455 uint8_t *valid_targets = BitmapAllocate(size); |
| 458 uint8_t *jump_dests = BitmapAllocate(size); | 456 uint8_t *jump_dests = BitmapAllocate(size); |
| 459 | 457 |
| 460 const uint8_t *p = data; | 458 const uint8_t *p = data; |
| 461 const uint8_t *begin = p; /* Start of the instruction being processed. */ | 459 const uint8_t *begin = p; /* Start of the instruction being processed. */ |
| 462 | 460 |
| 463 uint8_t rex_prefix, vex_prefix2, vex_prefix3; | 461 uint8_t rex_prefix = 0; |
| 462 uint8_t vex_prefix2 = 0xe0; |
| 463 uint8_t vex_prefix3 = 0x00; |
| 464 struct Operand { | 464 struct Operand { |
| 465 unsigned int name :5; | 465 unsigned int name :5; |
| 466 unsigned int type :2; | 466 unsigned int type :2; |
| 467 bool write :1; | 467 #ifdef _MSC_VER |
| 468 Bool write :1; |
| 469 #else |
| 470 _Bool write :1; |
| 471 #endif |
| 468 } operands[5]; | 472 } operands[5]; |
| 469 enum register_name base, index; | 473 enum register_name base = NO_REG; |
| 470 uint8_t operands_count, i; | 474 enum register_name index = NO_REG; |
| 475 uint8_t operands_count = 0; |
| 476 uint8_t i; |
| 471 int result = 0; | 477 int result = 0; |
| 472 /* | 478 /* |
| 473 * These are borders of the appropriate instructions. Initialize them to make | 479 * These are borders of the appropriate instructions. Initialize them to make |
| 474 * compiler happy: they are never used uninitialized even without explicit | 480 * compiler happy: they are never used uninitialized even without explicit |
| 475 * initialization but GCC is not sophysicated enough to prove that. | 481 * initialization but GCC is not sophysicated enough to prove that. |
| 476 */ | 482 */ |
| 477 const uint8_t *sandboxed_rsi = 0; | 483 const uint8_t *sandboxed_rsi = 0; |
| 478 const uint8_t *sandboxed_rsi_restricted_rdi = 0; | 484 const uint8_t *sandboxed_rsi_restricted_rdi = 0; |
| 479 const uint8_t *sandboxed_rdi = 0; | 485 const uint8_t *sandboxed_rdi = 0; |
| 480 | 486 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 506 } | 512 } |
| 507 } | 513 } |
| 508 | 514 |
| 509 if (CheckJumpTargets(valid_targets, jump_dests, size)) { | 515 if (CheckJumpTargets(valid_targets, jump_dests, size)) { |
| 510 return 1; | 516 return 1; |
| 511 } | 517 } |
| 512 | 518 |
| 513 error_detected: | 519 error_detected: |
| 514 return result; | 520 return result; |
| 515 } | 521 } |
| OLD | NEW |