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