X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=kconfig-hardened-check.py;h=f66f61adc48749845f79dbfae7bce0468118be40;hb=885eca86950992cdc34ef6067999fdc5b1467265;hp=a87b28d5374e0a686a9da7bcdeb07e2f5f551e93;hpb=3fb179530c3849364b61c1b9b75b4129034e06f4;p=kconfig-hardened-check.git diff --git a/kconfig-hardened-check.py b/kconfig-hardened-check.py index a87b28d..f66f61a 100755 --- a/kconfig-hardened-check.py +++ b/kconfig-hardened-check.py @@ -22,7 +22,6 @@ from collections import OrderedDict import re debug_mode = False # set it to True to print the unknown options from the config -error_count = 0 checklist = [] @@ -36,24 +35,63 @@ class OptCheck: self.result = None def check(self): - global error_count - if self.expected == self.state: self.result = 'OK' elif self.state is None: if self.expected == 'is not set': self.result = 'OK: not found' else: - error_count += 1 self.result = 'FAIL: not found' else: - error_count += 1 self.result = 'FAIL: "' + self.state + '"' + if self.result.startswith('OK'): + return True, self.result + else: + return False, self.result + def __repr__(self): return '{} = {}'.format(self.name, self.state) +class OR: + def __init__(self, *opts): + self.opts = opts + self.result = None + + # self.opts[0] is the option which this OR-check is about. + # Use case: OR(, ) + + @property + def name(self): + return self.opts[0].name + + @property + def expected(self): + return self.opts[0].expected + + @property + def state(self): + return self.opts[0].state + + @property + def decision(self): + return self.opts[0].decision + + @property + def reason(self): + return self.opts[0].reason + + def check(self): + for opt in self.opts: + result, msg = opt.check() + if result: + self.result = 'OK (CONFIG_{} {})'.format(opt.name, opt.state) + return result, self.result + self.result = 'FAIL: "{}"'.format(self.opts[0].state) + return False, self.result + + def construct_opt_checks(): checklist.append(OptCheck('BUG', 'y', 'ubuntu18', 'self_protection')) checklist.append(OptCheck('PAGE_TABLE_ISOLATION', 'y', 'ubuntu18', 'self_protection')) @@ -117,6 +155,7 @@ def construct_opt_checks(): checklist.append(OptCheck('ZSMALLOC_STAT', 'is not set', 'ubuntu18', 'cut_attack_surface')) checklist.append(OptCheck('PAGE_OWNER', 'is not set', 'ubuntu18', 'cut_attack_surface')) checklist.append(OptCheck('DEBUG_KMEMLEAK', 'is not set', 'ubuntu18', 'cut_attack_surface')) + checklist.append(OptCheck('BINFMT_AOUT', 'is not set', 'ubuntu18', 'cut_attack_surface')) checklist.append(OptCheck('IO_STRICT_DEVMEM', 'y', 'kspp', 'cut_attack_surface')) checklist.append(OptCheck('LEGACY_VSYSCALL_NONE', 'y', 'kspp', 'cut_attack_surface')) # 'vsyscall=none' @@ -169,8 +208,6 @@ def print_opt_checks(): def print_check_results(): - global error_count - print(' {:<39}|{:^13}|{:^10}|{:^20}||{:^20}'.format('option name', 'desired val', 'decision', 'reason', 'check result')) print(' ===========================================================================================================') for opt in checklist: @@ -184,7 +221,11 @@ def get_option_state(options, name): def perform_checks(parsed_options): for opt in checklist: - opt.state = get_option_state(parsed_options, opt.name) + if hasattr(opt, 'opts'): + for o in opt.opts: + o.state = get_option_state(parsed_options, o.name) + else: + opt.state = get_option_state(parsed_options, opt.name) opt.check() @@ -242,6 +283,7 @@ if __name__ == '__main__': if args.config: check_config_file(args.config) + error_count = len(list(filter(lambda opt: opt.result.startswith('FAIL'), checklist))) if error_count == 0: print('[+] config check is PASSED') sys.exit(0)