# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging, time from autotest_lib.client.bin import test, utils from autotest_lib.client.common_lib import error from autotest_lib.client.cros.power import power_utils from autotest_lib.client.cros.power import sys_power MSR_POSITIVE = { # IA32_FEATURE_CONTROL[2:0] # 0 - Lock bit (1 = locked) # 1 - Enable VMX in SMX operation # 2 - Enable VMX outside SMX operation 'Atom': { # Some CPUs reporting as "Atom" have VMX enabled. }, 'Core M': { # Some CPUs reporting as "Core M" have VMX enabled. }, 'Core': { # Some CPUs reporting as "Core" have VMX enabled. }, 'Stoney': { # VM_CR MSR (C001_0114h) with SVMDIS Bit 4 # can be used to lock writes to EFER.SVME. # 0 - writes to EFER.SVME are not blocked # 1 - writes to EFER treat EFER.SVME as MBZ '0xc0010114': [('4', 0)], }, } MSR_NEGATIVE = { 'Atom': { # No board has all bits set so this should fail. '0x3a': [('2:0', 7)], }, 'Core M': { # No board has all bits set so this should fail. '0x3a': [('2:0', 7)], }, 'Core': { # No board has all bits set so this should fail. '0x3a': [('2:0', 7)], }, 'Stoney': { # Inverted from positive case: none of these bits should be set. '0xc0010114': [('4', 1)], }, } RCBA_POSITIVE = { 'Atom': { # GCS.BILD is not set on H2C UEFI Firmware. :( # https://code.google.com/p/chromium/issues/detail?id=269633 '0x3410': [('0', 0)], }, 'Core M': { # GCS (General Control and Status) register, BILD (BIOS Interface # Lock-Down) bit should be set. '0x3410': [('0', 1)], }, 'Core': { # GCS (General Control and Status) register, BILD (BIOS Interface # Lock-Down) bit should be set. '0x3410': [('0', 1)], }, 'Stoney': { # Skipping this test as there is no register to change # reset vector on Stoney. NA for Stoney. }, } RCBA_NEGATIVE = { 'Atom': { # GCS register, BILD bit inverted from positive test. '0x3410': [('0', 1)], }, 'Core M': { # GCS register, BILD bit inverted from positive test. '0x3410': [('0', 0)], }, 'Core': { # GCS register, BILD bit inverted from positive test. '0x3410': [('0', 0)], }, 'Stoney': { }, } class security_x86Registers(test.test): """ Checks various CPU and firmware registers for security-sensitive safe settings. """ version = 1 def _check_negative_positive(self, name, func, match_neg, match_pos): errors = 0 # Catch missing test conditions. if len(match_neg) == 0: logging.debug('No inverted %s tests defined!', name) if len(match_pos) == 0: logging.debug('No positive %s tests defined!', name) if len(match_neg) == 0 or len(match_pos) == 0: return errors # Negative tests; make sure infrastructure is working. logging.debug("=== BEGIN [expecting %s FAILs] ===", name) if func(match_neg) == 0: logging.error('BAD: inverted %s tests did not fail!', name) errors += 1 logging.debug("=== END [expecting %s FAILs] ===", name) # Positive tests; make sure values are for real. logging.debug("=== BEGIN [expecting %s oks] ===", name) errors += func(match_pos) logging.debug("=== END [expecting %s oks] ===", name) logging.debug("%s errors found: %d", name, errors) return errors def _check_msr(self): return self._check_negative_positive('MSR', self._registers.verify_msr, MSR_NEGATIVE[self._cpu_type], MSR_POSITIVE[self._cpu_type]) def _check_bios(self): return self._check_negative_positive('BIOS', self._registers.verify_rcba, RCBA_NEGATIVE[self._cpu_type], RCBA_POSITIVE[self._cpu_type]) def _check_all(self): errors = 0 errors += self._check_msr() errors += self._check_bios() return errors def run_once(self): errors = 0 cpu_arch = power_utils.get_x86_cpu_arch() if not cpu_arch: cpu_arch = utils.get_cpu_arch() if cpu_arch == "arm": logging.info('OK: skipping x86-only test on %s.', cpu_arch) return raise error.TestNAError('Unknown CPU with arch "%s".' % (cpu_arch)) if cpu_arch == 'Stoney': self._cpu_type = 'Stoney' elif cpu_arch == 'Atom': self._cpu_type = 'Atom' elif cpu_arch == 'Core M': self._cpu_type = 'Core M' else: self._cpu_type = 'Core' self._registers = power_utils.Registers() # Check running machine. errors += self._check_all() # Pause briefly to make sure the RTC is ready for suspend/resume. time.sleep(3) # Suspend the system to RAM and return after 10 seconds. sys_power.do_suspend(10) # Check resumed machine. errors += self._check_all() if errors > 0: raise error.TestFail('x86 register mismatch detected')