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