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 import power_utils 9 from autotest_lib.client.cros 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 } 25 26 MSR_NEGATIVE = { 27 'Atom': { 28 # Inverted from positive case: none of these bits should be set. 29 '0x3a': [('2:0', 6)], 30 }, 31 'Non-Atom': { 32 # Inverted from positive case: none of these bits should be set. 33 '0x3a': [('2:0', 6)], 34 }, 35 } 36 37 RCBA_POSITIVE = { 38 'Atom': { 39 # GCS.BILD is not set on H2C UEFI Firmware. :( 40 # https://code.google.com/p/chromium/issues/detail?id=269633 41 '0x3410': [('0', 0)], 42 }, 43 'Non-Atom': { 44 # GCS (General Control and Status) register, BILD (BIOS Interface 45 # Lock-Down) bit should be set. 46 '0x3410': [('0', 1)], 47 }, 48 } 49 50 RCBA_NEGATIVE = { 51 'Atom': { 52 # GCS register, BILD bit inverted from positive test. 53 '0x3410': [('0', 1)], 54 }, 55 'Non-Atom': { 56 # GCS register, BILD bit inverted from positive test. 57 '0x3410': [('0', 0)], 58 }, 59 } 60 61 class security_x86Registers(test.test): 62 """ 63 Checks various CPU and firmware registers for security-sensitive safe 64 settings. 65 """ 66 version = 1 67 68 def _check_negative_positive(self, name, func, match_neg, match_pos): 69 errors = 0 70 71 # Catch missing test conditions. 72 if len(match_neg) == 0: 73 logging.error('BAD: no inverted %s tests defined!', name) 74 if len(match_pos) == 0: 75 logging.error('BAD: no positive %s tests defined!', name) 76 77 # Negative tests; make sure infrastructure is working. 78 logging.debug("=== BEGIN [expecting %s FAILs] ===", name) 79 if func(match_neg) == 0: 80 logging.error('BAD: inverted %s tests did not fail!', name) 81 errors += 1 82 logging.debug("=== END [expecting %s FAILs] ===", name) 83 84 # Positive tests; make sure values are for real. 85 logging.debug("=== BEGIN [expecting %s oks] ===", name) 86 errors += func(match_pos) 87 logging.debug("=== END [expecting %s oks] ===", name) 88 89 logging.debug("%s errors found: %d", name, errors) 90 return errors 91 92 def _check_msr(self): 93 return self._check_negative_positive('MSR', 94 self._registers.verify_msr, 95 MSR_NEGATIVE[self._cpu_type], 96 MSR_POSITIVE[self._cpu_type]) 97 98 def _check_bios(self): 99 return self._check_negative_positive('BIOS', 100 self._registers.verify_rcba, 101 RCBA_NEGATIVE[self._cpu_type], 102 RCBA_POSITIVE[self._cpu_type]) 103 104 def _check_all(self): 105 errors = 0 106 errors += self._check_msr() 107 errors += self._check_bios() 108 return errors 109 110 def run_once(self): 111 errors = 0 112 113 cpu_arch = power_utils.get_x86_cpu_arch() 114 if not cpu_arch: 115 cpu_arch = utils.get_cpu_arch() 116 if cpu_arch == "arm": 117 logging.debug('ok: skipping x86-only test on %s.', cpu_arch) 118 return 119 raise error.TestNAError('Unsupported CPU: %s' % (cpu_arch)) 120 121 self._cpu_type = 'Atom' 122 if cpu_arch is not 'Atom': 123 self._cpu_type = 'Non-Atom' 124 125 self._registers = power_utils.Registers() 126 127 # Check running machine. 128 errors += self._check_all() 129 130 # Pause briefly to make sure the RTC is ready for suspend/resume. 131 time.sleep(3) 132 # Suspend the system to RAM and return after 10 seconds. 133 sys_power.do_suspend(10) 134 135 # Check resumed machine. 136 errors += self._check_all() 137 138 if errors > 0: 139 raise error.TestFail("x86 register mismatch detected") 140