def setup(self): """ Test setup. """ self.arch = utils.get_arch() self.userspace_arch = utils.get_arch_userspace() # Report the full uname for anyone reading logs. logging.info('Running %s kernel, %s userspace: %s', self.arch, self.userspace_arch, utils.system_output('uname -a'))
def verify_file(self, name): """ Does sanity checks on a file on disk. @param name: filename to verify. """ if not os.path.exists(name): raise error.TestFail('Failed: File does not exist %s' % name) if not os.path.isfile(name): raise error.TestFail('Failed: Not a file %s' % name) if os.path.getsize(name) <= 0: raise error.TestFail('Failed: File is too short %s' % name) if name.endswith('libpepflashplayer.so'): output = subprocess.check_output(['file %s' % name], shell=True) if not 'stripped' in output: logging.error(output) raise error.TestFail('Failed: Flash binary not stripped.') if not 'dynamically linked' in output: logging.error(output) raise error.TestFail('Failed: Flash not dynamically linked.') arch = utils.get_arch_userspace() logging.info('get_arch_userspace = %s', arch) if arch == 'arm' and not 'ARM' in output: logging.error(output) raise error.TestFail('Failed: Flash binary not for ARM.') if arch == 'x86_64' and not 'x86-64' in output: logging.error(output) raise error.TestFail('Failed: Flash binary not for x86_64.') if arch == 'i386' and not '80386' in output: logging.error(output) raise error.TestFail('Failed: Flash binary not for i386.') logging.info('Verified file %s', name)
def run_once(self): # Cache the architecture to avoid redundant execs to "uname". arch = utils.get_arch() userspace_arch = utils.get_arch_userspace() # Report the full uname for anyone reading logs. logging.info('Running %s kernel, %s userspace: %s', arch, userspace_arch, utils.system_output('uname -a')) # Load the list of kernel config variables. config = kernel_config.KernelConfig() config.initialize() # Adjust for kernel-version-specific changes kernel_ver = os.uname()[2] if utils.compare_versions(kernel_ver, "3.10") >= 0: for entry in self.IS_EXCLUSIVE: if entry['regex'] == 'BINFMT_': entry['builtin'].append('BINFMT_SCRIPT') if utils.compare_versions(kernel_ver, "3.14") >= 0: self.IS_MODULE.append('TEST_ASYNC_DRIVER_PROBE') for entry in self.IS_EXCLUSIVE: if entry['regex'] == 'BINFMT_': entry['builtin'].append('BINFMT_MISC') if utils.compare_versions(kernel_ver, "3.18") >= 0: for entry in self.IS_EXCLUSIVE: if entry['regex'] == '.*_FS$': entry['builtin'].append('SND_PROC_FS') if utils.compare_versions(kernel_ver, "4.4") < 0: for entry in self.IS_EXCLUSIVE: if entry['regex'] == '.*_FS$': entry['builtin'].append('EXT4_USE_FOR_EXT23') # Run the static checks. map(config.has_builtin, self.IS_BUILTIN) map(config.has_module, self.IS_MODULE) map(config.is_enabled, self.IS_ENABLED) map(config.is_missing, self.IS_MISSING) map(config.is_exclusive, self.IS_EXCLUSIVE) # Run the dynamic checks. # Security; NULL-address hole should be as large as possible. # Upstream kernel recommends 64k, which should be large enough to # catch nearly all dereferenced structures. wanted = '65536' if self.is_arm_family(arch): # ... except on ARM where it shouldn't be larger than 32k due # to historical ELF load location. wanted = '32768' config.has_value('DEFAULT_MMAP_MIN_ADDR', [wanted]) # Security; make sure NX page table bits are usable. if self.is_x86_family(arch): if arch == "i386": config.has_builtin('X86_PAE') else: config.has_builtin('X86_64') # Security; marks data segments as RO/NX, text as RO. if (arch == 'armv7l' and utils.compare_versions(kernel_ver, "3.8") < 0): config.is_missing('DEBUG_RODATA') config.is_missing('DEBUG_SET_MODULE_RONX') else: config.has_builtin('DEBUG_RODATA') config.has_builtin('DEBUG_SET_MODULE_RONX') if arch == 'aarch64': config.has_builtin('DEBUG_ALIGN_RODATA') # NaCl; allow mprotect+PROT_EXEC on noexec mapped files. config.has_value('MMAP_NOEXEC_TAINT', ['0']) # Kernel: make sure port 0xED is the one used for I/O delay if self.is_x86_family(arch): config.has_builtin('IO_DELAY_0XED') needed = config.get('CONFIG_IO_DELAY_TYPE_0XED', None) config.has_value('DEFAULT_IO_DELAY_TYPE', [needed]) # Raise a failure if anything unexpected was seen. if len(config.failures()): raise error.TestFail((", ".join(config.failures())))
def run_once(self): """ The actual test. """ # Cache the architecture to avoid redundant execs to "uname". arch = utils.get_arch() userspace_arch = utils.get_arch_userspace() # Report the full uname for anyone reading logs. logging.info('Running %s kernel, %s userspace: %s', arch, userspace_arch, utils.system_output('uname -a')) # Load the list of kernel config variables. config = kernel_config.KernelConfig() config.initialize(missing_ok=self.MISSING_OK) # Adjust for kernel-version-specific changes kernel_ver = os.uname()[2] # For linux-3.10 or newer. if utils.compare_versions(kernel_ver, "3.10") >= 0: for entry in self.IS_EXCLUSIVE: if entry['regex'] == 'BINFMT_': entry['builtin'].append('BINFMT_SCRIPT') # For linux-3.14 or newer. if utils.compare_versions(kernel_ver, "3.14") >= 0: self.IS_MODULE.append('TEST_ASYNC_DRIVER_PROBE') self.IS_MISSING.remove('INET_DIAG') for entry in self.IS_EXCLUSIVE: if entry['regex'] == 'BINFMT_': entry['builtin'].append('BINFMT_MISC') if entry['regex'] == '.*_FS$': entry['module'].append('NFS_FS') # For linux-3.18 or newer. if utils.compare_versions(kernel_ver, "3.18") >= 0: for entry in self.IS_EXCLUSIVE: if entry['regex'] == '.*_FS$': entry['builtin'].append('SND_PROC_FS') entry['builtin'].append('USB_CONFIGFS_F_FS') entry['builtin'].append('ESD_FS') entry['enabled'].append('CONFIGFS_FS') entry['module'].append('USB_F_FS') # Like FW_LOADER_USER_HELPER, these may be exploited by userspace. # We run udev everywhere which uses netlink sockets for event # propagation rather than executing programs, so don't need this. self.IS_MISSING.append('UEVENT_HELPER') self.IS_MISSING.append('UEVENT_HELPER_PATH') # For kernels older than linux-4.4. if utils.compare_versions(kernel_ver, "4.4") < 0: for entry in self.IS_EXCLUSIVE: if entry['regex'] == '.*_FS$': entry['builtin'].append('EXT4_USE_FOR_EXT23') # For linux-4.4 or newer. if utils.compare_versions(kernel_ver, '4.4') >= 0: self.IS_BUILTIN.append('STATIC_USERMODEHELPER') # For linux-4.19 or newer. if utils.compare_versions(kernel_ver, "4.19") >= 0: self.IS_MISSING.remove('BPF_SYSCALL') self.IS_BUILTIN.append('HAVE_EBPF_JIT') self.IS_BUILTIN.append('BPF_JIT_ALWAYS_ON') self.IS_BUILTIN.remove('CC_STACKPROTECTOR') self.IS_BUILTIN.append('STACKPROTECTOR') # Run the static checks. map(config.has_builtin, self.IS_BUILTIN) map(config.has_module, self.IS_MODULE) map(config.is_enabled, self.IS_ENABLED) map(config.is_missing, self.IS_MISSING) map(config.is_exclusive, self.IS_EXCLUSIVE) # Run the dynamic checks. # Security; NULL-address hole should be as large as possible. # Upstream kernel recommends 64k, which should be large enough # to catch nearly all dereferenced structures. For # compatibility with ARM binaries (even on x86) this needs to # be 32k. wanted = '32768' config.has_value('DEFAULT_MMAP_MIN_ADDR', [wanted]) # Security; make sure usermode helper is our tool for linux-4.4+. if utils.compare_versions(kernel_ver, '4.4') >= 0: wanted = '"/sbin/usermode-helper"' config.has_value('STATIC_USERMODEHELPER_PATH', [wanted]) # Security; make sure NX page table bits are usable. if self.is_x86_family(arch): if arch == "i386": config.has_builtin('X86_PAE') else: config.has_builtin('X86_64') # Security; marks data segments as RO/NX, text as RO. if utils.compare_versions(kernel_ver, "4.11") < 0: config.has_builtin('DEBUG_RODATA') config.has_builtin('DEBUG_SET_MODULE_RONX') else: config.has_builtin('STRICT_KERNEL_RWX') config.has_builtin('STRICT_MODULE_RWX') if arch == 'aarch64': config.has_builtin('DEBUG_ALIGN_RODATA') # NaCl; allow mprotect+PROT_EXEC on noexec mapped files. config.has_value('MMAP_NOEXEC_TAINT', ['0']) # Kernel: make sure port 0xED is the one used for I/O delay. if self.is_x86_family(arch): config.has_builtin('IO_DELAY_0XED') needed = config.get('CONFIG_IO_DELAY_TYPE_0XED', None) config.has_value('DEFAULT_IO_DELAY_TYPE', [needed]) # Raise a failure if anything unexpected was seen. if len(config.failures()): raise error.TestFail((", ".join(config.failures())))