Home | History | Annotate | Download | only in security_x86Registers
      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