# Please don't cry if my Python code looks like C.
#
#
-# N.B Hardening command line parameters:
-# iommu=force (does it help against DMA attacks?)
-#
-# The list of disabled mitigations of CPU vulnerabilities:
-# mitigations=off
-# pti=off
-# spectre_v2=off
-# spectre_v2_user=off
-# spec_store_bypass_disable=off
-# l1tf=off
-# mds=off
-# tsx_async_abort=off
-# srbds=off
-# mmio_stale_data=off
-# retbleed=off
-# nopti
-# nokaslr
-# nospectre_v1
-# nospectre_v2
-# nospectre_bhb
-# nospec_store_bypass_disable
-# kpti=0
-# ssbd=force-off
-# nosmt (enabled)
-#
-# Hardware tag-based KASAN with arm64 Memory Tagging Extension (MTE):
-# kasan=on
-# kasan.stacktrace=off
-# kasan.fault=panic
-#
# N.B. Hardening sysctls:
# kernel.kptr_restrict=2 (or 1?)
# kernel.dmesg_restrict=1 (also see the kconfig option)
-# kernel.perf_event_paranoid=3
+# kernel.perf_event_paranoid=2 (or 3 with a custom patch, see https://lwn.net/Articles/696216/)
# kernel.kexec_load_disabled=1
# kernel.yama.ptrace_scope=3
# user.max_user_namespaces=0
# fs.suid_dumpable=0
# kernel.modules_disabled=1
# kernel.randomize_va_space = 2
+# nosmt sysfs control file
# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring
class OptCheck:
def __init__(self, reason, decision, name, expected):
assert(name and name == name.strip() and len(name.split()) == 1), \
- 'invalid name "{}" for {}'.format(name, self.__class__.__name__)
+ f'invalid name "{name}" for {self.__class__.__name__}'
self.name = name
assert(decision and decision == decision.strip() and len(decision.split()) == 1), \
- 'invalid decision "{}" for "{}" check'.format(decision, name)
+ f'invalid decision "{decision}" for "{name}" check'
self.decision = decision
assert(reason and reason == reason.strip() and len(reason.split()) == 1), \
- 'invalid reason "{}" for "{}" check'.format(reason, name)
+ f'invalid reason "{reason}" for "{name}" check'
self.reason = reason
assert(expected and expected == expected.strip()), \
- 'invalid expected value "{}" for "{}" check (1)'.format(expected, name)
+ f'invalid expected value "{expected}" for "{name}" check (1)'
val_len = len(expected.split())
if val_len == 3:
- assert(expected == 'is not set' or expected == 'is not off'), \
- 'invalid expected value "{}" for "{}" check (2)'.format(expected, name)
+ assert(expected in ('is not set', 'is not off')), \
+ f'invalid expected value "{expected}" for "{name}" check (2)'
elif val_len == 2:
assert(expected == 'is present'), \
- 'invalid expected value "{}" for "{}" check (3)'.format(expected, name)
+ f'invalid expected value "{expected}" for "{name}" check (3)'
else:
assert(val_len == 1), \
- 'invalid expected value "{}" for "{}" check (4)'.format(expected, name)
+ f'invalid expected value "{expected}" for "{name}" check (4)'
self.expected = expected
self.state = None
self.result = 'FAIL: "' + self.state + '"'
def table_print(self, _mode, with_results):
- print('{:<40}|{:^7}|{:^12}|{:^10}|{:^18}'.format(self.name, self.type, self.expected, self.decision, self.reason), end='')
+ print(f'{self.name:<40}|{self.type:^7}|{self.expected:^12}|{self.decision:^10}|{self.reason:^18}', end='')
if with_results:
- print('| {}'.format(self.result), end='')
+ print(f'| {self.result}', end='')
def json_dump(self, with_results):
dump = [self.name, self.type, self.expected, self.decision, self.reason]
class VersionCheck:
def __init__(self, ver_expected):
assert(ver_expected and isinstance(ver_expected, tuple) and len(ver_expected) == 2), \
- 'invalid version "{}" for VersionCheck'.format(ver_expected)
+ f'invalid version "{ver_expected}" for VersionCheck'
self.ver_expected = ver_expected
self.ver = ()
self.result = None
def table_print(self, _mode, with_results):
ver_req = 'kernel version >= ' + str(self.ver_expected[0]) + '.' + str(self.ver_expected[1])
- print('{:<91}'.format(ver_req), end='')
+ print(f'{ver_req:<91}', end='')
if with_results:
- print('| {}'.format(self.result), end='')
+ print(f'| {self.result}', end='')
class ComplexOptCheck:
def __init__(self, *opts):
self.opts = opts
assert(self.opts), \
- 'empty {} check'.format(self.__class__.__name__)
+ f'empty {self.__class__.__name__} check'
assert(len(self.opts) != 1), \
- 'useless {} check: {}'.format(self.__class__.__name__, opts)
+ f'useless {self.__class__.__name__} check: {opts}'
assert(isinstance(opts[0], (KconfigCheck, CmdlineCheck))), \
- 'invalid {} check: {}'.format(self.__class__.__name__, opts)
+ f'invalid {self.__class__.__name__} check: {opts}'
self.result = None
@property
def table_print(self, mode, with_results):
if mode == 'verbose':
- print(' {:87}'.format('<<< ' + self.__class__.__name__ + ' >>>'), end='')
+ print(f" {'<<< ' + self.__class__.__name__ + ' >>>':87}", end='')
if with_results:
- print('| {}'.format(self.result), end='')
+ print(f'| {self.result}', end='')
for o in self.opts:
print()
o.table_print(mode, with_results)
o = self.opts[0]
o.table_print(mode, False)
if with_results:
- print('| {}'.format(self.result), end='')
+ print(f'| {self.result}', end='')
def json_dump(self, with_results):
dump = self.opts[0].json_dump(False)
# Add more info for additional checks:
if i != 0:
if opt.result == 'OK':
- self.result = 'OK: {} is "{}"'.format(opt.name, opt.expected)
+ self.result = f'OK: {opt.name} is "{opt.expected}"'
elif opt.result == 'OK: is not found':
- self.result = 'OK: {} is not found'.format(opt.name)
+ self.result = f'OK: {opt.name} is not found'
elif opt.result == 'OK: is present':
- self.result = 'OK: {} is present'.format(opt.name)
+ self.result = f'OK: {opt.name} is present'
elif opt.result.startswith('OK: is not off'):
- self.result = 'OK: {} is not off'.format(opt.name)
+ self.result = f'OK: {opt.name} is not off'
else:
# VersionCheck provides enough info
assert(opt.result.startswith('OK: version')), \
- 'unexpected OK description "{}"'.format(opt.result)
+ f'unexpected OK description "{opt.result}"'
return
self.result = self.opts[0].result
# and not by the main option that this AND-check is about.
# Describe the reason of the FAIL.
if opt.result.startswith('FAIL: \"') or opt.result == 'FAIL: is not found':
- self.result = 'FAIL: {} is not "{}"'.format(opt.name, opt.expected)
+ self.result = f'FAIL: {opt.name} is not "{opt.expected}"'
elif opt.result == 'FAIL: is not present':
- self.result = 'FAIL: {} is not present'.format(opt.name)
- elif opt.result == 'FAIL: is off' or opt.result == 'FAIL: is off, "0"':
- self.result = 'FAIL: {} is off'.format(opt.name)
+ self.result = f'FAIL: {opt.name} is not present'
+ elif opt.result in ('FAIL: is off', 'FAIL: is off, "0"'):
+ self.result = f'FAIL: {opt.name} is off'
elif opt.result == 'FAIL: is off, not found':
- self.result = 'FAIL: {} is off, not found'.format(opt.name)
+ self.result = f'FAIL: {opt.name} is off, not found'
else:
# VersionCheck provides enough info
self.result = opt.result
assert(opt.result.startswith('FAIL: version')), \
- 'unexpected FAIL description "{}"'.format(opt.result)
+ f'unexpected FAIL description "{opt.result}"'
return
VersionCheck((5, 5)))] # REFCOUNT_FULL is enabled by default since v5.5
if arch in ('X86_64', 'ARM64', 'X86_32'):
l += [KconfigCheck('self_protection', 'defconfig', 'RANDOMIZE_BASE', 'y')]
- if arch in ('X86_64', 'ARM64'):
+ if arch in ('X86_64', 'ARM64', 'ARM'):
l += [KconfigCheck('self_protection', 'defconfig', 'VMAP_STACK', 'y')]
if arch in ('X86_64', 'X86_32'):
+ l += [KconfigCheck('self_protection', 'defconfig', 'DEBUG_WX', 'y')]
+ l += [KconfigCheck('self_protection', 'defconfig', 'WERROR', 'y')]
l += [KconfigCheck('self_protection', 'defconfig', 'X86_MCE', 'y')]
l += [KconfigCheck('self_protection', 'defconfig', 'X86_MCE_INTEL', 'y')]
l += [KconfigCheck('self_protection', 'defconfig', 'X86_MCE_AMD', 'y')]
l += [OR(KconfigCheck('self_protection', 'defconfig', 'X86_UMIP', 'y'),
KconfigCheck('self_protection', 'defconfig', 'X86_INTEL_UMIP', 'y'))]
if arch in ('ARM64', 'ARM'):
+ l += [KconfigCheck('self_protection', 'defconfig', 'IOMMU_DEFAULT_DMA_STRICT', 'y')]
+ l += [KconfigCheck('self_protection', 'defconfig', 'IOMMU_DEFAULT_PASSTHROUGH', 'is not set')] # true if IOMMU_DEFAULT_DMA_STRICT is set
l += [KconfigCheck('self_protection', 'defconfig', 'STACKPROTECTOR_PER_TASK', 'y')]
if arch == 'X86_64':
l += [KconfigCheck('self_protection', 'defconfig', 'PAGE_TABLE_ISOLATION', 'y')]
# 'self_protection', 'kspp'
l += [KconfigCheck('self_protection', 'kspp', 'BUG_ON_DATA_CORRUPTION', 'y')]
- l += [KconfigCheck('self_protection', 'kspp', 'DEBUG_WX', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'SCHED_STACK_END_CHECK', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'SLAB_FREELIST_HARDENED', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'SLAB_FREELIST_RANDOM', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'DEBUG_NOTIFIERS', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'INIT_ON_ALLOC_DEFAULT_ON', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'KFENCE', 'y')]
- l += [KconfigCheck('self_protection', 'kspp', 'WERROR', 'y')]
- l += [KconfigCheck('self_protection', 'kspp', 'IOMMU_DEFAULT_DMA_STRICT', 'y')]
- l += [KconfigCheck('self_protection', 'kspp', 'IOMMU_DEFAULT_PASSTHROUGH', 'is not set')] # true if IOMMU_DEFAULT_DMA_STRICT is set
l += [KconfigCheck('self_protection', 'kspp', 'ZERO_CALL_USED_REGS', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'HW_RANDOM_TPM', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'STATIC_USERMODEHELPER', 'y')] # needs userspace support
- l += [KconfigCheck('self_protection', 'kspp', 'SCHED_CORE', 'y')]
randstruct_is_set = OR(KconfigCheck('self_protection', 'kspp', 'RANDSTRUCT_FULL', 'y'),
KconfigCheck('self_protection', 'kspp', 'GCC_PLUGIN_RANDSTRUCT', 'y'))
l += [randstruct_is_set]
l += [AND(KconfigCheck('self_protection', 'kspp', 'CFI_PERMISSIVE', 'is not set'),
cfi_clang_is_set)]
if arch in ('X86_64', 'X86_32'):
+ l += [KconfigCheck('self_protection', 'kspp', 'SCHED_CORE', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '65536')]
+ l += [KconfigCheck('self_protection', 'kspp', 'IOMMU_DEFAULT_DMA_STRICT', 'y')]
+ l += [KconfigCheck('self_protection', 'kspp', 'IOMMU_DEFAULT_PASSTHROUGH', 'is not set')] # true if IOMMU_DEFAULT_DMA_STRICT is set
l += [AND(KconfigCheck('self_protection', 'kspp', 'INTEL_IOMMU_DEFAULT_ON', 'y'),
iommu_support_is_set)]
if arch in ('ARM64', 'ARM'):
+ l += [KconfigCheck('self_protection', 'kspp', 'DEBUG_WX', 'y')]
+ l += [KconfigCheck('self_protection', 'kspp', 'WERROR', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '32768')]
l += [KconfigCheck('self_protection', 'kspp', 'SYN_COOKIES', 'y')] # another reason?
if arch == 'X86_64':
if arch == 'ARM64':
l += [KconfigCheck('self_protection', 'kspp', 'ARM64_SW_TTBR0_PAN', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'SHADOW_CALL_STACK', 'y')]
- l += [KconfigCheck('self_protection', 'kspp', 'KASAN_HW_TAGS', 'y')]
+ l += [KconfigCheck('self_protection', 'kspp', 'KASAN_HW_TAGS', 'y')] # see also: kasan=on, kasan.stacktrace=off, kasan.fault=panic
if arch == 'X86_32':
l += [KconfigCheck('self_protection', 'kspp', 'PAGE_TABLE_ISOLATION', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'HIGHMEM64G', 'y')]
l += [KconfigCheck('cut_attack_surface', 'kspp', 'PROC_KCORE', 'is not set')] # refers to LOCKDOWN
l += [KconfigCheck('cut_attack_surface', 'kspp', 'LEGACY_PTYS', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'kspp', 'HIBERNATION', 'is not set')] # refers to LOCKDOWN
+ l += [KconfigCheck('cut_attack_surface', 'kspp', 'COMPAT', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'kspp', 'IA32_EMULATION', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'kspp', 'X86_X32', 'is not set')]
+ l += [KconfigCheck('cut_attack_surface', 'kspp', 'X86_X32_ABI', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'kspp', 'MODIFY_LDT_SYSCALL', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'kspp', 'OABI_COMPAT', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'kspp', 'X86_MSR', 'is not set')] # refers to LOCKDOWN
l += [KconfigCheck('cut_attack_surface', 'maintainer', 'VT', 'is not set')] # recommended by Daniel Vetter in /issues/38
l += [KconfigCheck('cut_attack_surface', 'maintainer', 'BLK_DEV_FD', 'is not set')] # recommended by Denis Efremov in /pull/54
l += [KconfigCheck('cut_attack_surface', 'maintainer', 'BLK_DEV_FD_RAWCMD', 'is not set')] # recommended by Denis Efremov in /pull/62
-
- # 'cut_attack_surface', 'grapheneos'
- l += [KconfigCheck('cut_attack_surface', 'grapheneos', 'AIO', 'is not set')]
+ l += [KconfigCheck('cut_attack_surface', 'maintainer', 'NOUVEAU_LEGACY_CTX_SUPPORT', 'is not set')]
+ # recommended by Dave Airlie in kernel commit b30a43ac7132cdda
# 'cut_attack_surface', 'clipos'
l += [KconfigCheck('cut_attack_surface', 'clipos', 'STAGING', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'my', 'VIDEO_VIVID', 'is not set')]
l += [KconfigCheck('cut_attack_surface', 'my', 'INPUT_EVBUG', 'is not set')] # Can be used as a keylogger
l += [KconfigCheck('cut_attack_surface', 'my', 'KGDB', 'is not set')]
+ l += [KconfigCheck('cut_attack_surface', 'my', 'AIO', 'is not set')]
l += [OR(KconfigCheck('cut_attack_surface', 'my', 'TRIM_UNUSED_KSYMS', 'y'),
modules_not_set)]
l += [CmdlineCheck('self_protection', 'defconfig', 'arm64.nobti', 'is not set')]
l += [CmdlineCheck('self_protection', 'defconfig', 'arm64.nopauth', 'is not set')]
l += [CmdlineCheck('self_protection', 'defconfig', 'arm64.nomte', 'is not set')]
- l += [OR(CmdlineCheck('self_protection', 'defconfig', 'mitigations', 'is not off'),
- CmdlineCheck('self_protection', 'defconfig', 'mitigations', 'is not set'))]
l += [OR(CmdlineCheck('self_protection', 'defconfig', 'spectre_v2', 'is not off'),
CmdlineCheck('self_protection', 'defconfig', 'spectre_v2', 'is not set'))]
l += [OR(CmdlineCheck('self_protection', 'defconfig', 'spectre_v2_user', 'is not off'),
CmdlineCheck('self_protection', 'defconfig', 'retbleed', 'is not set'))]
l += [OR(CmdlineCheck('self_protection', 'defconfig', 'kpti', 'is not off'),
CmdlineCheck('self_protection', 'defconfig', 'kpti', 'is not set'))]
+ l += [OR(CmdlineCheck('self_protection', 'defconfig', 'kvm.nx_huge_pages', 'is not off'),
+ CmdlineCheck('self_protection', 'defconfig', 'kvm.nx_huge_pages', 'is not set'))]
if arch == 'ARM64':
l += [OR(CmdlineCheck('self_protection', 'defconfig', 'ssbd', 'kernel'),
CmdlineCheck('self_protection', 'my', 'ssbd', 'force-on'),
# 'self_protection', 'kspp'
l += [CmdlineCheck('self_protection', 'kspp', 'nosmt', 'is present')]
+ l += [CmdlineCheck('self_protection', 'kspp', 'mitigations', 'auto,nosmt')] # 'nosmt' by kspp + 'auto' by defconfig
l += [OR(CmdlineCheck('self_protection', 'kspp', 'init_on_alloc', '1'),
AND(KconfigCheck('self_protection', 'kspp', 'INIT_ON_ALLOC_DEFAULT_ON', 'y'),
CmdlineCheck('self_protection', 'kspp', 'init_on_alloc', 'is not set')))]
CmdlineCheck('self_protection', 'kspp', 'slub_debug', 'P')))]
l += [OR(CmdlineCheck('self_protection', 'kspp', 'slab_nomerge', 'is present'),
AND(KconfigCheck('self_protection', 'clipos', 'SLAB_MERGE_DEFAULT', 'is not set'),
- CmdlineCheck('self_protection', 'kspp', 'slab_merge', 'is not set')))]
+ CmdlineCheck('self_protection', 'kspp', 'slab_merge', 'is not set'),
+ CmdlineCheck('self_protection', 'clipos', 'slub_merge', 'is not set')))]
l += [OR(CmdlineCheck('self_protection', 'kspp', 'iommu.strict', '1'),
AND(KconfigCheck('self_protection', 'kspp', 'IOMMU_DEFAULT_DMA_STRICT', 'y'),
CmdlineCheck('self_protection', 'kspp', 'iommu.strict', 'is not set')))]
# 'self_protection', 'clipos'
l += [CmdlineCheck('self_protection', 'clipos', 'page_alloc.shuffle', '1')]
+ if arch in ('X86_64', 'X86_32'):
+ l += [CmdlineCheck('self_protection', 'clipos', 'iommu', 'force')]
# 'cut_attack_surface', 'defconfig'
if arch in ('X86_64', 'X86_32'):
continue
for o3 in o2.opts:
assert(o3.type != 'complex'), \
- 'unexpected ComplexOptCheck inside {}'.format(o2.name)
+ f'unexpected ComplexOptCheck inside {o2.name}'
if hasattr(o3, 'name'):
known_options.append(o3.name)
for option, value in parsed_options.items():
if option not in known_options:
- print('[?] No check for option {} ({})'.format(option, value))
+ print(f'[?] No check for option {option} ({value})')
def print_checklist(mode, checklist, with_results):
if with_results:
sep_line_len += 30
print('=' * sep_line_len)
- print('{:^40}|{:^7}|{:^12}|{:^10}|{:^18}'.format('option name', 'type', 'desired val', 'decision', 'reason'), end='')
+ print(f"{'option name':^40}|{'type':^7}|{'desired val':^12}|{'decision':^10}|{'reason':^18}", end='')
if with_results:
- print('| {}'.format('check result'), end='')
+ print('| check result', end='')
print()
print('=' * sep_line_len)
if mode == 'show_fail':
ok_suppressed = ' (suppressed in output)'
if mode != 'json':
- print('[+] Config check is finished: \'OK\' - {}{} / \'FAIL\' - {}{}'.format(ok_count, ok_suppressed, fail_count, fail_suppressed))
+ print(f'[+] Config check is finished: \'OK\' - {ok_count}{ok_suppressed} / \'FAIL\' - {fail_count}{fail_suppressed}')
def populate_simple_opt_with_data(opt, data, data_type):
assert(opt.type != 'complex'), \
- 'unexpected ComplexOptCheck "{}"'.format(opt.name)
+ f'unexpected ComplexOptCheck "{opt.name}"'
assert(opt.type in SIMPLE_OPTION_TYPES), \
- 'invalid opt type "{}"'.format(opt.type)
+ f'invalid opt type "{opt.type}"'
assert(data_type in SIMPLE_OPTION_TYPES), \
- 'invalid data type "{}"'.format(data_type)
+ f'invalid data type "{data_type}"'
if data_type != opt.type:
return
opt.state = data.get(opt.name, None)
else:
assert(data_type == 'version'), \
- 'unexpected data type "{}"'.format(data_type)
+ f'unexpected data type "{data_type}"'
opt.ver = data
populate_simple_opt_with_data(o, data, data_type)
else:
assert(opt.type in ('kconfig', 'cmdline')), \
- 'bad type "{}" for a simple check'.format(opt.type)
+ f'bad type "{opt.type}" for a simple check'
populate_simple_opt_with_data(opt, data, data_type)
if args.mode:
mode = args.mode
if mode != 'json':
- print('[+] Special report mode: {}'.format(mode))
+ print(f'[+] Special report mode: {mode}')
config_checklist = []
sys.exit('[!] ERROR: --config and --print can\'t be used together')
if mode != 'json':
- print('[+] Kconfig file to check: {}'.format(args.config))
+ print(f'[+] Kconfig file to check: {args.config}')
if args.cmdline:
- print('[+] Kernel cmdline file to check: {}'.format(args.cmdline))
+ print(f'[+] Kernel cmdline file to check: {args.cmdline}')
arch, msg = detect_arch(args.config, supported_archs)
if not arch:
sys.exit('[!] ERROR: {}'.format(msg))
if mode != 'json':
- print('[+] Detected architecture: {}'.format(arch))
+ print(f'[+] Detected architecture: {arch}')
kernel_version, msg = detect_kernel_version(args.config)
if not kernel_version:
sys.exit('[!] ERROR: {}'.format(msg))
if mode != 'json':
- print('[+] Detected kernel version: {}.{}'.format(kernel_version[0], kernel_version[1]))
+ print(f'[+] Detected kernel version: {kernel_version[0]}.{kernel_version[1]}')
compiler, msg = detect_compiler(args.config)
if mode != 'json':
if compiler:
- print('[+] Detected compiler: {}'.format(compiler))
+ print(f'[+] Detected compiler: {compiler}')
else:
- print('[-] Can\'t detect the compiler: {}'.format(msg))
+ print(f'[-] Can\'t detect the compiler: {msg}')
# add relevant kconfig checks to the checklist
add_kconfig_checks(config_checklist, arch)
parse_cmdline_file(parsed_cmdline_options, args.cmdline)
populate_with_data(config_checklist, parsed_cmdline_options, 'cmdline')
- # now everything is ready for performing the checks
+ # now everything is ready, perform the checks
perform_checks(config_checklist)
- # finally print the results
if mode == 'verbose':
- print_unknown_options(config_checklist, parsed_kconfig_options)
+ # print the parsed options without the checks (for debugging)
+ all_parsed_options = parsed_kconfig_options # assignment does not copy
+ if args.cmdline:
+ all_parsed_options.update(parsed_cmdline_options)
+ print_unknown_options(config_checklist, all_parsed_options)
+
+ # finally print the results
print_checklist(mode, config_checklist, True)
sys.exit(0)
add_kconfig_checks(config_checklist, arch)
add_cmdline_checks(config_checklist, arch)
if mode != 'json':
- print('[+] Printing kernel security hardening preferences for {}...'.format(arch))
+ print(f'[+] Printing kernel security hardening preferences for {arch}...')
print_checklist(mode, config_checklist, False)
sys.exit(0)