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