1# Copyright (c) 2011 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, os 6from autotest_lib.client.bin import test, utils 7from autotest_lib.client.common_lib import error 8from autotest_lib.client.cros import kernel_config 9 10class kernel_ConfigVerify(test.test): 11 """Examine a kernel build CONFIG list to make sure various things are 12 present, missing, built as modules, etc. 13 """ 14 version = 1 15 IS_BUILTIN = [ 16 # Sanity checks; should be present in builds as builtins. 17 'INET', 18 'MMU', 19 'MODULES', 20 'PRINTK', 21 'SECURITY', 22 # Security; adds stack buffer overflow protections. 23 'CC_STACKPROTECTOR', 24 # Security; enables the SECCOMP application API. 25 'SECCOMP', 26 # Security; blocks direct physical memory access. 27 'STRICT_DEVMEM', 28 # Security; provides some protections against SYN flooding. 29 'SYN_COOKIES', 30 # Security; make sure PID_NS, NET_NS, and USER_NS are enabled for 31 # chrome's layer 1 sandbox. 32 'PID_NS', 33 'NET_NS', 34 'USER_NS', 35 # Security; perform additional validation of credentials. 36 'DEBUG_CREDENTIALS', 37 # Security; make sure the Chrome OS LSM is in use. 38 'SECURITY_CHROMIUMOS', 39 ] 40 IS_MODULE = [ 41 # Sanity checks; should be present in builds as modules. 42 'BLK_DEV_SR', 43 'BT', 44 'TUN', 45 # Useful modules for users that should not be removed 46 'USB_SERIAL_OTI6858', 47 ] 48 IS_ENABLED = [ 49 # Either module or enabled, depending on platform. 50 'VIDEO_V4L2', 51 ] 52 IS_MISSING = [ 53 # Sanity checks. 54 'M386', # Never going to optimize to this CPU. 55 'CHARLIE_THE_UNICORN', # Config not in real kernel config var list. 56 # Dangerous; allows direct physical memory writing. 57 'ACPI_CUSTOM_METHOD', 58 # Dangerous; disables brk ASLR. 59 'COMPAT_BRK', 60 # Dangerous; disables VDSO ASLR. 61 'COMPAT_VDSO', 62 # Dangerous; allows direct kernel memory writing. 63 'DEVKMEM', 64 # Dangerous; allows replacement of running kernel. 65 'KEXEC', 66 # Dangerous; allows replacement of running kernel. 67 'HIBERNATION', 68 # Assists heap memory attacks; best to keep interface disabled. 69 'INET_DIAG', 70 ] 71 IS_EXCLUSIVE = [ 72 # Security; no surprise binary formats. 73 { 74 'regex': 'BINFMT_', 75 'builtin': [ 76 'BINFMT_ELF', 77 ], 78 'module': [ 79 ], 80 'missing': [ 81 # Sanity checks; one disabled, one does not exist. 82 'BINFMT_MISC', 83 'BINFMT_IMPOSSIBLE', 84 ], 85 }, 86 # Security; no surprise filesystem formats. 87 { 88 'regex': '.*_FS$', 89 'builtin': [ 90 'DEBUG_FS', 91 'ECRYPT_FS', 92 'EXT4_FS', 93 'EXT4_USE_FOR_EXT23', 94 'PROC_FS', 95 'SCSI_PROC_FS', 96 ], 97 'module': [ 98 'FAT_FS', 99 'FUSE_FS', 100 'HFSPLUS_FS', 101 'ISO9660_FS', 102 'UDF_FS', 103 'VFAT_FS', 104 ], 105 'missing': [ 106 # Sanity checks; one disabled, one does not exist. 107 'EXT2_FS', 108 'EXT3_FS', 109 'XFS_FS', 110 'IMPOSSIBLE_FS', 111 ], 112 }, 113 # Security; no surprise partition formats. 114 # MAC is for external drive formatted on Macintosh. 115 { 116 'regex': '.*_PARTITION$', 117 'builtin': [ 118 'EFI_PARTITION', 119 'MAC_PARTITION', 120 'MSDOS_PARTITION', 121 ], 122 'module': [ 123 ], 124 'missing': [ 125 # Sanity checks; one disabled, one does not exist. 126 'LDM_PARTITION', 127 'IMPOSSIBLE_PARTITION', 128 ], 129 }, 130 ] 131 132 def is_arm_family(self, arch): 133 return arch in ['armv7l', 'aarch64'] 134 135 def is_x86_family(self, arch): 136 return arch in ['i386', 'x86_64'] 137 138 def run_once(self): 139 # Cache the architecture to avoid redundant execs to "uname". 140 arch = utils.get_arch() 141 userspace_arch = utils.get_arch_userspace() 142 143 # Report the full uname for anyone reading logs. 144 logging.info('Running %s kernel, %s userspace: %s', 145 arch, userspace_arch, 146 utils.system_output('uname -a')) 147 148 # Load the list of kernel config variables. 149 config = kernel_config.KernelConfig() 150 config.initialize() 151 152 # Adjust for kernel-version-specific changes 153 kernel_ver = os.uname()[2] 154 if utils.compare_versions(kernel_ver, "3.10") >= 0: 155 for entry in self.IS_EXCLUSIVE: 156 if entry['regex'] == 'BINFMT_': 157 entry['builtin'].append('BINFMT_SCRIPT') 158 159 if utils.compare_versions(kernel_ver, "3.14") >= 0: 160 self.IS_MODULE.append('TEST_ASYNC_DRIVER_PROBE') 161 162 if utils.compare_versions(kernel_ver, "3.18") >= 0: 163 for entry in self.IS_EXCLUSIVE: 164 if entry['regex'] == '.*_FS$': 165 entry['builtin'].append('SND_PROC_FS') 166 167 # Run the static checks. 168 map(config.has_builtin, self.IS_BUILTIN) 169 map(config.has_module, self.IS_MODULE) 170 map(config.is_enabled, self.IS_ENABLED) 171 map(config.is_missing, self.IS_MISSING) 172 map(config.is_exclusive, self.IS_EXCLUSIVE) 173 174 # Run the dynamic checks. 175 176 # Security; NULL-address hole should be as large as possible. 177 # Upstream kernel recommends 64k, which should be large enough to 178 # catch nearly all dereferenced structures. 179 wanted = '65536' 180 if self.is_arm_family(arch): 181 # ... except on ARM where it shouldn't be larger than 32k due 182 # to historical ELF load location. 183 wanted = '32768' 184 config.has_value('DEFAULT_MMAP_MIN_ADDR', [wanted]) 185 186 # Security; make sure NX page table bits are usable. 187 if self.is_x86_family(arch): 188 if arch == "i386": 189 config.has_builtin('X86_PAE') 190 else: 191 config.has_builtin('X86_64') 192 193 # Security; marks data segments as RO/NX, text as RO. 194 if (arch == 'armv7l' and 195 utils.compare_versions(kernel_ver, "3.8") < 0): 196 config.is_missing('DEBUG_RODATA') 197 config.is_missing('DEBUG_SET_MODULE_RONX') 198 else: 199 config.has_builtin('DEBUG_RODATA') 200 config.has_builtin('DEBUG_SET_MODULE_RONX') 201 202 if arch == 'aarch64': 203 config.has_builtin('DEBUG_ALIGN_RODATA') 204 205 # NaCl; allow mprotect+PROT_EXEC on noexec mapped files. 206 config.has_value('MMAP_NOEXEC_TAINT', ['0']) 207 208 # Kernel: make sure port 0xED is the one used for I/O delay 209 if self.is_x86_family(arch): 210 config.has_builtin('IO_DELAY_0XED') 211 needed = config.get('CONFIG_IO_DELAY_TYPE_0XED', None) 212 config.has_value('DEFAULT_IO_DELAY_TYPE', [needed]) 213 214 # Raise a failure if anything unexpected was seen. 215 if len(config.failures()): 216 raise error.TestFail((", ".join(config.failures()))) 217