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 5 import logging, os 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 kernel_config 9 10 class 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(2) 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 # We don't need to provide access to *all* symbols in /proc/kallsyms. 71 'KALLSYMS_ALL', 72 # bpf(2) syscall can be used to generate code patterns in kernel memory. 73 'BPF_SYSCALL', 74 # This callback can be subverted to point to arbitrary programs. We 75 # require firmware to be in the rootfs at normal locations which lets 76 # the kernel locate things itself. 77 'FW_LOADER_USER_HELPER', 78 'FW_LOADER_USER_HELPER_FALLBACK', 79 ] 80 IS_EXCLUSIVE = [ 81 # Security; no surprise binary formats. 82 { 83 'regex': 'BINFMT_', 84 'builtin': [ 85 'BINFMT_ELF', 86 ], 87 'module': [ 88 ], 89 'missing': [ 90 # Sanity checks; one disabled, one does not exist. 91 'BINFMT_AOUT', 92 'BINFMT_IMPOSSIBLE', 93 ], 94 }, 95 # Security; no surprise filesystem formats. 96 { 97 'regex': '.*_FS$', 98 'builtin': [ 99 'DEBUG_FS', 100 'ECRYPT_FS', 101 'EXT4_FS', 102 'PROC_FS', 103 'SCSI_PROC_FS', 104 ], 105 'module': [ 106 'FAT_FS', 107 'FUSE_FS', 108 'HFSPLUS_FS', 109 'ISO9660_FS', 110 'UDF_FS', 111 'VFAT_FS', 112 ], 113 'missing': [ 114 # Sanity checks; one disabled, one does not exist. 115 'EXT2_FS', 116 'EXT3_FS', 117 'XFS_FS', 118 'IMPOSSIBLE_FS', 119 ], 120 }, 121 # Security; no surprise partition formats. 122 # MAC is for external drive formatted on Macintosh. 123 { 124 'regex': '.*_PARTITION$', 125 'builtin': [ 126 'EFI_PARTITION', 127 'MAC_PARTITION', 128 'MSDOS_PARTITION', 129 ], 130 'module': [ 131 ], 132 'missing': [ 133 # Sanity checks; one disabled, one does not exist. 134 'LDM_PARTITION', 135 'IMPOSSIBLE_PARTITION', 136 ], 137 }, 138 ] 139 140 def is_x86_family(self, arch): 141 """ 142 Returns true if the architecture is x86 family. 143 """ 144 return arch in ['i386', 'x86_64'] 145 146 def run_once(self): 147 """ 148 The actual test. 149 """ 150 # Cache the architecture to avoid redundant execs to "uname". 151 arch = utils.get_arch() 152 userspace_arch = utils.get_arch_userspace() 153 154 # Report the full uname for anyone reading logs. 155 logging.info('Running %s kernel, %s userspace: %s', 156 arch, userspace_arch, 157 utils.system_output('uname -a')) 158 159 # Load the list of kernel config variables. 160 config = kernel_config.KernelConfig() 161 config.initialize() 162 163 # Adjust for kernel-version-specific changes 164 kernel_ver = os.uname()[2] 165 if utils.compare_versions(kernel_ver, "3.10") >= 0: 166 for entry in self.IS_EXCLUSIVE: 167 if entry['regex'] == 'BINFMT_': 168 entry['builtin'].append('BINFMT_SCRIPT') 169 170 if utils.compare_versions(kernel_ver, "3.14") >= 0: 171 self.IS_MODULE.append('TEST_ASYNC_DRIVER_PROBE') 172 for entry in self.IS_EXCLUSIVE: 173 if entry['regex'] == 'BINFMT_': 174 entry['builtin'].append('BINFMT_MISC') 175 if entry['regex'] == '.*_FS$': 176 entry['module'].append('NFS_FS') 177 178 if utils.compare_versions(kernel_ver, "3.18") >= 0: 179 for entry in self.IS_EXCLUSIVE: 180 if entry['regex'] == '.*_FS$': 181 entry['builtin'].append('SND_PROC_FS') 182 183 if utils.compare_versions(kernel_ver, "4.4") < 0: 184 for entry in self.IS_EXCLUSIVE: 185 if entry['regex'] == '.*_FS$': 186 entry['builtin'].append('EXT4_USE_FOR_EXT23') 187 188 if utils.compare_versions(kernel_ver, "4.4") >= 0 and \ 189 utils.compare_versions(kernel_ver, "4.12") < 0: 190 for entry in self.IS_EXCLUSIVE: 191 if entry['regex'] == '.*_FS$': 192 entry['builtin'].append('ESD_FS') 193 entry['builtin'].append('CONFIGFS_FS') 194 195 if utils.compare_versions(kernel_ver, "3.14") >= 0: 196 self.IS_MISSING.remove('INET_DIAG') 197 198 # Run the static checks. 199 map(config.has_builtin, self.IS_BUILTIN) 200 map(config.has_module, self.IS_MODULE) 201 map(config.is_enabled, self.IS_ENABLED) 202 map(config.is_missing, self.IS_MISSING) 203 map(config.is_exclusive, self.IS_EXCLUSIVE) 204 205 # Run the dynamic checks. 206 207 # Security; NULL-address hole should be as large as possible. 208 # Upstream kernel recommends 64k, which should be large enough 209 # to catch nearly all dereferenced structures. For 210 # compatibility with ARM binaries (even on x86) this needs to 211 # be 32k. 212 wanted = '32768' 213 config.has_value('DEFAULT_MMAP_MIN_ADDR', [wanted]) 214 215 # Security; make sure NX page table bits are usable. 216 if self.is_x86_family(arch): 217 if arch == "i386": 218 config.has_builtin('X86_PAE') 219 else: 220 config.has_builtin('X86_64') 221 222 # Security; marks data segments as RO/NX, text as RO. 223 if utils.compare_versions(kernel_ver, "4.11") < 0: 224 config.has_builtin('DEBUG_RODATA') 225 config.has_builtin('DEBUG_SET_MODULE_RONX') 226 else: 227 config.has_builtin('STRICT_KERNEL_RWX') 228 config.has_builtin('STRICT_MODULE_RWX') 229 230 if arch == 'aarch64': 231 config.has_builtin('DEBUG_ALIGN_RODATA') 232 233 # NaCl; allow mprotect+PROT_EXEC on noexec mapped files. 234 config.has_value('MMAP_NOEXEC_TAINT', ['0']) 235 236 # Kernel: make sure port 0xED is the one used for I/O delay. 237 if self.is_x86_family(arch): 238 config.has_builtin('IO_DELAY_0XED') 239 needed = config.get('CONFIG_IO_DELAY_TYPE_0XED', None) 240 config.has_value('DEFAULT_IO_DELAY_TYPE', [needed]) 241 242 # Raise a failure if anything unexpected was seen. 243 if len(config.failures()): 244 raise error.TestFail((", ".join(config.failures()))) 245