#!/usr/bin/python3
#
-# This tool helps me to check the Linux kernel Kconfig option list
-# against my security hardening preferences for X86_64, ARM64, X86_32, and ARM.
+# This tool helps me to check Linux kernel options against
+# my security hardening preferences for X86_64, ARM64, X86_32, and ARM.
# Let the computers do their job!
#
# Author: Alexander Popov <alex.popov@linux.com>
for i, opt in enumerate(self.opts):
ret = opt.check()
if ret:
- if opt.result != 'OK' or i == 0:
- # Preserve additional explanation of this OK result.
- # Simple OK is enough only for the main option that
- # this OR-check is about.
- self.result = opt.result
- else:
- # Simple OK is not enough for additional checks.
+ if opt.result == 'OK' and i != 0:
+ # Simple OK is not enough for additional checks, add more info:
self.result = 'OK: CONFIG_{} "{}"'.format(opt.name, opt.expected)
+ else:
+ self.result = opt.result
return True
self.result = self.opts[0].result
return False
print('[+] Config check is finished: \'OK\' - {}{} / \'FAIL\' - {}{}'.format(ok_count, ok_suppressed, fail_count, fail_suppressed))
-def perform_check(opt, parsed_options, kernel_version):
+def populate_opt_with_data(opt, parsed_options, kernel_version):
if hasattr(opt, 'opts'):
# prepare ComplexOptCheck
for o in opt.opts:
if hasattr(o, 'opts'):
# Recursion for nested ComplexOptChecks
- perform_check(o, parsed_options, kernel_version)
+ populate_opt_with_data(o, parsed_options, kernel_version)
if hasattr(o, 'state'):
o.state = parsed_options.get(o.name, None)
if hasattr(o, 'ver'):
if not hasattr(opt, 'state'):
sys.exit('[!] ERROR: bad simple check {}'.format(vars(opt)))
opt.state = parsed_options.get(opt.name, None)
- opt.check()
-def perform_checks(checklist, parsed_options, kernel_version):
+def populate_with_data(checklist, parsed_options, kernel_version):
+ for opt in checklist:
+ populate_opt_with_data(opt, parsed_options, kernel_version)
+
+
+def perform_checks(checklist):
for opt in checklist:
- perform_check(opt, parsed_options, kernel_version)
+ opt.check()
def parse_kconfig_file(parsed_options, fname):
parser.add_argument('-p', '--print', choices=supported_archs,
help='print security hardening preferences for the selected architecture')
parser.add_argument('-c', '--config',
- help='check the kernel config file against these preferences')
+ help='check the kernel kconfig file against these preferences')
parser.add_argument('-m', '--mode', choices=report_modes,
help='choose the report mode')
args = parser.parse_args()
if args.config:
if mode != 'json':
- print('[+] Config file to check: {}'.format(args.config))
+ print('[+] Kconfig file to check: {}'.format(args.config))
arch, msg = detect_arch(args.config, supported_archs)
if not arch:
# add relevant kconfig checks to the checklist
add_kconfig_checks(config_checklist, arch)
+ # populate the checklist with the parsed kconfig data
parsed_kconfig_options = OrderedDict()
parse_kconfig_file(parsed_kconfig_options, args.config)
+ populate_with_data(config_checklist, parsed_kconfig_options, kernel_version)
- perform_checks(config_checklist, parsed_kconfig_options, kernel_version)
+ # now everything is ready for performing the checks
+ perform_checks(config_checklist)
+ # finally print the results
if mode == 'verbose':
print_unknown_options(config_checklist, parsed_kconfig_options)
print_checklist(mode, config_checklist, True)