X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=kernel_hardening_checker%2Fchecks.py;h=ca014afc8fd9382fefd6a2572a52959093a0c7ce;hb=b87f0b675171581857d3cb2f01ce74f1dcf72248;hp=0ce187d6f6cf8781aa6ecefd75a0de2c541fbe33;hpb=b29098f65cfd9a22d39273553944c9da72b9adfc;p=kconfig-hardened-check.git diff --git a/kernel_hardening_checker/checks.py b/kernel_hardening_checker/checks.py index 0ce187d..ca014af 100644 --- a/kernel_hardening_checker/checks.py +++ b/kernel_hardening_checker/checks.py @@ -35,8 +35,6 @@ def add_kconfig_checks(l, arch): l += [KconfigCheck('self_protection', 'defconfig', 'BUG', 'y')] l += [KconfigCheck('self_protection', 'defconfig', 'SLUB_DEBUG', 'y')] l += [KconfigCheck('self_protection', 'defconfig', 'THREAD_INFO_IN_TASK', 'y')] - gcc_plugins_support_is_set = KconfigCheck('self_protection', 'defconfig', 'GCC_PLUGINS', 'y') - l += [gcc_plugins_support_is_set] iommu_support_is_set = KconfigCheck('self_protection', 'defconfig', 'IOMMU_SUPPORT', 'y') l += [iommu_support_is_set] # is needed for mitigating DMA attacks l += [OR(KconfigCheck('self_protection', 'defconfig', 'STACKPROTECTOR', 'y'), @@ -63,20 +61,26 @@ def add_kconfig_checks(l, arch): if arch in ('X86_64', 'ARM64', 'ARM'): l += [vmap_stack_is_set] if arch in ('X86_64', 'X86_32'): + cpu_sup_amd_not_set=KconfigCheck('-', '-', 'CPU_SUP_AMD', 'is not set') + cpu_sup_intel_not_set=KconfigCheck('-', '-', 'CPU_SUP_INTEL', 'is not set') l += [KconfigCheck('self_protection', 'defconfig', 'SPECULATION_MITIGATIONS', 'y')] 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_MCE_INTEL', 'y'), + cpu_sup_intel_not_set)] + l += [OR(KconfigCheck('self_protection', 'defconfig', 'X86_MCE_AMD', 'y'), + cpu_sup_amd_not_set)] l += [KconfigCheck('self_protection', 'defconfig', 'RETPOLINE', 'y')] l += [KconfigCheck('self_protection', 'defconfig', 'SYN_COOKIES', 'y')] # another reason? microcode_is_set = KconfigCheck('self_protection', 'defconfig', 'MICROCODE', 'y') l += [microcode_is_set] # is needed for mitigating CPU bugs l += [OR(KconfigCheck('self_protection', 'defconfig', 'MICROCODE_INTEL', 'y'), + cpu_sup_intel_not_set, AND(microcode_is_set, VersionCheck((6, 6, 0))))] # MICROCODE_INTEL was included in MICROCODE since v6.6 l += [OR(KconfigCheck('self_protection', 'defconfig', 'MICROCODE_AMD', 'y'), + cpu_sup_amd_not_set, AND(microcode_is_set, VersionCheck((6, 6, 0))))] # MICROCODE_AMD was included in MICROCODE since v6.6 l += [OR(KconfigCheck('self_protection', 'defconfig', 'X86_SMAP', 'y'), @@ -92,7 +96,8 @@ def add_kconfig_checks(l, arch): l += [KconfigCheck('self_protection', 'defconfig', 'PAGE_TABLE_ISOLATION', 'y')] l += [KconfigCheck('self_protection', 'defconfig', 'RANDOMIZE_MEMORY', 'y')] l += [KconfigCheck('self_protection', 'defconfig', 'X86_KERNEL_IBT', 'y')] - l += [KconfigCheck('self_protection', 'defconfig', 'CPU_SRSO', 'y')] + l += [OR(KconfigCheck('self_protection', 'defconfig', 'CPU_SRSO', 'y'), + cpu_sup_amd_not_set)] l += [AND(KconfigCheck('self_protection', 'defconfig', 'INTEL_IOMMU', 'y'), iommu_support_is_set)] l += [AND(KconfigCheck('self_protection', 'defconfig', 'AMD_IOMMU', 'y'), @@ -140,7 +145,8 @@ def add_kconfig_checks(l, arch): VersionCheck((6, 6, 8)))] # DEBUG_CREDENTIALS was dropped in v6.6.8 l += [OR(KconfigCheck('self_protection', 'kspp', 'DEBUG_NOTIFIERS', 'y'), AND(cfi_clang_is_set, - cfi_clang_permissive_not_set))] + cfi_clang_permissive_not_set, + cc_is_clang))] l += [OR(KconfigCheck('self_protection', 'kspp', 'SCHED_STACK_END_CHECK', 'y'), vmap_stack_is_set)] kfence_is_set = KconfigCheck('self_protection', 'kspp', 'KFENCE', 'y') @@ -160,7 +166,7 @@ def add_kconfig_checks(l, arch): l += [AND(KconfigCheck('self_protection', 'kspp', 'HARDENED_USERCOPY_PAGESPAN', 'is not set'), hardened_usercopy_is_set)] # this debugging for HARDENED_USERCOPY is not needed for security l += [AND(KconfigCheck('self_protection', 'kspp', 'GCC_PLUGIN_LATENT_ENTROPY', 'y'), - gcc_plugins_support_is_set)] + cc_is_gcc)] l += [OR(KconfigCheck('self_protection', 'kspp', 'MODULE_SIG', 'y'), modules_not_set)] l += [OR(KconfigCheck('self_protection', 'kspp', 'MODULE_SIG_ALL', 'y'), @@ -198,18 +204,21 @@ def add_kconfig_checks(l, arch): ubsan_bounds_is_set)] if arch in ('X86_64', 'ARM64', 'X86_32'): stackleak_is_set = KconfigCheck('self_protection', 'kspp', 'GCC_PLUGIN_STACKLEAK', 'y') - l += [AND(stackleak_is_set, gcc_plugins_support_is_set)] + l += [AND(stackleak_is_set, + cc_is_gcc)] l += [AND(KconfigCheck('self_protection', 'kspp', 'STACKLEAK_METRICS', 'is not set'), stackleak_is_set, - gcc_plugins_support_is_set)] + cc_is_gcc)] l += [AND(KconfigCheck('self_protection', 'kspp', 'STACKLEAK_RUNTIME_DISABLE', 'is not set'), stackleak_is_set, - gcc_plugins_support_is_set)] + cc_is_gcc)] l += [KconfigCheck('self_protection', 'kspp', 'RANDOMIZE_KSTACK_OFFSET_DEFAULT', 'y')] if arch in ('X86_64', 'ARM64'): - l += [cfi_clang_is_set] + l += [AND(cfi_clang_is_set, + cc_is_clang)] l += [AND(cfi_clang_permissive_not_set, - cfi_clang_is_set)] + cfi_clang_is_set, + cc_is_clang)] if arch in ('X86_64', 'X86_32'): l += [KconfigCheck('self_protection', 'kspp', 'HW_RANDOM_TPM', 'y')] l += [KconfigCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '65536')] @@ -272,7 +281,8 @@ def add_kconfig_checks(l, arch): l += [OR(KconfigCheck('cut_attack_surface', 'defconfig', 'STRICT_DEVMEM', 'y'), devmem_not_set)] # refers to LOCKDOWN if arch in ('X86_64', 'X86_32'): - l += [KconfigCheck('cut_attack_surface', 'defconfig', 'X86_INTEL_TSX_MODE_OFF', 'y')] # tsx=off + l += [OR(KconfigCheck('cut_attack_surface', 'defconfig', 'X86_INTEL_TSX_MODE_OFF', 'y'), # tsx=off + cpu_sup_intel_not_set)] # 'cut_attack_surface', 'kspp' l += [KconfigCheck('cut_attack_surface', 'kspp', 'SECURITY_DMESG_RESTRICT', 'y')] @@ -393,9 +403,11 @@ def add_kconfig_checks(l, arch): l += [KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'KGDB', 'is not set')] l += [KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'CORESIGHT', 'is not set')] l += [KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'XFS_SUPPORT_V4', 'is not set')] + l += [KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'MODULE_FORCE_LOAD', 'is not set')] + l += [KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'BLK_DEV_WRITE_MOUNTED', 'is not set')] l += [OR(KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'TRIM_UNUSED_KSYMS', 'y'), modules_not_set)] - l += [KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'MODULE_FORCE_LOAD', 'is not set')] + # 'harden_userspace' if arch == 'ARM64': @@ -405,6 +417,8 @@ def add_kconfig_checks(l, arch): l += [KconfigCheck('harden_userspace', 'defconfig', 'VMSPLIT_3G', 'y')] l += [KconfigCheck('harden_userspace', 'clipos', 'COREDUMP', 'is not set')] l += [KconfigCheck('harden_userspace', 'a13xp0p0v', 'ARCH_MMAP_RND_BITS', 'MAX')] # 'MAX' value is refined using ARCH_MMAP_RND_BITS_MAX + if arch == 'X86_64': + l += [KconfigCheck('harden_userspace', 'a13xp0p0v', 'X86_USER_SHADOW_STACK', 'y')] def add_cmdline_checks(l, arch): @@ -542,9 +556,12 @@ def add_cmdline_checks(l, arch): # 'cut_attack_surface', 'defconfig' if arch in ('X86_64', 'X86_32'): + tsx_not_set = CmdlineCheck('cut_attack_surface', 'defconfig', 'tsx', 'is not set') l += [OR(CmdlineCheck('cut_attack_surface', 'defconfig', 'tsx', 'off'), AND(KconfigCheck('cut_attack_surface', 'defconfig', 'X86_INTEL_TSX_MODE_OFF', 'y'), - CmdlineCheck('cut_attack_surface', 'defconfig', 'tsx', 'is not set')))] + tsx_not_set), + AND(KconfigCheck('cut_attack_surface', 'defconfig', 'CPU_SUP_INTEL', 'is not set'), + tsx_not_set))] # 'cut_attack_surface', 'kspp' l += [CmdlineCheck('cut_attack_surface', 'kspp', 'nosmt', 'is present')] # slow (high performance penalty) @@ -573,6 +590,9 @@ def add_cmdline_checks(l, arch): # 'cut_attack_surface', 'a13xp0p0v' l += [CmdlineCheck('cut_attack_surface', 'a13xp0p0v', 'sysrq_always_enabled', 'is not set')] + l += [OR(CmdlineCheck('cut_attack_surface', 'a13xp0p0v', 'bdev_allow_write_mounted', '0'), + AND(KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'BLK_DEV_WRITE_MOUNTED', 'is not set'), + CmdlineCheck('cut_attack_surface', 'a13xp0p0v', 'bdev_allow_write_mounted', 'is not set')))] if arch == 'X86_64': l += [OR(CmdlineCheck('cut_attack_surface', 'a13xp0p0v', 'ia32_emulation', '0'), KconfigCheck('cut_attack_surface', 'kspp', 'IA32_EMULATION', 'is not set'), @@ -647,7 +667,7 @@ def add_sysctl_checks(l, _arch): l += [SysctlCheck('cut_attack_surface', 'kspp', 'kernel.dmesg_restrict', '1')] l += [SysctlCheck('cut_attack_surface', 'kspp', 'kernel.perf_event_paranoid', '3')] # with a custom patch, see https://lwn.net/Articles/696216/ l += [SysctlCheck('cut_attack_surface', 'kspp', 'kernel.kexec_load_disabled', '1')] - l += [SysctlCheck('cut_attack_surface', 'kspp', 'user.max_user_namespaces', '0')] + l += [SysctlCheck('cut_attack_surface', 'kspp', 'user.max_user_namespaces', '0')] # may break the upower daemon in Ubuntu l += [SysctlCheck('cut_attack_surface', 'kspp', 'dev.tty.ldisc_autoload', '0')] l += [SysctlCheck('cut_attack_surface', 'kspp', 'kernel.unprivileged_bpf_disabled', '1')] l += [SysctlCheck('cut_attack_surface', 'kspp', 'kernel.kptr_restrict', '2')]