X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=kconfig_hardened_check%2F__init__.py;h=3a55b44dd1786672ee82fd79fb262a378b357b6c;hb=3e435f082b3eb9c1959ad87fd120bb9634079d6b;hp=3e6e6096d036ae889f6afc05db8174e1b8a113e7;hpb=45bb1e8f0e193715e0b0072929f063b765b78287;p=kconfig-hardened-check.git diff --git a/kconfig_hardened_check/__init__.py b/kconfig_hardened_check/__init__.py index 3e6e609..3a55b44 100644 --- a/kconfig_hardened_check/__init__.py +++ b/kconfig_hardened_check/__init__.py @@ -2,7 +2,7 @@ # # This tool helps me to check the Linux kernel Kconfig option list -# against my hardening preferences for X86_64, ARM64, X86_32, and ARM. +# against my security hardening preferences for X86_64, ARM64, X86_32, and ARM. # Let the computers do their job! # # Author: Alexander Popov @@ -11,18 +11,19 @@ # # # N.B Hardening command line parameters: -# slub_debug=FZP # slab_nomerge # page_alloc.shuffle=1 # iommu=force (does it help against DMA attacks?) -# page_poison=1 (if enabled) -# init_on_alloc=1 -# init_on_free=1 +# slub_debug=FZ (slow) +# init_on_alloc=1 (since v5.3) +# init_on_free=1 (since v5.3, otherwise slub_debug=P and page_poison=1) # loadpin.enforce=1 +# debugfs=no-mount (or off if possible) +# randomize_kstack_offset=1 # # Mitigations of CPU vulnerabilities: # Аrch-independent: -# mitigations=auto,nosmt +# mitigations=auto,nosmt (nosmt is slow) # X86: # spectre_v2=on # pti=on @@ -34,9 +35,19 @@ # kpti=on # ssbd=force-on # +# Should NOT be set: +# nokaslr +# arm64.nobti +# arm64.nopauth +# +# 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 -# kernel.dmesg_restrict=1 +# kernel.kptr_restrict=2 (or 1?) +# kernel.dmesg_restrict=1 (also see the kconfig option) # kernel.perf_event_paranoid=3 # kernel.kexec_load_disabled=1 # kernel.yama.ptrace_scope=3 @@ -46,6 +57,8 @@ # net.core.bpf_jit_harden=2 # # vm.unprivileged_userfaultfd=0 +# (at first, it disabled unprivileged userfaultfd, +# and since v5.11 it enables unprivileged userfaultfd for user-mode only) # # dev.tty.ldisc_autoload=0 # fs.protected_symlinks=1 @@ -225,9 +238,11 @@ class AND(ComplexOptCheck): if not ret: # This FAIL is caused by additional checks, # and not by the main option that this AND-check is about. - if opt.result.startswith('FAIL: \"'): - # Describe the reason of the FAIL. + # Describe the reason of the FAIL. + if opt.result.startswith('FAIL: \"') or opt.result == 'FAIL: not found': self.result = 'FAIL: CONFIG_{} not "{}"'.format(opt.name, opt.expected) + elif opt.result == 'FAIL: not present': + self.result = 'FAIL: CONFIG_{} not present'.format(opt.name) else: # This FAIL message is self-explaining. self.result = opt.result @@ -270,6 +285,9 @@ def detect_version(fname): def construct_checklist(l, arch): + # Calling the OptCheck class constructor: + # OptCheck(reason, decision, name, expected) + modules_not_set = OptCheck('cut_attack_surface', 'kspp', 'MODULES', 'is not set') devmem_not_set = OptCheck('cut_attack_surface', 'kspp', 'DEVMEM', 'is not set') # refers to LOCKDOWN @@ -288,6 +306,11 @@ def construct_checklist(l, arch): VerCheck((5, 5)))] # REFCOUNT_FULL is enabled by default since v5.5 iommu_support_is_set = OptCheck('self_protection', 'defconfig', 'IOMMU_SUPPORT', 'y') l += [iommu_support_is_set] # is needed for mitigating DMA attacks + if arch in ('X86_64', 'ARM64', 'X86_32'): + l += [OptCheck('self_protection', 'defconfig', 'RANDOMIZE_BASE', 'y')] + l += [OptCheck('self_protection', 'defconfig', 'THREAD_INFO_IN_TASK', 'y')] + if arch in ('X86_64', 'ARM64'): + l += [OptCheck('self_protection', 'defconfig', 'VMAP_STACK', 'y')] if arch in ('X86_64', 'X86_32'): l += [OptCheck('self_protection', 'defconfig', 'MICROCODE', 'y')] # is needed for mitigating CPU bugs l += [OptCheck('self_protection', 'defconfig', 'RETPOLINE', 'y')] @@ -295,6 +318,8 @@ def construct_checklist(l, arch): l += [OptCheck('self_protection', 'defconfig', 'SYN_COOKIES', 'y')] # another reason? l += [OR(OptCheck('self_protection', 'defconfig', 'X86_UMIP', 'y'), OptCheck('self_protection', 'defconfig', 'X86_INTEL_UMIP', 'y'))] + if arch in ('ARM64', 'ARM'): + l += [OptCheck('self_protection', 'defconfig', 'STACKPROTECTOR_PER_TASK', 'y')] if arch == 'X86_64': l += [OptCheck('self_protection', 'defconfig', 'PAGE_TABLE_ISOLATION', 'y')] l += [OptCheck('self_protection', 'defconfig', 'RANDOMIZE_MEMORY', 'y')] @@ -304,24 +329,23 @@ def construct_checklist(l, arch): iommu_support_is_set)] if arch == 'ARM64': l += [OptCheck('self_protection', 'defconfig', 'ARM64_PAN', 'y')] + l += [OptCheck('self_protection', 'defconfig', 'ARM64_EPAN', 'y')] l += [OptCheck('self_protection', 'defconfig', 'UNMAP_KERNEL_AT_EL0', 'y')] l += [OR(OptCheck('self_protection', 'defconfig', 'HARDEN_EL2_VECTORS', 'y'), AND(OptCheck('self_protection', 'defconfig', 'RANDOMIZE_BASE', 'y'), VerCheck((5, 9))))] # HARDEN_EL2_VECTORS was included in RANDOMIZE_BASE in v5.9 l += [OptCheck('self_protection', 'defconfig', 'RODATA_FULL_DEFAULT_ENABLED', 'y')] - l += [OptCheck('self_protection', 'defconfig', 'ARM64_PTR_AUTH', 'y')] - if arch in ('X86_64', 'ARM64'): - l += [OptCheck('self_protection', 'defconfig', 'VMAP_STACK', 'y')] - if arch in ('X86_64', 'ARM64', 'X86_32'): - l += [OptCheck('self_protection', 'defconfig', 'RANDOMIZE_BASE', 'y')] - l += [OptCheck('self_protection', 'defconfig', 'THREAD_INFO_IN_TASK', 'y')] + l += [OptCheck('self_protection', 'defconfig', 'ARM64_PTR_AUTH_KERNEL', 'y')] + l += [OptCheck('self_protection', 'defconfig', 'ARM64_BTI_KERNEL', 'y')] + l += [OR(OptCheck('self_protection', 'defconfig', 'HARDEN_BRANCH_PREDICTOR', 'y'), + VerCheck((5, 10)))] # HARDEN_BRANCH_PREDICTOR is enabled by default since v5.10 + l += [OptCheck('self_protection', 'defconfig', 'ARM64_MTE', 'y')] if arch == 'ARM': l += [OptCheck('self_protection', 'defconfig', 'CPU_SW_DOMAIN_PAN', 'y')] - l += [OptCheck('self_protection', 'defconfig', 'STACKPROTECTOR_PER_TASK', 'y')] - if arch in ('ARM64', 'ARM'): l += [OptCheck('self_protection', 'defconfig', 'HARDEN_BRANCH_PREDICTOR', 'y')] # 'self_protection', 'kspp' + l += [OptCheck('self_protection', 'kspp', 'SECURITY_DMESG_RESTRICT', 'y')] l += [OptCheck('self_protection', 'kspp', 'BUG_ON_DATA_CORRUPTION', 'y')] l += [OptCheck('self_protection', 'kspp', 'DEBUG_WX', 'y')] l += [OptCheck('self_protection', 'kspp', 'SCHED_STACK_END_CHECK', 'y')] @@ -341,6 +365,8 @@ def construct_checklist(l, arch): l += [hardened_usercopy_is_set] l += [AND(OptCheck('self_protection', 'kspp', 'HARDENED_USERCOPY_FALLBACK', 'is not set'), hardened_usercopy_is_set)] + l += [AND(OptCheck('self_protection', 'kspp', 'HARDENED_USERCOPY_PAGESPAN', 'is not set'), + hardened_usercopy_is_set)] l += [OR(OptCheck('self_protection', 'kspp', 'MODULE_SIG', 'y'), modules_not_set)] l += [OR(OptCheck('self_protection', 'kspp', 'MODULE_SIG_ALL', 'y'), @@ -349,27 +375,40 @@ def construct_checklist(l, arch): modules_not_set)] l += [OR(OptCheck('self_protection', 'kspp', 'MODULE_SIG_FORCE', 'y'), modules_not_set)] # refers to LOCKDOWN - l += [OR(OptCheck('self_protection', 'kspp', 'INIT_STACK_ALL', 'y'), + l += [OR(OptCheck('self_protection', 'kspp', 'INIT_STACK_ALL_ZERO', 'y'), OptCheck('self_protection', 'kspp', 'GCC_PLUGIN_STRUCTLEAK_BYREF_ALL', 'y'))] l += [OR(OptCheck('self_protection', 'kspp', 'INIT_ON_FREE_DEFAULT_ON', 'y'), - OptCheck('self_protection', 'kspp', 'PAGE_POISONING', 'y'))] # before v5.3 + OptCheck('self_protection', 'kspp', 'PAGE_POISONING_ZERO', 'y'))] + # CONFIG_INIT_ON_FREE_DEFAULT_ON was added in v5.3. + # CONFIG_PAGE_POISONING_ZERO was removed in v5.11. + # Starting from v5.11 CONFIG_PAGE_POISONING unconditionally checks + # the 0xAA poison pattern on allocation. + # That brings higher performance penalty. if arch in ('X86_64', 'ARM64', 'X86_32'): stackleak_is_set = OptCheck('self_protection', 'kspp', 'GCC_PLUGIN_STACKLEAK', 'y') l += [stackleak_is_set] + l += [OptCheck('self_protection', 'kspp', 'RANDOMIZE_KSTACK_OFFSET_DEFAULT', 'y')] if arch in ('X86_64', 'X86_32'): l += [OptCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '65536')] + if arch in ('ARM64', 'ARM'): + l += [OptCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '32768')] + l += [OptCheck('self_protection', 'kspp', 'SYN_COOKIES', 'y')] # another reason? + if arch == 'ARM64': + l += [OptCheck('self_protection', 'kspp', 'ARM64_SW_TTBR0_PAN', 'y')] if arch == 'X86_32': l += [OptCheck('self_protection', 'kspp', 'PAGE_TABLE_ISOLATION', 'y')] l += [OptCheck('self_protection', 'kspp', 'HIGHMEM64G', 'y')] l += [OptCheck('self_protection', 'kspp', 'X86_PAE', 'y')] - if arch == 'ARM64': - l += [OptCheck('self_protection', 'kspp', 'ARM64_SW_TTBR0_PAN', 'y')] - if arch in ('ARM64', 'ARM'): - l += [OptCheck('self_protection', 'kspp', 'SYN_COOKIES', 'y')] # another reason? - l += [OptCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '32768')] + + # 'self_protection', 'maintainer' + ubsan_bounds_is_set = OptCheck('self_protection', 'maintainer', 'UBSAN_BOUNDS', 'y') # only array index bounds checking + l += [ubsan_bounds_is_set] # recommended by Kees Cook in /issues/53 + l += [AND(OptCheck('self_protection', 'maintainer', 'UBSAN_SANITIZE_ALL', 'y'), + ubsan_bounds_is_set)] # recommended by Kees Cook in /issues/53 + l += [AND(OptCheck('self_protection', 'maintainer', 'UBSAN_TRAP', 'y'), + ubsan_bounds_is_set)] # recommended by Kees Cook in /issues/53 # 'self_protection', 'clipos' - l += [OptCheck('self_protection', 'clipos', 'SECURITY_DMESG_RESTRICT', 'y')] l += [OptCheck('self_protection', 'clipos', 'DEBUG_VIRTUAL', 'y')] l += [OptCheck('self_protection', 'clipos', 'STATIC_USERMODEHELPER', 'y')] # needs userspace support l += [OptCheck('self_protection', 'clipos', 'EFI_DISABLE_PCI_DMA', 'y')] @@ -384,20 +423,27 @@ def construct_checklist(l, arch): l += [AND(OptCheck('self_protection', 'clipos', 'STACKLEAK_RUNTIME_DISABLE', 'is not set'), stackleak_is_set)] if arch in ('X86_64', 'X86_32'): - l += [AND(OptCheck('self_protection', 'clipos', 'INTEL_IOMMU_SVM', 'y'), - iommu_support_is_set)] l += [AND(OptCheck('self_protection', 'clipos', 'INTEL_IOMMU_DEFAULT_ON', 'y'), iommu_support_is_set)] + if arch == 'X86_64': + l += [AND(OptCheck('self_protection', 'clipos', 'INTEL_IOMMU_SVM', 'y'), + iommu_support_is_set)] if arch == 'X86_32': l += [AND(OptCheck('self_protection', 'clipos', 'INTEL_IOMMU', 'y'), iommu_support_is_set)] # 'self_protection', 'my' - l += [OptCheck('self_protection', 'my', 'SLUB_DEBUG_ON', 'y')] # TODO: is it better to set that via kernel cmd? l += [OptCheck('self_protection', 'my', 'RESET_ATTACK_MITIGATION', 'y')] # needs userspace support (systemd) if arch == 'X86_64': l += [AND(OptCheck('self_protection', 'my', 'AMD_IOMMU_V2', 'y'), iommu_support_is_set)] + if arch == 'ARM64': + l += [OptCheck('self_protection', 'my', 'SHADOW_CALL_STACK', 'y')] # depends on clang, maybe it's alternative to STACKPROTECTOR_STRONG + l += [OptCheck('self_protection', 'my', 'KASAN_HW_TAGS', 'y')] + cfi_clang_is_set = OptCheck('self_protection', 'my', 'CFI_CLANG', 'y') + l += [cfi_clang_is_set] + l += [AND(OptCheck('self_protection', 'my', 'CFI_PERMISSIVE', 'is not set'), + cfi_clang_is_set)] # 'security_policy' if arch in ('X86_64', 'ARM64', 'X86_32'): @@ -453,9 +499,13 @@ def construct_checklist(l, arch): l += [OptCheck('cut_attack_surface', 'grsecurity', 'PAGE_OWNER', 'is not set')] l += [OptCheck('cut_attack_surface', 'grsecurity', 'DEBUG_KMEMLEAK', 'is not set')] l += [OptCheck('cut_attack_surface', 'grsecurity', 'BINFMT_AOUT', 'is not set')] - l += [OptCheck('cut_attack_surface', 'grsecurity', 'KPROBES', 'is not set')] # refers to LOCKDOWN - l += [OptCheck('cut_attack_surface', 'grsecurity', 'UPROBES', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'KPROBE_EVENTS', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'UPROBE_EVENTS', 'is not set')] l += [OptCheck('cut_attack_surface', 'grsecurity', 'GENERIC_TRACER', 'is not set')] # refers to LOCKDOWN + l += [OptCheck('cut_attack_surface', 'grsecurity', 'FUNCTION_TRACER', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'STACK_TRACER', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'HIST_TRIGGERS', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'BLK_DEV_IO_TRACE', 'is not set')] l += [OptCheck('cut_attack_surface', 'grsecurity', 'PROC_VMCORE', 'is not set')] l += [OptCheck('cut_attack_surface', 'grsecurity', 'PROC_PAGE_MONITOR', 'is not set')] l += [OptCheck('cut_attack_surface', 'grsecurity', 'USELIB', 'is not set')] @@ -466,13 +516,30 @@ def construct_checklist(l, arch): l += [OptCheck('cut_attack_surface', 'grsecurity', 'DEVPORT', 'is not set')] # refers to LOCKDOWN l += [OptCheck('cut_attack_surface', 'grsecurity', 'DEBUG_FS', 'is not set')] # refers to LOCKDOWN l += [OptCheck('cut_attack_surface', 'grsecurity', 'NOTIFIER_ERROR_INJECTION', 'is not set')] - l += [AND(OptCheck('cut_attack_surface', 'grsecurity', 'X86_PTDUMP', 'is not set'), - OptCheck('cut_attack_surface', 'my', 'PTDUMP_DEBUGFS', 'is not set'))] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'FAIL_FUTEX', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'PUNIT_ATOM_DEBUG', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'ACPI_CONFIGFS', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'EDAC_DEBUG', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'DRM_I915_DEBUG', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'BCACHE_CLOSURES_DEBUG', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'DVB_C8SECTPFE', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'MTD_SLRAM', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'MTD_PHRAM', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'IO_URING', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'KCMP', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'RSEQ', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'LATENCYTOP', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'KCOV', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'PROVIDE_OHCI1394_DMA_INIT', 'is not set')] + l += [OptCheck('cut_attack_surface', 'grsecurity', 'SUNRPC_DEBUG', 'is not set')] + l += [AND(OptCheck('cut_attack_surface', 'grsecurity', 'PTDUMP_DEBUGFS', 'is not set'), + OptCheck('cut_attack_surface', 'grsecurity', 'X86_PTDUMP', 'is not set'))] # 'cut_attack_surface', 'maintainer' - l += [OptCheck('cut_attack_surface', 'maintainer', 'DRM_LEGACY', 'is not set')] - l += [OptCheck('cut_attack_surface', 'maintainer', 'FB', 'is not set')] - l += [OptCheck('cut_attack_surface', 'maintainer', 'VT', 'is not set')] + l += [OptCheck('cut_attack_surface', 'maintainer', 'DRM_LEGACY', 'is not set')] # recommended by Daniel Vetter in /issues/38 + l += [OptCheck('cut_attack_surface', 'maintainer', 'FB', 'is not set')] # recommended by Daniel Vetter in /issues/38 + l += [OptCheck('cut_attack_surface', 'maintainer', 'VT', 'is not set')] # recommended by Daniel Vetter in /issues/38 + l += [OptCheck('cut_attack_surface', 'maintainer', 'BLK_DEV_FD', 'is not set')] # recommended by Denis Efremov in /pull/54 # 'cut_attack_surface', 'grapheneos' l += [OptCheck('cut_attack_surface', 'grapheneos', 'AIO', 'is not set')] @@ -488,7 +555,6 @@ def construct_checklist(l, arch): l += [OptCheck('cut_attack_surface', 'clipos', 'USER_NS', 'is not set')] # user.max_user_namespaces=0 l += [OptCheck('cut_attack_surface', 'clipos', 'X86_MSR', 'is not set')] # refers to LOCKDOWN l += [OptCheck('cut_attack_surface', 'clipos', 'X86_CPUID', 'is not set')] - l += [OptCheck('cut_attack_surface', 'clipos', 'IO_URING', 'is not set')] l += [OptCheck('cut_attack_surface', 'clipos', 'X86_IOPL_IOPERM', 'is not set')] # refers to LOCKDOWN l += [OptCheck('cut_attack_surface', 'clipos', 'ACPI_TABLE_UPGRADE', 'is not set')] # refers to LOCKDOWN l += [OptCheck('cut_attack_surface', 'clipos', 'EFI_CUSTOM_SSDT_OVERLAYS', 'is not set')] @@ -501,8 +567,10 @@ def construct_checklist(l, arch): l += [OptCheck('cut_attack_surface', 'lockdown', 'EFI_TEST', 'is not set')] # refers to LOCKDOWN l += [OptCheck('cut_attack_surface', 'lockdown', 'BPF_SYSCALL', 'is not set')] # refers to LOCKDOWN l += [OptCheck('cut_attack_surface', 'lockdown', 'MMIOTRACE_TEST', 'is not set')] # refers to LOCKDOWN + l += [OptCheck('cut_attack_surface', 'lockdown', 'KPROBES', 'is not set')] # refers to LOCKDOWN # 'cut_attack_surface', 'my' + l += [OptCheck('cut_attack_surface', 'my', 'TRIM_UNUSED_KSYMS', 'y')] l += [OptCheck('cut_attack_surface', 'my', 'MMIOTRACE', 'is not set')] # refers to LOCKDOWN (permissive) l += [OptCheck('cut_attack_surface', 'my', 'LIVEPATCH', 'is not set')] l += [OptCheck('cut_attack_surface', 'my', 'IP_DCCP', 'is not set')] @@ -516,6 +584,8 @@ def construct_checklist(l, arch): l += [OptCheck('userspace_hardening', 'defconfig', 'INTEGRITY', 'y')] if arch == 'ARM': l += [OptCheck('userspace_hardening', 'my', 'INTEGRITY', 'y')] + if arch == 'ARM64': + l += [OptCheck('userspace_hardening', 'defconfig', 'ARM64_MTE', 'y')] if arch in ('ARM', 'X86_32'): l += [OptCheck('userspace_hardening', 'defconfig', 'VMSPLIT_3G', 'y')] if arch in ('X86_64', 'ARM64'): @@ -592,22 +662,22 @@ def print_checklist(mode, checklist, with_results): def perform_check(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) - if hasattr(o, 'state'): - o.state = parsed_options.get(o.name, None) - if hasattr(o, 'ver'): - o.ver = kernel_version - else: - # prepare simple check, opt.state is mandatory - if not hasattr(opt, 'state'): - sys.exit('[!] ERROR: bad simple check {}'.format(vars(opt))) - opt.state = parsed_options.get(opt.name, None) - opt.check() + 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) + if hasattr(o, 'state'): + o.state = parsed_options.get(o.name, None) + if hasattr(o, 'ver'): + o.ver = kernel_version + else: + # prepare simple check, opt.state is mandatory + 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): @@ -650,10 +720,10 @@ def main(): report_modes = ['verbose', 'json', 'show_ok', 'show_fail'] supported_archs = ['X86_64', 'X86_32', 'ARM64', 'ARM'] parser = ArgumentParser(prog='kconfig-hardened-check', - description='Checks the hardening options in the Linux kernel config') + description='A tool for checking the security hardening options of the Linux kernel') parser.add_argument('--version', action='version', version='%(prog)s ' + __version__) parser.add_argument('-p', '--print', choices=supported_archs, - help='print hardening preferences for selected architecture') + help='print security hardening preferences for the selected architecture') parser.add_argument('-c', '--config', help='check the kernel config file against these preferences') parser.add_argument('-m', '--mode', choices=report_modes, @@ -701,7 +771,7 @@ def main(): arch = args.print construct_checklist(config_checklist, arch) if mode != 'json': - print('[+] Printing kernel hardening preferences for {}...'.format(arch)) + print('[+] Printing kernel security hardening preferences for {}...'.format(arch)) print_checklist(mode, config_checklist, False) sys.exit(0)