| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2013 The Native Client Authors. All rights reserved. | 2 # Copyright (c) 2013 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 # Executable specification of valid instructions and superinstructions (in terms | 6 # Executable specification of valid instructions and superinstructions (in terms |
| 7 # of their disassembler listing). | 7 # of their disassembler listing). |
| 8 # Should serve as formal and up-to-date ABI reference and as baseline for | 8 # Should serve as formal and up-to-date ABI reference and as baseline for |
| 9 # validator exhaustive tests. | 9 # validator exhaustive tests. |
| 10 | 10 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 '%ebp' : '%rbp', | 210 '%ebp' : '%rbp', |
| 211 '%r8d' : '%r8', | 211 '%r8d' : '%r8', |
| 212 '%r9d' : '%r9', | 212 '%r9d' : '%r9', |
| 213 '%r10d' : '%r10', | 213 '%r10d' : '%r10', |
| 214 '%r11d' : '%r11', | 214 '%r11d' : '%r11', |
| 215 '%r12d' : '%r12', | 215 '%r12d' : '%r12', |
| 216 '%r13d' : '%r13', | 216 '%r13d' : '%r13', |
| 217 '%r14d' : '%r14', | 217 '%r14d' : '%r14', |
| 218 '%r15d' : '%r15'} | 218 '%r15d' : '%r15'} |
| 219 | 219 |
| 220 REGS32 = REG32_TO_REG64.keys() |
| 220 REGS64 = REG32_TO_REG64.values() | 221 REGS64 = REG32_TO_REG64.values() |
| 221 | 222 |
| 222 | 223 |
| 223 class Condition(object): | 224 class Condition(object): |
| 224 """Represents assertion about the state of 64-bit registers. | 225 """Represents assertion about the state of 64-bit registers. |
| 225 | 226 |
| 226 (used as precondition and postcondition) | 227 (used as precondition and postcondition) |
| 227 | 228 |
| 228 Supported assertions: | 229 Supported assertions: |
| 229 0. %rpb and %rsp are sandboxed (and nothing is known about other registers) | 230 0. %rpb and %rsp are sandboxed (and nothing is known about other registers) |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 for op in write_operands: | 418 for op in write_operands: |
| 418 # TODO(shcherbina): disallow writes to | 419 # TODO(shcherbina): disallow writes to |
| 419 # cs, ds, es, fs, gs | 420 # cs, ds, es, fs, gs |
| 420 if op in ['%r15', '%r15d', '%r15w', '%r15b']: | 421 if op in ['%r15', '%r15d', '%r15w', '%r15b']: |
| 421 raise SandboxingError('changes to r15 are not allowed', instruction) | 422 raise SandboxingError('changes to r15 are not allowed', instruction) |
| 422 if op in ['%bpl', '%bp', '%rbp']: | 423 if op in ['%bpl', '%bp', '%rbp']: |
| 423 raise SandboxingError('changes to rbp are not allowed', instruction) | 424 raise SandboxingError('changes to rbp are not allowed', instruction) |
| 424 if op in ['%spl', '%sp', '%rsp']: | 425 if op in ['%spl', '%sp', '%rsp']: |
| 425 raise SandboxingError('changes to rsp are not allowed', instruction) | 426 raise SandboxingError('changes to rsp are not allowed', instruction) |
| 426 | 427 |
| 427 if op in REG32_TO_REG64 and zero_extending: | 428 if op in REGS32 and zero_extending: |
| 428 if not postcondition.Implies(Condition()): | 429 if not postcondition.Implies(Condition()): |
| 429 raise SandboxingError( | 430 raise SandboxingError( |
| 430 '%s when zero-extending %s' | 431 '%s when zero-extending %s' |
| 431 % (postcondition.WhyNotImplies(Condition()), op), | 432 % (postcondition.WhyNotImplies(Condition()), op), |
| 432 instruction) | 433 instruction) |
| 433 | 434 |
| 434 r = REG32_TO_REG64[op] | 435 r = REG32_TO_REG64[op] |
| 435 if r in ['%rbp', '%rsp']: | 436 if r in ['%rbp', '%rsp']: |
| 436 postcondition = Condition(restricted_instead_of_sandboxed=r) | 437 postcondition = Condition(restricted_instead_of_sandboxed=r) |
| 437 else: | 438 else: |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 'segments in memory references are not allowed', instruction) | 505 'segments in memory references are not allowed', instruction) |
| 505 | 506 |
| 506 if bitness == 32: | 507 if bitness == 32: |
| 507 if _InstructionNameIn( | 508 if _InstructionNameIn( |
| 508 name, | 509 name, |
| 509 ['mov', # including MOVD | 510 ['mov', # including MOVD |
| 510 'add', 'sub', 'and', 'or', 'xor', | 511 'add', 'sub', 'and', 'or', 'xor', |
| 511 'xchg', 'xadd', | 512 'xchg', 'xadd', |
| 512 'inc', 'dec', 'neg', 'not', | 513 'inc', 'dec', 'neg', 'not', |
| 513 'lea', | 514 'lea', |
| 515 'adc', 'bsf', 'bsr', 'lzcnt', |
| 516 'btc', 'btr', 'bts', 'bt', |
| 517 'cmp', |
| 518 'cmc', |
| 514 ]): | 519 ]): |
| 515 return Condition(), Condition() | 520 return Condition(), Condition() |
| 516 elif re.match(r'mov[sz][bwl][lqw]$', name): # MOVSX, MOVSXD, MOVZX | 521 elif re.match(r'mov[sz][bwl][lqw]$', name): # MOVSX, MOVSXD, MOVZX |
| 517 return Condition(), Condition() | 522 return Condition(), Condition() |
| 523 elif name == 'bswap': |
| 524 if ops[0] not in REGS32: |
| 525 raise SandboxingError( |
| 526 'bswap is only allowed with 32-bit operands', |
| 527 instruction) |
| 528 return Condition(), Condition() |
| 518 else: | 529 else: |
| 519 raise DoNotMatchError(instruction) | 530 raise DoNotMatchError(instruction) |
| 520 | 531 |
| 521 elif bitness == 64: | 532 elif bitness == 64: |
| 522 precondition = Condition() | 533 precondition = Condition() |
| 523 postcondition = Condition() | 534 postcondition = Condition() |
| 524 zero_extending = False | 535 zero_extending = False |
| 525 touches_memory = True | 536 touches_memory = True |
| 526 | 537 |
| 527 if _InstructionNameIn( | 538 if _InstructionNameIn( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 541 write_ops = ops | 552 write_ops = ops |
| 542 elif _InstructionNameIn(name, ['inc', 'dec', 'neg', 'not']): | 553 elif _InstructionNameIn(name, ['inc', 'dec', 'neg', 'not']): |
| 543 assert len(ops) == 1 | 554 assert len(ops) == 1 |
| 544 zero_extending = True | 555 zero_extending = True |
| 545 write_ops = ops | 556 write_ops = ops |
| 546 elif name == 'lea': | 557 elif name == 'lea': |
| 547 assert len(ops) == 2 | 558 assert len(ops) == 2 |
| 548 write_ops = [ops[1]] | 559 write_ops = [ops[1]] |
| 549 touches_memory = False | 560 touches_memory = False |
| 550 zero_extending = True | 561 zero_extending = True |
| 562 elif _InstructionNameIn( |
| 563 name, |
| 564 ['adc', 'bsf', 'bsr', 'lzcnt']): |
| 565 # Note: some versions of objdump (including one that is currently used |
| 566 # in targeted tests) decode 'tzcnt' as 'repz bsf' |
| 567 # (see validator_ragel/testdata/32/tzcnt.test) |
| 568 # From sandboxing point of view bsf and tzcnt are the same, so |
| 569 # we ignore this bug here. |
| 570 # Same applies to 32-bit version. |
| 571 assert len(ops) == 2 |
| 572 write_ops = [ops[1]] |
| 573 elif _InstructionNameIn(name, ['btc', 'btr', 'bts', 'bt']): |
| 574 assert len(ops) == 2 |
| 575 # bt* accept arbitrarily large bit offset when second |
| 576 # operand is memory and offset is in register. |
| 577 # Interestingly, when offset is immediate, it's taken modulo operand size, |
| 578 # even when second operand is memory. |
| 579 # Also, validator currently disallows |
| 580 # bt* <register>, <register> |
| 581 # which is techincally safe. We disallow it in spec as well for |
| 582 # simplicity. |
| 583 if not re.match(_ImmediateRE() + r'$', ops[0]): |
| 584 raise SandboxingError( |
| 585 'bt* is only allowed with immediate as bit offset', |
| 586 instruction) |
| 587 if _InstructionNameIn(name, ['bt']): |
| 588 write_ops = [] |
| 589 else: |
| 590 write_ops = [ops[1]] |
| 591 elif _InstructionNameIn(name, ['cmp']): |
| 592 assert len(ops) == 2 |
| 593 write_ops = [] |
| 594 elif name == 'bswap': |
| 595 assert len(ops) == 1 |
| 596 if ops[0] not in REGS32 + REGS64: |
| 597 raise SandboxingError( |
| 598 'bswap is only allowed with 32-bit and 64-bit operands', |
| 599 instruction) |
| 600 write_ops = ops |
| 601 elif _InstructionNameIn(name, ['cmc']): |
| 602 assert len(ops) == 0 |
| 603 write_ops = [] |
| 551 else: | 604 else: |
| 552 raise DoNotMatchError(instruction) | 605 raise DoNotMatchError(instruction) |
| 553 | 606 |
| 554 if touches_memory: | 607 if touches_memory: |
| 555 precondition = _ProcessMemoryAccess(instruction, ops) | 608 precondition = _ProcessMemoryAccess(instruction, ops) |
| 556 | 609 |
| 557 postcondition = _ProcessOperandWrites( | 610 postcondition = _ProcessOperandWrites( |
| 558 instruction, write_ops, zero_extending) | 611 instruction, write_ops, zero_extending) |
| 559 | 612 |
| 560 return precondition, postcondition | 613 return precondition, postcondition |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 raise DoNotMatchError(superinstruction) | 843 raise DoNotMatchError(superinstruction) |
| 791 if lea_r15_rsi_rsi.match(superinstruction[1].disasm) is None: | 844 if lea_r15_rsi_rsi.match(superinstruction[1].disasm) is None: |
| 792 raise DoNotMatchError(superinstruction) | 845 raise DoNotMatchError(superinstruction) |
| 793 if mov_edi_edi.match(superinstruction[2].disasm) is None: | 846 if mov_edi_edi.match(superinstruction[2].disasm) is None: |
| 794 raise DoNotMatchError(superinstruction) | 847 raise DoNotMatchError(superinstruction) |
| 795 if lea_r15_rdi_rdi.match(superinstruction[3].disasm) is None: | 848 if lea_r15_rdi_rdi.match(superinstruction[3].disasm) is None: |
| 796 raise DoNotMatchError(superinstruction) | 849 raise DoNotMatchError(superinstruction) |
| 797 return | 850 return |
| 798 | 851 |
| 799 raise DoNotMatchError(superinstruction) | 852 raise DoNotMatchError(superinstruction) |
| OLD | NEW |