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