Commit 0db002da by Alexander Popov

Merge branch 'cmdline'

This is the feature for #46.
parents 12c2af7f 7831bae4
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
## Motivation ## Motivation
There are plenty of security hardening options in the Linux kernel. A lot of them are There are plenty of security hardening options for the Linux kernel. A lot of them are
not enabled by the major distros. We have to enable these options ourselves to not enabled by the major distros. We have to enable these options ourselves to
make our systems more secure. make our systems more secure.
But nobody likes checking configs manually. So let the computers do their job! But nobody likes checking configs manually. So let the computers do their job!
__kconfig-hardened-check.py__ helps me to check the Linux kernel Kconfig option list __kconfig-hardened-check.py__ helps me to check the Linux kernel options
against my security hardening preferences, which are based on the against my security hardening preferences, which are based on the
- [KSPP recommended settings][1], - [KSPP recommended settings][1],
...@@ -20,6 +20,8 @@ against my security hardening preferences, which are based on the ...@@ -20,6 +20,8 @@ against my security hardening preferences, which are based on the
- [SECURITY_LOCKDOWN_LSM][5] patchset, - [SECURITY_LOCKDOWN_LSM][5] patchset,
- Direct feedback from Linux kernel maintainers (see [#38][6], [#53][15], [#54][16], [#62][17]). - Direct feedback from Linux kernel maintainers (see [#38][6], [#53][15], [#54][16], [#62][17]).
This tool supports checking __Kconfig__ options and __kernel cmdline__ parameters.
I also created [__Linux Kernel Defence Map__][4] that is a graphical representation of the I also created [__Linux Kernel Defence Map__][4] that is a graphical representation of the
relationships between security hardening features and the corresponding vulnerability classes relationships between security hardening features and the corresponding vulnerability classes
or exploitation techniques. or exploitation techniques.
...@@ -49,6 +51,7 @@ Some Linux distributions also provide `kconfig-hardened-check` as a package. ...@@ -49,6 +51,7 @@ Some Linux distributions also provide `kconfig-hardened-check` as a package.
``` ```
usage: kconfig-hardened-check [-h] [--version] [-p {X86_64,X86_32,ARM64,ARM}] usage: kconfig-hardened-check [-h] [--version] [-p {X86_64,X86_32,ARM64,ARM}]
[-c CONFIG] [-c CONFIG]
[-l CMDLINE]
[-m {verbose,json,show_ok,show_fail}] [-m {verbose,json,show_ok,show_fail}]
A tool for checking the security hardening options of the Linux kernel A tool for checking the security hardening options of the Linux kernel
...@@ -59,7 +62,9 @@ optional arguments: ...@@ -59,7 +62,9 @@ optional arguments:
-p {X86_64,X86_32,ARM64,ARM}, --print {X86_64,X86_32,ARM64,ARM} -p {X86_64,X86_32,ARM64,ARM}, --print {X86_64,X86_32,ARM64,ARM}
print security hardening preferences for the selected architecture print security hardening preferences for the selected architecture
-c CONFIG, --config CONFIG -c CONFIG, --config CONFIG
check the kernel config file against these preferences check the kernel kconfig file against these preferences
-l CMDLINE, --cmdline CMDLINE
check the kernel cmdline file against these preferences
-m {verbose,json,show_ok,show_fail}, --mode {verbose,json,show_ok,show_fail} -m {verbose,json,show_ok,show_fail}, --mode {verbose,json,show_ok,show_fail}
choose the report mode choose the report mode
``` ```
...@@ -81,23 +86,24 @@ CONFIG_DEVMEM | is not set | kspp | cut_atta ...@@ -81,23 +86,24 @@ CONFIG_DEVMEM | is not set | kspp | cut_atta
- `-m show_ok` for showing only the successful checks - `-m show_ok` for showing only the successful checks
- `-m json` for printing the results in JSON format (for combining `kconfig-hardened-check` with other tools) - `-m json` for printing the results in JSON format (for combining `kconfig-hardened-check` with other tools)
## Example output for `Ubuntu 20.04 LTS (Focal Fossa)` kernel config ## Example output for `Fedora 34` kernel config
``` ```
$ ./bin/kconfig-hardened-check -c kconfig_hardened_check/config_files/distros/ubuntu-focal.config $ ./bin/kconfig-hardened-check -c /boot/config-5.16.20-100.fc34.x86_64 -l /proc/cmdline
[+] Kconfig file to check: kconfig_hardened_check/config_files/distros/ubuntu-focal.config [+] Kconfig file to check: /boot/config-5.16.20-100.fc34.x86_64
[+] Kernel cmdline file to check: /proc/cmdline
[+] Detected architecture: X86_64 [+] Detected architecture: X86_64
[+] Detected kernel version: 5.4 [+] Detected kernel version: 5.16
========================================================================================================================= =========================================================================================================================
option name | type |desired val | decision | reason | check result option name | type |desired val | decision | reason | check result
========================================================================================================================= =========================================================================================================================
CONFIG_BUG |kconfig| y |defconfig | self_protection | OK CONFIG_BUG |kconfig| y |defconfig | self_protection | OK
CONFIG_SLUB_DEBUG |kconfig| y |defconfig | self_protection | OK CONFIG_SLUB_DEBUG |kconfig| y |defconfig | self_protection | OK
CONFIG_GCC_PLUGINS |kconfig| y |defconfig | self_protection | FAIL: not found CONFIG_GCC_PLUGINS |kconfig| y |defconfig | self_protection | OK
CONFIG_STACKPROTECTOR |kconfig| y |defconfig | self_protection | OK CONFIG_STACKPROTECTOR |kconfig| y |defconfig | self_protection | OK
CONFIG_STACKPROTECTOR_STRONG |kconfig| y |defconfig | self_protection | OK CONFIG_STACKPROTECTOR_STRONG |kconfig| y |defconfig | self_protection | FAIL: "is not set"
CONFIG_STRICT_KERNEL_RWX |kconfig| y |defconfig | self_protection | OK CONFIG_STRICT_KERNEL_RWX |kconfig| y |defconfig | self_protection | OK
CONFIG_STRICT_MODULE_RWX |kconfig| y |defconfig | self_protection | OK CONFIG_STRICT_MODULE_RWX |kconfig| y |defconfig | self_protection | OK
CONFIG_REFCOUNT_FULL |kconfig| y |defconfig | self_protection | FAIL: "is not set" CONFIG_REFCOUNT_FULL |kconfig| y |defconfig | self_protection | OK: version >= 5.5
CONFIG_THREAD_INFO_IN_TASK |kconfig| y |defconfig | self_protection | OK CONFIG_THREAD_INFO_IN_TASK |kconfig| y |defconfig | self_protection | OK
CONFIG_IOMMU_SUPPORT |kconfig| y |defconfig | self_protection | OK CONFIG_IOMMU_SUPPORT |kconfig| y |defconfig | self_protection | OK
CONFIG_RANDOMIZE_BASE |kconfig| y |defconfig | self_protection | OK CONFIG_RANDOMIZE_BASE |kconfig| y |defconfig | self_protection | OK
...@@ -106,58 +112,58 @@ CONFIG_MICROCODE |kconfig| y |defconfig | self_p ...@@ -106,58 +112,58 @@ CONFIG_MICROCODE |kconfig| y |defconfig | self_p
CONFIG_RETPOLINE |kconfig| y |defconfig | self_protection | OK CONFIG_RETPOLINE |kconfig| y |defconfig | self_protection | OK
CONFIG_X86_SMAP |kconfig| y |defconfig | self_protection | OK CONFIG_X86_SMAP |kconfig| y |defconfig | self_protection | OK
CONFIG_SYN_COOKIES |kconfig| y |defconfig | self_protection | OK CONFIG_SYN_COOKIES |kconfig| y |defconfig | self_protection | OK
CONFIG_X86_UMIP |kconfig| y |defconfig | self_protection | OK: CONFIG_X86_INTEL_UMIP "y" CONFIG_X86_UMIP |kconfig| y |defconfig | self_protection | OK
CONFIG_PAGE_TABLE_ISOLATION |kconfig| y |defconfig | self_protection | OK CONFIG_PAGE_TABLE_ISOLATION |kconfig| y |defconfig | self_protection | OK
CONFIG_RANDOMIZE_MEMORY |kconfig| y |defconfig | self_protection | OK CONFIG_RANDOMIZE_MEMORY |kconfig| y |defconfig | self_protection | OK
CONFIG_INTEL_IOMMU |kconfig| y |defconfig | self_protection | OK CONFIG_INTEL_IOMMU |kconfig| y |defconfig | self_protection | OK
CONFIG_AMD_IOMMU |kconfig| y |defconfig | self_protection | OK CONFIG_AMD_IOMMU |kconfig| y |defconfig | self_protection | OK
CONFIG_SECURITY_DMESG_RESTRICT |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_SECURITY_DMESG_RESTRICT |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_BUG_ON_DATA_CORRUPTION |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_BUG_ON_DATA_CORRUPTION |kconfig| y | kspp | self_protection | OK
CONFIG_DEBUG_WX |kconfig| y | kspp | self_protection | OK CONFIG_DEBUG_WX |kconfig| y | kspp | self_protection | OK
CONFIG_SCHED_STACK_END_CHECK |kconfig| y | kspp | self_protection | OK CONFIG_SCHED_STACK_END_CHECK |kconfig| y | kspp | self_protection | OK
CONFIG_SLAB_FREELIST_HARDENED |kconfig| y | kspp | self_protection | OK CONFIG_SLAB_FREELIST_HARDENED |kconfig| y | kspp | self_protection | OK
CONFIG_SLAB_FREELIST_RANDOM |kconfig| y | kspp | self_protection | OK CONFIG_SLAB_FREELIST_RANDOM |kconfig| y | kspp | self_protection | OK
CONFIG_SHUFFLE_PAGE_ALLOCATOR |kconfig| y | kspp | self_protection | OK CONFIG_SHUFFLE_PAGE_ALLOCATOR |kconfig| y | kspp | self_protection | OK
CONFIG_FORTIFY_SOURCE |kconfig| y | kspp | self_protection | OK CONFIG_FORTIFY_SOURCE |kconfig| y | kspp | self_protection | OK
CONFIG_DEBUG_LIST |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_DEBUG_LIST |kconfig| y | kspp | self_protection | OK
CONFIG_DEBUG_SG |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_DEBUG_SG |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_DEBUG_CREDENTIALS |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_DEBUG_CREDENTIALS |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_DEBUG_NOTIFIERS |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_DEBUG_NOTIFIERS |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_INIT_ON_ALLOC_DEFAULT_ON |kconfig| y | kspp | self_protection | OK CONFIG_INIT_ON_ALLOC_DEFAULT_ON |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_GCC_PLUGIN_LATENT_ENTROPY |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_GCC_PLUGIN_LATENT_ENTROPY |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_KFENCE |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_KFENCE |kconfig| y | kspp | self_protection | OK
CONFIG_WERROR |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_WERROR |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_IOMMU_DEFAULT_DMA_STRICT |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_IOMMU_DEFAULT_DMA_STRICT |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_ZERO_CALL_USED_REGS |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_ZERO_CALL_USED_REGS |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_GCC_PLUGIN_RANDSTRUCT |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_GCC_PLUGIN_RANDSTRUCT |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_HARDENED_USERCOPY |kconfig| y | kspp | self_protection | OK CONFIG_HARDENED_USERCOPY |kconfig| y | kspp | self_protection | OK
CONFIG_HARDENED_USERCOPY_FALLBACK |kconfig| is not set | kspp | self_protection | FAIL: "y" CONFIG_HARDENED_USERCOPY_FALLBACK |kconfig| is not set | kspp | self_protection | OK: not found
CONFIG_HARDENED_USERCOPY_PAGESPAN |kconfig| is not set | kspp | self_protection | OK CONFIG_HARDENED_USERCOPY_PAGESPAN |kconfig| is not set | kspp | self_protection | OK: not found
CONFIG_MODULE_SIG |kconfig| y | kspp | self_protection | OK CONFIG_MODULE_SIG |kconfig| y | kspp | self_protection | OK
CONFIG_MODULE_SIG_ALL |kconfig| y | kspp | self_protection | OK CONFIG_MODULE_SIG_ALL |kconfig| y | kspp | self_protection | OK
CONFIG_MODULE_SIG_SHA512 |kconfig| y | kspp | self_protection | OK CONFIG_MODULE_SIG_SHA512 |kconfig| y | kspp | self_protection | OK
CONFIG_MODULE_SIG_FORCE |kconfig| y | kspp | self_protection | FAIL: "is not set" CONFIG_MODULE_SIG_FORCE |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_INIT_STACK_ALL_ZERO |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_INIT_STACK_ALL_ZERO |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_INIT_ON_FREE_DEFAULT_ON |kconfig| y | kspp | self_protection | OK: CONFIG_PAGE_POISONING_ZERO "y" CONFIG_INIT_ON_FREE_DEFAULT_ON |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_GCC_PLUGIN_STACKLEAK |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_GCC_PLUGIN_STACKLEAK |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_SCHED_CORE |kconfig| y | kspp | self_protection | FAIL: not found CONFIG_SCHED_CORE |kconfig| y | kspp | self_protection | OK
CONFIG_DEFAULT_MMAP_MIN_ADDR |kconfig| 65536 | kspp | self_protection | OK CONFIG_DEFAULT_MMAP_MIN_ADDR |kconfig| 65536 | kspp | self_protection | OK
CONFIG_UBSAN_BOUNDS |kconfig| y |maintainer| self_protection | FAIL: not found CONFIG_UBSAN_BOUNDS |kconfig| y |maintainer| self_protection | FAIL: not found
CONFIG_UBSAN_SANITIZE_ALL |kconfig| y |maintainer| self_protection | FAIL: CONFIG_UBSAN_BOUNDS not "y" CONFIG_UBSAN_SANITIZE_ALL |kconfig| y |maintainer| self_protection | FAIL: CONFIG_UBSAN_BOUNDS not "y"
CONFIG_UBSAN_TRAP |kconfig| y |maintainer| self_protection | FAIL: CONFIG_UBSAN_BOUNDS not "y" CONFIG_UBSAN_TRAP |kconfig| y |maintainer| self_protection | FAIL: CONFIG_UBSAN_BOUNDS not "y"
CONFIG_DEBUG_VIRTUAL |kconfig| y | clipos | self_protection | FAIL: "is not set" CONFIG_DEBUG_VIRTUAL |kconfig| y | clipos | self_protection | FAIL: "is not set"
CONFIG_STATIC_USERMODEHELPER |kconfig| y | clipos | self_protection | FAIL: "is not set" CONFIG_STATIC_USERMODEHELPER |kconfig| y | clipos | self_protection | FAIL: "is not set"
CONFIG_EFI_DISABLE_PCI_DMA |kconfig| y | clipos | self_protection | FAIL: not found CONFIG_EFI_DISABLE_PCI_DMA |kconfig| y | clipos | self_protection | FAIL: "is not set"
CONFIG_SLAB_MERGE_DEFAULT |kconfig| is not set | clipos | self_protection | FAIL: "y" CONFIG_SLAB_MERGE_DEFAULT |kconfig| is not set | clipos | self_protection | OK
CONFIG_RANDOM_TRUST_BOOTLOADER |kconfig| is not set | clipos | self_protection | FAIL: "y" CONFIG_RANDOM_TRUST_BOOTLOADER |kconfig| is not set | clipos | self_protection | OK
CONFIG_RANDOM_TRUST_CPU |kconfig| is not set | clipos | self_protection | FAIL: "y" CONFIG_RANDOM_TRUST_CPU |kconfig| is not set | clipos | self_protection | FAIL: "y"
CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE|kconfig| is not set | clipos | self_protection | FAIL: CONFIG_GCC_PLUGIN_RANDSTRUCT not "y" CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE|kconfig| is not set | clipos | self_protection | FAIL: CONFIG_GCC_PLUGIN_RANDSTRUCT not "y"
CONFIG_STACKLEAK_METRICS |kconfig| is not set | clipos | self_protection | FAIL: CONFIG_GCC_PLUGIN_STACKLEAK not "y" CONFIG_STACKLEAK_METRICS |kconfig| is not set | clipos | self_protection | FAIL: CONFIG_GCC_PLUGIN_STACKLEAK not "y"
CONFIG_STACKLEAK_RUNTIME_DISABLE |kconfig| is not set | clipos | self_protection | FAIL: CONFIG_GCC_PLUGIN_STACKLEAK not "y" CONFIG_STACKLEAK_RUNTIME_DISABLE |kconfig| is not set | clipos | self_protection | FAIL: CONFIG_GCC_PLUGIN_STACKLEAK not "y"
CONFIG_INTEL_IOMMU_DEFAULT_ON |kconfig| y | clipos | self_protection | FAIL: "is not set" CONFIG_INTEL_IOMMU_DEFAULT_ON |kconfig| y | clipos | self_protection | FAIL: "is not set"
CONFIG_INTEL_IOMMU_SVM |kconfig| y | clipos | self_protection | OK CONFIG_INTEL_IOMMU_SVM |kconfig| y | clipos | self_protection | OK
CONFIG_RESET_ATTACK_MITIGATION |kconfig| y | my | self_protection | OK CONFIG_RESET_ATTACK_MITIGATION |kconfig| y | my | self_protection | FAIL: "is not set"
CONFIG_SLS |kconfig| y | my | self_protection | FAIL: not found CONFIG_SLS |kconfig| y | my | self_protection | FAIL: not found
CONFIG_AMD_IOMMU_V2 |kconfig| y | my | self_protection | FAIL: "m" CONFIG_AMD_IOMMU_V2 |kconfig| y | my | self_protection | FAIL: "m"
CONFIG_SECURITY |kconfig| y |defconfig | security_policy | OK CONFIG_SECURITY |kconfig| y |defconfig | security_policy | OK
...@@ -167,34 +173,34 @@ CONFIG_SECURITY_LOCKDOWN_LSM |kconfig| y | clipos | securi ...@@ -167,34 +173,34 @@ CONFIG_SECURITY_LOCKDOWN_LSM |kconfig| y | clipos | securi
CONFIG_SECURITY_LOCKDOWN_LSM_EARLY |kconfig| y | clipos | security_policy | OK CONFIG_SECURITY_LOCKDOWN_LSM_EARLY |kconfig| y | clipos | security_policy | OK
CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY|kconfig| y | clipos | security_policy | FAIL: "is not set" CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY|kconfig| y | clipos | security_policy | FAIL: "is not set"
CONFIG_SECURITY_WRITABLE_HOOKS |kconfig| is not set | my | security_policy | OK: not found CONFIG_SECURITY_WRITABLE_HOOKS |kconfig| is not set | my | security_policy | OK: not found
CONFIG_SECURITY_SAFESETID |kconfig| y | my | security_policy | OK CONFIG_SECURITY_SAFESETID |kconfig| y | my | security_policy | FAIL: "is not set"
CONFIG_SECURITY_LOADPIN |kconfig| y | my | security_policy | FAIL: "is not set" CONFIG_SECURITY_LOADPIN |kconfig| y | my | security_policy | FAIL: "is not set"
CONFIG_SECURITY_LOADPIN_ENFORCE |kconfig| y | my | security_policy | FAIL: CONFIG_SECURITY_LOADPIN not "y" CONFIG_SECURITY_LOADPIN_ENFORCE |kconfig| y | my | security_policy | FAIL: CONFIG_SECURITY_LOADPIN not "y"
CONFIG_BPF_UNPRIV_DEFAULT_OFF |kconfig| y |defconfig |cut_attack_surface| FAIL: not found CONFIG_BPF_UNPRIV_DEFAULT_OFF |kconfig| y |defconfig |cut_attack_surface| OK
CONFIG_SECCOMP |kconfig| y |defconfig |cut_attack_surface| OK CONFIG_SECCOMP |kconfig| y |defconfig |cut_attack_surface| OK
CONFIG_SECCOMP_FILTER |kconfig| y |defconfig |cut_attack_surface| OK CONFIG_SECCOMP_FILTER |kconfig| y |defconfig |cut_attack_surface| OK
CONFIG_STRICT_DEVMEM |kconfig| y |defconfig |cut_attack_surface| OK CONFIG_STRICT_DEVMEM |kconfig| y |defconfig |cut_attack_surface| OK
CONFIG_ACPI_CUSTOM_METHOD |kconfig| is not set | kspp |cut_attack_surface| OK CONFIG_ACPI_CUSTOM_METHOD |kconfig| is not set | kspp |cut_attack_surface| OK
CONFIG_COMPAT_BRK |kconfig| is not set | kspp |cut_attack_surface| OK CONFIG_COMPAT_BRK |kconfig| is not set | kspp |cut_attack_surface| OK
CONFIG_DEVKMEM |kconfig| is not set | kspp |cut_attack_surface| OK CONFIG_DEVKMEM |kconfig| is not set | kspp |cut_attack_surface| OK: not found
CONFIG_COMPAT_VDSO |kconfig| is not set | kspp |cut_attack_surface| OK CONFIG_COMPAT_VDSO |kconfig| is not set | kspp |cut_attack_surface| OK
CONFIG_BINFMT_MISC |kconfig| is not set | kspp |cut_attack_surface| FAIL: "m" CONFIG_BINFMT_MISC |kconfig| is not set | kspp |cut_attack_surface| FAIL: "m"
CONFIG_INET_DIAG |kconfig| is not set | kspp |cut_attack_surface| FAIL: "m" CONFIG_INET_DIAG |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_KEXEC |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_KEXEC |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_PROC_KCORE |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_PROC_KCORE |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_LEGACY_PTYS |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_LEGACY_PTYS |kconfig| is not set | kspp |cut_attack_surface| OK
CONFIG_HIBERNATION |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_HIBERNATION |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_IA32_EMULATION |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_IA32_EMULATION |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_X86_X32 |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_X86_X32 |kconfig| is not set | kspp |cut_attack_surface| OK
CONFIG_MODIFY_LDT_SYSCALL |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_MODIFY_LDT_SYSCALL |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_OABI_COMPAT |kconfig| is not set | kspp |cut_attack_surface| OK: not found CONFIG_OABI_COMPAT |kconfig| is not set | kspp |cut_attack_surface| OK: not found
CONFIG_X86_MSR |kconfig| is not set | kspp |cut_attack_surface| FAIL: "m" CONFIG_X86_MSR |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_MODULES |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_MODULES |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_DEVMEM |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y" CONFIG_DEVMEM |kconfig| is not set | kspp |cut_attack_surface| FAIL: "y"
CONFIG_IO_STRICT_DEVMEM |kconfig| y | kspp |cut_attack_surface| FAIL: "is not set" CONFIG_IO_STRICT_DEVMEM |kconfig| y | kspp |cut_attack_surface| OK
CONFIG_LEGACY_VSYSCALL_NONE |kconfig| y | kspp |cut_attack_surface| FAIL: "is not set" CONFIG_LEGACY_VSYSCALL_NONE |kconfig| y | kspp |cut_attack_surface| FAIL: "is not set"
CONFIG_ZSMALLOC_STAT |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_ZSMALLOC_STAT |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_PAGE_OWNER |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_PAGE_OWNER |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_DEBUG_KMEMLEAK |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_DEBUG_KMEMLEAK |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_BINFMT_AOUT |kconfig| is not set | grsec |cut_attack_surface| OK: not found CONFIG_BINFMT_AOUT |kconfig| is not set | grsec |cut_attack_surface| OK: not found
CONFIG_KPROBE_EVENTS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_KPROBE_EVENTS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
...@@ -206,31 +212,31 @@ CONFIG_HIST_TRIGGERS |kconfig| is not set | grsec |cut_att ...@@ -206,31 +212,31 @@ CONFIG_HIST_TRIGGERS |kconfig| is not set | grsec |cut_att
CONFIG_BLK_DEV_IO_TRACE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_BLK_DEV_IO_TRACE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_PROC_VMCORE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_PROC_VMCORE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_PROC_PAGE_MONITOR |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_PROC_PAGE_MONITOR |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_USELIB |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_USELIB |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_CHECKPOINT_RESTORE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_CHECKPOINT_RESTORE |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_USERFAULTFD |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_USERFAULTFD |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_HWPOISON_INJECT |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_HWPOISON_INJECT |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m"
CONFIG_MEM_SOFT_DIRTY |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_MEM_SOFT_DIRTY |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_DEVPORT |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_DEVPORT |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_DEBUG_FS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_DEBUG_FS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_NOTIFIER_ERROR_INJECTION |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_NOTIFIER_ERROR_INJECTION |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_FAIL_FUTEX |kconfig| is not set | grsec |cut_attack_surface| OK: not found CONFIG_FAIL_FUTEX |kconfig| is not set | grsec |cut_attack_surface| OK: not found
CONFIG_PUNIT_ATOM_DEBUG |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_PUNIT_ATOM_DEBUG |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_ACPI_CONFIGFS |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_ACPI_CONFIGFS |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_EDAC_DEBUG |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_EDAC_DEBUG |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_DRM_I915_DEBUG |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_DRM_I915_DEBUG |kconfig| is not set | grsec |cut_attack_surface| OK: not found
CONFIG_BCACHE_CLOSURES_DEBUG |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_BCACHE_CLOSURES_DEBUG |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_DVB_C8SECTPFE |kconfig| is not set | grsec |cut_attack_surface| OK: not found CONFIG_DVB_C8SECTPFE |kconfig| is not set | grsec |cut_attack_surface| OK: not found
CONFIG_MTD_SLRAM |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_MTD_SLRAM |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_MTD_PHRAM |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m" CONFIG_MTD_PHRAM |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_IO_URING |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_IO_URING |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_KCMP |kconfig| is not set | grsec |cut_attack_surface| OK: not found CONFIG_KCMP |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_RSEQ |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_RSEQ |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_LATENCYTOP |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_LATENCYTOP |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_KCOV |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_KCOV |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_PROVIDE_OHCI1394_DMA_INIT |kconfig| is not set | grsec |cut_attack_surface| OK CONFIG_PROVIDE_OHCI1394_DMA_INIT |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_SUNRPC_DEBUG |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y" CONFIG_SUNRPC_DEBUG |kconfig| is not set | grsec |cut_attack_surface| FAIL: "y"
CONFIG_PTDUMP_DEBUGFS |kconfig| is not set | grsec |cut_attack_surface| OK: not found CONFIG_PTDUMP_DEBUGFS |kconfig| is not set | grsec |cut_attack_surface| OK
CONFIG_DRM_LEGACY |kconfig| is not set |maintainer|cut_attack_surface| OK CONFIG_DRM_LEGACY |kconfig| is not set |maintainer|cut_attack_surface| OK
CONFIG_FB |kconfig| is not set |maintainer|cut_attack_surface| FAIL: "y" CONFIG_FB |kconfig| is not set |maintainer|cut_attack_surface| FAIL: "y"
CONFIG_VT |kconfig| is not set |maintainer|cut_attack_surface| FAIL: "y" CONFIG_VT |kconfig| is not set |maintainer|cut_attack_surface| FAIL: "y"
...@@ -244,10 +250,10 @@ CONFIG_X86_VSYSCALL_EMULATION |kconfig| is not set | clipos |cut_att ...@@ -244,10 +250,10 @@ CONFIG_X86_VSYSCALL_EMULATION |kconfig| is not set | clipos |cut_att
CONFIG_MAGIC_SYSRQ |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_MAGIC_SYSRQ |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_KEXEC_FILE |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_KEXEC_FILE |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_USER_NS |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_USER_NS |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_X86_CPUID |kconfig| is not set | clipos |cut_attack_surface| FAIL: "m" CONFIG_X86_CPUID |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_X86_IOPL_IOPERM |kconfig| is not set | clipos |cut_attack_surface| OK: not found CONFIG_X86_IOPL_IOPERM |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_ACPI_TABLE_UPGRADE |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_ACPI_TABLE_UPGRADE |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_EFI_CUSTOM_SSDT_OVERLAYS |kconfig| is not set | clipos |cut_attack_surface| OK: not found CONFIG_EFI_CUSTOM_SSDT_OVERLAYS |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_LDISC_AUTOLOAD |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y" CONFIG_LDISC_AUTOLOAD |kconfig| is not set | clipos |cut_attack_surface| FAIL: "y"
CONFIG_X86_INTEL_TSX_MODE_OFF |kconfig| y | clipos |cut_attack_surface| OK CONFIG_X86_INTEL_TSX_MODE_OFF |kconfig| y | clipos |cut_attack_surface| OK
CONFIG_BPF_SYSCALL |kconfig| is not set | lockdown |cut_attack_surface| FAIL: "y" CONFIG_BPF_SYSCALL |kconfig| is not set | lockdown |cut_attack_surface| FAIL: "y"
...@@ -257,15 +263,17 @@ CONFIG_KPROBES |kconfig| is not set | lockdown |cut_att ...@@ -257,15 +263,17 @@ CONFIG_KPROBES |kconfig| is not set | lockdown |cut_att
CONFIG_TRIM_UNUSED_KSYMS |kconfig| y | my |cut_attack_surface| FAIL: not found CONFIG_TRIM_UNUSED_KSYMS |kconfig| y | my |cut_attack_surface| FAIL: not found
CONFIG_MMIOTRACE |kconfig| is not set | my |cut_attack_surface| FAIL: "y" CONFIG_MMIOTRACE |kconfig| is not set | my |cut_attack_surface| FAIL: "y"
CONFIG_LIVEPATCH |kconfig| is not set | my |cut_attack_surface| FAIL: "y" CONFIG_LIVEPATCH |kconfig| is not set | my |cut_attack_surface| FAIL: "y"
CONFIG_IP_DCCP |kconfig| is not set | my |cut_attack_surface| FAIL: "m" CONFIG_IP_DCCP |kconfig| is not set | my |cut_attack_surface| OK
CONFIG_IP_SCTP |kconfig| is not set | my |cut_attack_surface| FAIL: "m" CONFIG_IP_SCTP |kconfig| is not set | my |cut_attack_surface| FAIL: "m"
CONFIG_FTRACE |kconfig| is not set | my |cut_attack_surface| FAIL: "y" CONFIG_FTRACE |kconfig| is not set | my |cut_attack_surface| FAIL: "y"
CONFIG_VIDEO_VIVID |kconfig| is not set | my |cut_attack_surface| FAIL: "m" CONFIG_VIDEO_VIVID |kconfig| is not set | my |cut_attack_surface| OK: not found
CONFIG_INPUT_EVBUG |kconfig| is not set | my |cut_attack_surface| FAIL: "m" CONFIG_INPUT_EVBUG |kconfig| is not set | my |cut_attack_surface| OK
CONFIG_KGDB |kconfig| is not set | my |cut_attack_surface| FAIL: "y"
CONFIG_INTEGRITY |kconfig| y |defconfig | harden_userspace | OK CONFIG_INTEGRITY |kconfig| y |defconfig | harden_userspace | OK
CONFIG_ARCH_MMAP_RND_BITS |kconfig| 32 | clipos | harden_userspace | FAIL: "28" CONFIG_ARCH_MMAP_RND_BITS |kconfig| 32 | clipos | harden_userspace | FAIL: "28"
pti |cmdline| on | kspp | self_protection | FAIL: not found
[+] Config check is finished: 'OK' - 71 / 'FAIL' - 103 [+] Config check is finished: 'OK' - 82 / 'FAIL' - 94
``` ```
## kconfig-hardened-check versioning ## kconfig-hardened-check versioning
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
# #
# #
# N.B Hardening command line parameters: # N.B Hardening command line parameters:
# slab_nomerge
# page_alloc.shuffle=1 # page_alloc.shuffle=1
# iommu=force (does it help against DMA attacks?) # iommu=force (does it help against DMA attacks?)
# iommu.passthrough=0 # iommu.passthrough=0
...@@ -21,14 +20,12 @@ ...@@ -21,14 +20,12 @@
# init_on_free=1 (since v5.3, otherwise slub_debug=P and page_poison=1) # init_on_free=1 (since v5.3, otherwise slub_debug=P and page_poison=1)
# loadpin.enforce=1 # loadpin.enforce=1
# debugfs=no-mount (or off if possible) # debugfs=no-mount (or off if possible)
# randomize_kstack_offset=1
# #
# Mitigations of CPU vulnerabilities: # Mitigations of CPU vulnerabilities:
# Аrch-independent: # Аrch-independent:
# mitigations=auto,nosmt (nosmt is slow) # mitigations=auto,nosmt (nosmt is slow)
# X86: # X86:
# spectre_v2=on # spectre_v2=on
# pti=on
# spec_store_bypass_disable=on # spec_store_bypass_disable=on
# l1tf=full,force # l1tf=full,force
# l1d_flush=on (a part of the l1tf option) # l1d_flush=on (a part of the l1tf option)
...@@ -39,6 +36,7 @@ ...@@ -39,6 +36,7 @@
# ssbd=force-on # ssbd=force-on
# #
# Should NOT be set: # Should NOT be set:
# slab_merge
# nokaslr # nokaslr
# rodata=off # rodata=off
# sysrq_always_enabled # sysrq_always_enabled
...@@ -85,7 +83,7 @@ import re ...@@ -85,7 +83,7 @@ import re
import json import json
from .__about__ import __version__ from .__about__ import __version__
TYPES_OF_CHECKS = ('kconfig', 'version') SIMPLE_OPTION_TYPES = ('kconfig', 'version', 'cmdline')
class OptCheck: class OptCheck:
# Constructor without the 'expected' parameter is for option presence checks (any value is OK) # Constructor without the 'expected' parameter is for option presence checks (any value is OK)
...@@ -132,6 +130,12 @@ class OptCheck: ...@@ -132,6 +130,12 @@ class OptCheck:
if with_results: if with_results:
print('| {}'.format(self.result), end='') print('| {}'.format(self.result), end='')
def json_dump(self, with_results):
dump = [self.name, self.type, self.expected, self.decision, self.reason]
if with_results:
dump.append(self.result)
return dump
class KconfigCheck(OptCheck): class KconfigCheck(OptCheck):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
...@@ -142,11 +146,11 @@ class KconfigCheck(OptCheck): ...@@ -142,11 +146,11 @@ class KconfigCheck(OptCheck):
def type(self): def type(self):
return 'kconfig' return 'kconfig'
def json_dump(self, with_results):
dump = [self.name, self.type, self.expected, self.decision, self.reason] class CmdlineCheck(OptCheck):
if with_results: @property
dump.append(self.result) def type(self):
return dump return 'cmdline'
class VersionCheck: class VersionCheck:
...@@ -185,7 +189,7 @@ class ComplexOptCheck: ...@@ -185,7 +189,7 @@ class ComplexOptCheck:
sys.exit('[!] ERROR: empty {} check'.format(self.__class__.__name__)) sys.exit('[!] ERROR: empty {} check'.format(self.__class__.__name__))
if len(self.opts) == 1: if len(self.opts) == 1:
sys.exit('[!] ERROR: useless {} check'.format(self.__class__.__name__)) sys.exit('[!] ERROR: useless {} check'.format(self.__class__.__name__))
if not isinstance(opts[0], KconfigCheck): if not isinstance(opts[0], KconfigCheck) and not isinstance(opts[0], CmdlineCheck):
sys.exit('[!] ERROR: invalid {} check: {}'.format(self.__class__.__name__, opts)) sys.exit('[!] ERROR: invalid {} check: {}'.format(self.__class__.__name__, opts))
self.result = None self.result = None
...@@ -433,7 +437,8 @@ def add_kconfig_checks(l, arch): ...@@ -433,7 +437,8 @@ def add_kconfig_checks(l, arch):
if arch in ('X86_64', 'ARM64', 'X86_32'): if arch in ('X86_64', 'ARM64', 'X86_32'):
stackleak_is_set = KconfigCheck('self_protection', 'kspp', 'GCC_PLUGIN_STACKLEAK', 'y') stackleak_is_set = KconfigCheck('self_protection', 'kspp', 'GCC_PLUGIN_STACKLEAK', 'y')
l += [stackleak_is_set] l += [stackleak_is_set]
l += [KconfigCheck('self_protection', 'kspp', 'RANDOMIZE_KSTACK_OFFSET_DEFAULT', 'y')] l += [OR(KconfigCheck('self_protection', 'kspp', 'RANDOMIZE_KSTACK_OFFSET_DEFAULT', 'y'),
CmdlineCheck('self_protection', 'kspp', 'randomize_kstack_offset', '1'))]
if arch in ('X86_64', 'X86_32'): if arch in ('X86_64', 'X86_32'):
l += [KconfigCheck('self_protection', 'kspp', 'SCHED_CORE', 'y')] l += [KconfigCheck('self_protection', 'kspp', 'SCHED_CORE', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '65536')] l += [KconfigCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '65536')]
...@@ -461,7 +466,8 @@ def add_kconfig_checks(l, arch): ...@@ -461,7 +466,8 @@ def add_kconfig_checks(l, arch):
l += [KconfigCheck('self_protection', 'clipos', 'STATIC_USERMODEHELPER', 'y')] # needs userspace support l += [KconfigCheck('self_protection', 'clipos', 'STATIC_USERMODEHELPER', 'y')] # needs userspace support
l += [OR(KconfigCheck('self_protection', 'clipos', 'EFI_DISABLE_PCI_DMA', 'y'), l += [OR(KconfigCheck('self_protection', 'clipos', 'EFI_DISABLE_PCI_DMA', 'y'),
efi_not_set)] efi_not_set)]
l += [KconfigCheck('self_protection', 'clipos', 'SLAB_MERGE_DEFAULT', 'is not set')] # slab_nomerge l += [OR(KconfigCheck('self_protection', 'clipos', 'SLAB_MERGE_DEFAULT', 'is not set'),
CmdlineCheck('self_protection', 'kspp', 'slab_nomerge'))] # option presence check
l += [KconfigCheck('self_protection', 'clipos', 'RANDOM_TRUST_BOOTLOADER', 'is not set')] l += [KconfigCheck('self_protection', 'clipos', 'RANDOM_TRUST_BOOTLOADER', 'is not set')]
l += [KconfigCheck('self_protection', 'clipos', 'RANDOM_TRUST_CPU', 'is not set')] l += [KconfigCheck('self_protection', 'clipos', 'RANDOM_TRUST_CPU', 'is not set')]
l += [AND(KconfigCheck('self_protection', 'clipos', 'GCC_PLUGIN_RANDSTRUCT_PERFORMANCE', 'is not set'), l += [AND(KconfigCheck('self_protection', 'clipos', 'GCC_PLUGIN_RANDSTRUCT_PERFORMANCE', 'is not set'),
...@@ -650,6 +656,15 @@ def add_kconfig_checks(l, arch): ...@@ -650,6 +656,15 @@ def add_kconfig_checks(l, arch):
# l += [KconfigCheck('feature_test', 'my', 'LKDTM', 'm')] # only for debugging! # l += [KconfigCheck('feature_test', 'my', 'LKDTM', 'm')] # only for debugging!
def add_cmdline_checks(l, arch):
# Calling the CmdlineCheck class constructor:
# CmdlineCheck(reason, decision, name, expected)
if arch in ('X86_64', 'X86_32'):
l += [CmdlineCheck('self_protection', 'kspp', 'pti', 'on')]
# TODO: add other
def print_unknown_options(checklist, parsed_options): def print_unknown_options(checklist, parsed_options):
known_options = [] known_options = []
...@@ -724,15 +739,15 @@ def print_checklist(mode, checklist, with_results): ...@@ -724,15 +739,15 @@ def print_checklist(mode, checklist, with_results):
def populate_simple_opt_with_data(opt, data, data_type): def populate_simple_opt_with_data(opt, data, data_type):
if opt.type == 'complex': if opt.type == 'complex':
sys.exit('[!] ERROR: unexpected ComplexOptCheck {}: {}'.format(opt.name, vars(opt))) sys.exit('[!] ERROR: unexpected ComplexOptCheck {}: {}'.format(opt.name, vars(opt)))
if opt.type not in TYPES_OF_CHECKS: if opt.type not in SIMPLE_OPTION_TYPES:
sys.exit('[!] ERROR: invalid opt type "{}" for {}'.format(opt.type, opt.name)) sys.exit('[!] ERROR: invalid opt type "{}" for {}'.format(opt.type, opt.name))
if data_type not in TYPES_OF_CHECKS: if data_type not in SIMPLE_OPTION_TYPES:
sys.exit('[!] ERROR: invalid data type "{}"'.format(data_type)) sys.exit('[!] ERROR: invalid data type "{}"'.format(data_type))
if data_type != opt.type: if data_type != opt.type:
return return
if data_type == 'kconfig': if data_type in ('kconfig', 'cmdline'):
opt.state = data.get(opt.name, None) opt.state = data.get(opt.name, None)
elif data_type == 'version': elif data_type == 'version':
opt.ver = data opt.ver = data
...@@ -749,7 +764,7 @@ def populate_opt_with_data(opt, data, data_type): ...@@ -749,7 +764,7 @@ def populate_opt_with_data(opt, data, data_type):
else: else:
populate_simple_opt_with_data(o, data, data_type) populate_simple_opt_with_data(o, data, data_type)
else: else:
if opt.type != 'kconfig': if opt.type not in ('kconfig', 'cmdline'):
sys.exit('[!] ERROR: bad type "{}" for a simple check {}'.format(opt.type, opt.name)) sys.exit('[!] ERROR: bad type "{}" for a simple check {}'.format(opt.type, opt.name))
populate_simple_opt_with_data(opt, data, data_type) populate_simple_opt_with_data(opt, data, data_type)
...@@ -788,6 +803,24 @@ def parse_kconfig_file(parsed_options, fname): ...@@ -788,6 +803,24 @@ def parse_kconfig_file(parsed_options, fname):
parsed_options[option] = value parsed_options[option] = value
def parse_cmdline_file(parsed_options, fname):
with open(fname, 'r') as f:
line = f.readline()
opts = line.split()
line = f.readline()
if line:
sys.exit('[!] ERROR: more than one line in "{}"'.format(fname))
for opt in opts:
if '=' in opt:
name, value = opt.split('=', 1)
else:
name = opt
value = '' # '' is not None
parsed_options[name] = value
def main(): def main():
# Report modes: # Report modes:
# * verbose mode for # * verbose mode for
...@@ -803,6 +836,8 @@ def main(): ...@@ -803,6 +836,8 @@ def main():
help='print security hardening preferences for the selected architecture') help='print security hardening preferences for the selected architecture')
parser.add_argument('-c', '--config', parser.add_argument('-c', '--config',
help='check the kernel kconfig file against these preferences') help='check the kernel kconfig file against these preferences')
parser.add_argument('-l', '--cmdline',
help='check the kernel cmdline file against these preferences')
parser.add_argument('-m', '--mode', choices=report_modes, parser.add_argument('-m', '--mode', choices=report_modes,
help='choose the report mode') help='choose the report mode')
args = parser.parse_args() args = parser.parse_args()
...@@ -818,6 +853,8 @@ def main(): ...@@ -818,6 +853,8 @@ def main():
if args.config: if args.config:
if mode != 'json': if mode != 'json':
print('[+] Kconfig file to check: {}'.format(args.config)) print('[+] Kconfig file to check: {}'.format(args.config))
if args.cmdline:
print('[+] Kernel cmdline file to check: {}'.format(args.cmdline))
arch, msg = detect_arch(args.config, supported_archs) arch, msg = detect_arch(args.config, supported_archs)
if not arch: if not arch:
...@@ -840,6 +877,15 @@ def main(): ...@@ -840,6 +877,15 @@ def main():
populate_with_data(config_checklist, parsed_kconfig_options, 'kconfig') populate_with_data(config_checklist, parsed_kconfig_options, 'kconfig')
populate_with_data(config_checklist, kernel_version, 'version') populate_with_data(config_checklist, kernel_version, 'version')
if args.cmdline:
# add relevant cmdline checks to the checklist
add_cmdline_checks(config_checklist, arch)
# populate the checklist with the parsed kconfig data
parsed_cmdline_options = OrderedDict()
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 for performing the checks
perform_checks(config_checklist) perform_checks(config_checklist)
...@@ -849,12 +895,15 @@ def main(): ...@@ -849,12 +895,15 @@ def main():
print_checklist(mode, config_checklist, True) print_checklist(mode, config_checklist, True)
sys.exit(0) sys.exit(0)
elif args.cmdline:
sys.exit('[!] ERROR: checking cmdline doesn\'t work without checking kconfig')
if args.print: if args.print:
if mode in ('show_ok', 'show_fail'): if mode in ('show_ok', 'show_fail'):
sys.exit('[!] ERROR: wrong mode "{}" for --print'.format(mode)) sys.exit('[!] ERROR: wrong mode "{}" for --print'.format(mode))
arch = args.print arch = args.print
add_kconfig_checks(config_checklist, arch) add_kconfig_checks(config_checklist, arch)
add_cmdline_checks(config_checklist, arch)
if mode != 'json': if mode != 'json':
print('[+] Printing kernel security hardening preferences for {}...'.format(arch)) print('[+] Printing kernel security hardening preferences for {}...'.format(arch))
print_checklist(mode, config_checklist, False) print_checklist(mode, config_checklist, False)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment