1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import logging, time 6 from autotest_lib.client.bin import test, utils 7 from autotest_lib.client.common_lib import error 8 from autotest_lib.client.cros.power import power_utils 9 from autotest_lib.client.cros.power import sys_power 10 11 MSR_POSITIVE = { 12 'Atom': { 13 # VMX does not exist on Atom (so it reports as disabled). 14 '0x3a': [('2:0', 1)], 15 }, 16 'Non-Atom': { 17 # IA32_FEATURE_CONTROL[2:0] 18 # 0 - Lock bit (1 = locked) 19 # 1 - Enable VMX in SMX operation 20 # 2 - Enable VMX outside SMX operation 21 # Want value "1": VMX locked and disabled in all modes. 22 '0x3a': [('2:0', 1)], 23 }, 24 'Stoney': { 25 # VM_CR MSR (C001_0114h) with SVMDIS Bit 4 26 # can be used to lock writes to EFER.SVME 27 # 0 - writes to EFER.SVME are not blocked 28 # 1 - writes to EFER treat EFER.SVME as MBZ 29 '0xc0010114': [('4', 0)], 30 }, 31 } 32 33 MSR_NEGATIVE = { 34 'Atom': { 35 # Inverted from positive case: none of these bits should be set. 36 '0x3a': [('2:0', 6)], 37 }, 38 'Non-Atom': { 39 # Inverted from positive case: none of these bits should be set. 40 '0x3a': [('2:0', 6)], 41 }, 42 'Stoney': { 43 # Inverted from positive case: none of these bits should be set. 44 '0xc0010114': [('4', 1)], 45 }, 46 } 47 48 RCBA_POSITIVE = { 49 'Atom': { 50 # GCS.BILD is not set on H2C UEFI Firmware. :( 51 # https://code.google.com/p/chromium/issues/detail?id=269633 52 '0x3410': [('0', 0)], 53 }, 54 'Non-Atom': { 55 # GCS (General Control and Status) register, BILD (BIOS Interface 56 # Lock-Down) bit should be set. 57 '0x3410': [('0', 1)], 58 }, 59 'Stoney': { 60 # Skipping this test as there is no register to change 61 # reset vector on Stoney. NA for Stoney. 62 }, 63 } 64 65 RCBA_NEGATIVE = { 66 'Atom': { 67 # GCS register, BILD bit inverted from positive test. 68 '0x3410': [('0', 1)], 69 }, 70 'Non-Atom': { 71 # GCS register, BILD bit inverted from positive test. 72 '0x3410': [('0', 0)], 73 }, 74 'Stoney': { 75 }, 76 } 77 78 class security_x86Registers(test.test): 79 """ 80 Checks various CPU and firmware registers for security-sensitive safe 81 settings. 82 """ 83 version = 1 84 85 def _check_negative_positive(self, name, func, match_neg, match_pos): 86 errors = 0 87 88 # Catch missing test conditions. 89 if len(match_neg) == 0: 90 logging.debug('No inverted %s tests defined!', name) 91 if len(match_pos) == 0: 92 logging.debug('No positive %s tests defined!', name) 93 if len(match_neg) == 0 or len(match_pos) == 0: 94 return errors 95 96 # Negative tests; make sure infrastructure is working. 97 logging.debug("=== BEGIN [expecting %s FAILs] ===", name) 98 if func(match_neg) == 0: 99 logging.error('BAD: inverted %s tests did not fail!', name) 100 errors += 1 101 logging.debug("=== END [expecting %s FAILs] ===", name) 102 103 # Positive tests; make sure values are for real. 104 logging.debug("=== BEGIN [expecting %s oks] ===", name) 105 errors += func(match_pos) 106 logging.debug("=== END [expecting %s oks] ===", name) 107 108 logging.debug("%s errors found: %d", name, errors) 109 return errors 110 111 def _check_msr(self): 112 return self._check_negative_positive('MSR', 113 self._registers.verify_msr, 114 MSR_NEGATIVE[self._cpu_type], 115 MSR_POSITIVE[self._cpu_type]) 116 117 def _check_bios(self): 118 return self._check_negative_positive('BIOS', 119 self._registers.verify_rcba, 120 RCBA_NEGATIVE[self._cpu_type], 121 RCBA_POSITIVE[self._cpu_type]) 122 123 def _check_all(self): 124 errors = 0 125 errors += self._check_msr() 126 errors += self._check_bios() 127 return errors 128 129 def run_once(self): 130 errors = 0 131 132 cpu_arch = power_utils.get_x86_cpu_arch() 133 if not cpu_arch: 134 cpu_arch = utils.get_cpu_arch() 135 if cpu_arch == "arm": 136 logging.info('OK: skipping x86-only test on %s.', cpu_arch) 137 return 138 raise error.TestNAError('Unknown CPU with arch "%s".' % (cpu_arch)) 139 140 if cpu_arch == 'Stoney': 141 self._cpu_type = 'Stoney' 142 elif cpu_arch == 'Atom': 143 self._cpu_type = 'Atom' 144 else: 145 self._cpu_type = 'Non-Atom' 146 147 self._registers = power_utils.Registers() 148 149 # Check running machine. 150 errors += self._check_all() 151 152 # Pause briefly to make sure the RTC is ready for suspend/resume. 153 time.sleep(3) 154 # Suspend the system to RAM and return after 10 seconds. 155 sys_power.do_suspend(10) 156 157 # Check resumed machine. 158 errors += self._check_all() 159 160 if errors > 0: 161 raise error.TestFail('x86 register mismatch detected') 162