X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=kconfig-hardened-check.py;h=4762219b1354e63b76c9c5559ee3fe249a46d680;hb=0ace19012b626203d14332090cdcd40ed2237100;hp=95a5edfca633132eeb3a8659362aee111da689ff;hpb=c2b4899fc4cf7b43dd560bf8890e87ecf48f3bdf;p=kconfig-hardened-check.git diff --git a/kconfig-hardened-check.py b/kconfig-hardened-check.py index 95a5edf..4762219 100755 --- a/kconfig-hardened-check.py +++ b/kconfig-hardened-check.py @@ -156,7 +156,6 @@ def detect_arch(fname): with open(fname, 'r') as f: arch_pattern = re.compile("CONFIG_[a-zA-Z0-9_]*=y") arch = None - msg = None if not json_mode: print('[+] Trying to detect architecture in "{}"...'.format(fname)) for line in f.readlines(): @@ -173,6 +172,27 @@ def detect_arch(fname): return arch, 'OK' +def detect_version(fname): + with open(fname, 'r') as f: + ver_pattern = re.compile("# Linux/.* Kernel Configuration") + if not json_mode: + print('[+] Trying to detect kernel version in "{}"...'.format(fname)) + for line in f.readlines(): + if ver_pattern.match(line): + line = line.strip() + if not json_mode: + print('[+] Found version line: "{}"'.format(line)) + parts = line.split() + ver_str = parts[2] + ver_numbers = ver_str.split('.') + if len(ver_numbers) < 3 or not ver_numbers[0].isdigit() or not ver_numbers[1].isdigit(): + msg = 'failed to parse the version "' + ver_str + '"' + return None, msg + else: + return (int(ver_numbers[0]), int(ver_numbers[1])), None + return None, 'no kernel version detected' + + def construct_checklist(checklist, arch): modules_not_set = OptCheck('MODULES', 'is not set', 'kspp', 'cut_attack_surface') devmem_not_set = OptCheck('DEVMEM', 'is not set', 'kspp', 'cut_attack_surface') # refers to LOCK_DOWN_KERNEL @@ -215,6 +235,7 @@ def construct_checklist(checklist, arch): if debug_mode or arch == 'ARM': checklist.append(OptCheck('VMSPLIT_3G', 'y', 'defconfig', 'self_protection')) checklist.append(OptCheck('CPU_SW_DOMAIN_PAN', 'y', 'defconfig', 'self_protection')) + checklist.append(OptCheck('STACKPROTECTOR_PER_TASK', 'y', 'defconfig', 'self_protection')) if debug_mode or arch == 'ARM64' or arch == 'ARM': checklist.append(OptCheck('REFCOUNT_FULL', 'y', 'defconfig', 'self_protection')) checklist.append(OptCheck('HARDEN_BRANCH_PREDICTOR', 'y', 'defconfig', 'self_protection')) @@ -289,8 +310,6 @@ def construct_checklist(checklist, arch): iommu_support_is_set)) if debug_mode or arch == 'X86_32': checklist.append(OptCheck('PAGE_TABLE_ISOLATION', 'y', 'my', 'self_protection')) - if debug_mode or arch == 'ARM': - checklist.append(OptCheck('STACKPROTECTOR_PER_TASK', 'y', 'my', 'self_protection')) if debug_mode or arch == 'X86_64' or arch == 'ARM64' or arch == 'X86_32': checklist.append(OptCheck('SECURITY', 'y', 'defconfig', 'security_policy')) # and choose your favourite LSM @@ -418,17 +437,15 @@ def print_checklist(checklist, with_results): print() -def get_option_state(options, name): - return options.get(name, None) - - def perform_checks(checklist, parsed_options): for opt in checklist: if hasattr(opt, 'opts'): + # prepare ComplexOptCheck for o in opt.opts: - o.state = get_option_state(parsed_options, o.name) + o.state = parsed_options.get(o.name, None) else: - opt.state = get_option_state(parsed_options, opt.name) + # prepare OptCheck + opt.state = parsed_options.get(opt.name, None) opt.check() @@ -497,6 +514,12 @@ if __name__ == '__main__': elif not json_mode: print('[+] Detected architecture: {}'.format(arch)) + kernel_version, msg = detect_version(args.config) + if not kernel_version: + sys.exit('[!] ERROR: {}'.format(msg)) + elif not json_mode: + print('[+] Detected kernel version: {}.{}'.format(kernel_version[0], kernel_version[1])) + construct_checklist(config_checklist, arch) check_config_file(config_checklist, args.config) error_count = len(list(filter(lambda opt: opt.result.startswith('FAIL'), config_checklist)))