• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import power_utils
9from autotest_lib.client.cros import sys_power
10
11MSR_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
26MSR_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
37RCBA_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
50RCBA_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
61class 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