Commit 0db002da by Alexander Popov

Merge branch 'cmdline'

This is the feature for #46.
parents 12c2af7f 7831bae4
......@@ -5,13 +5,13 @@
## 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
make our systems more secure.
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
- [KSPP recommended settings][1],
......@@ -20,6 +20,8 @@ against my security hardening preferences, which are based on the
- [SECURITY_LOCKDOWN_LSM][5] patchset,
- 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
relationships between security hardening features and the corresponding vulnerability classes
or exploitation techniques.
......@@ -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}]
[-c CONFIG]
[-l CMDLINE]
[-m {verbose,json,show_ok,show_fail}]
A tool for checking the security hardening options of the Linux kernel
......@@ -59,7 +62,9 @@ optional arguments:
-p {X86_64,X86_32,ARM64,ARM}, --print {X86_64,X86_32,ARM64,ARM}
print security hardening preferences for the selected architecture
-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}
choose the report mode
```
......@@ -81,23 +86,24 @@ CONFIG_DEVMEM | is not set | kspp | cut_atta
- `-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)
## 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
[+] Kconfig file to check: 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: /boot/config-5.16.20-100.fc34.x86_64
[+] Kernel cmdline file to check: /proc/cmdline
[+] Detected architecture: X86_64
[+] Detected kernel version: 5.4
[+] Detected kernel version: 5.16
=========================================================================================================================
option name | type |desired val | decision | reason | check result
=========================================================================================================================
CONFIG_BUG |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_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_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_IOMMU_SUPPORT |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
CONFIG_RETPOLINE |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_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_RANDOMIZE_MEMORY |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_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_SCHED_STACK_END_CHECK |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_SHUFFLE_PAGE_ALLOCATOR |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_CREDENTIALS |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_GCC_PLUGIN_LATENT_ENTROPY |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_KFENCE |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_WERROR |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_IOMMU_DEFAULT_DMA_STRICT |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_ZERO_CALL_USED_REGS |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_GCC_PLUGIN_RANDSTRUCT |kconfig| y | kspp | self_protection | FAIL: not found
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: "is not set"
CONFIG_KFENCE |kconfig| y | kspp | self_protection | OK
CONFIG_WERROR |kconfig| y | kspp | self_protection | FAIL: "is not set"
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: "is not set"
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_FALLBACK |kconfig| is not set | kspp | self_protection | FAIL: "y"
CONFIG_HARDENED_USERCOPY_PAGESPAN |kconfig| is not set | kspp | self_protection | OK
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: not found
CONFIG_MODULE_SIG |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_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_ON_FREE_DEFAULT_ON |kconfig| y | kspp | self_protection | OK: CONFIG_PAGE_POISONING_ZERO "y"
CONFIG_GCC_PLUGIN_STACKLEAK |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT |kconfig| y | kspp | self_protection | FAIL: not found
CONFIG_SCHED_CORE |kconfig| y | kspp | self_protection | FAIL: not found
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: "is not set"
CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT |kconfig| y | kspp | self_protection | FAIL: "is not set"
CONFIG_SCHED_CORE |kconfig| y | 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_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_DEBUG_VIRTUAL |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_SLAB_MERGE_DEFAULT |kconfig| is not set | clipos | self_protection | FAIL: "y"
CONFIG_RANDOM_TRUST_BOOTLOADER |kconfig| is not set | clipos | self_protection | FAIL: "y"
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 | OK
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_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_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_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_AMD_IOMMU_V2 |kconfig| y | my | self_protection | FAIL: "m"
CONFIG_SECURITY |kconfig| y |defconfig | security_policy | OK
......@@ -167,34 +173,34 @@ CONFIG_SECURITY_LOCKDOWN_LSM |kconfig| y | clipos | securi
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_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_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_FILTER |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_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_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_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_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_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_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_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_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"
......@@ -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_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_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_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_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_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_PUNIT_ATOM_DEBUG |kconfig| is not set | grsec |cut_attack_surface| FAIL: "m"
CONFIG_ACPI_CONFIGFS |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| 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_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_PHRAM |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| OK
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_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_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_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_FB |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
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_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_IOPL_IOPERM |kconfig| is not set | clipos |cut_attack_surface| OK: not found
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| 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_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"
......@@ -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_MMIOTRACE |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_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_INPUT_EVBUG |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| OK
CONFIG_KGDB |kconfig| is not set | my |cut_attack_surface| FAIL: "y"
CONFIG_INTEGRITY |kconfig| y |defconfig | harden_userspace | OK
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
......
......@@ -11,7 +11,6 @@
#
#
# N.B Hardening command line parameters:
# slab_nomerge
# page_alloc.shuffle=1
# iommu=force (does it help against DMA attacks?)
# iommu.passthrough=0
......@@ -21,14 +20,12 @@
# 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 (nosmt is slow)
# X86:
# spectre_v2=on
# pti=on
# spec_store_bypass_disable=on
# l1tf=full,force
# l1d_flush=on (a part of the l1tf option)
......@@ -39,6 +36,7 @@
# ssbd=force-on
#
# Should NOT be set:
# slab_merge
# nokaslr
# rodata=off
# sysrq_always_enabled
......@@ -85,7 +83,7 @@ import re
import json
from .__about__ import __version__
TYPES_OF_CHECKS = ('kconfig', 'version')
SIMPLE_OPTION_TYPES = ('kconfig', 'version', 'cmdline')
class OptCheck:
# Constructor without the 'expected' parameter is for option presence checks (any value is OK)
......@@ -132,6 +130,12 @@ class OptCheck:
if with_results:
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):
def __init__(self, *args, **kwargs):
......@@ -142,11 +146,11 @@ class KconfigCheck(OptCheck):
def type(self):
return 'kconfig'
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 CmdlineCheck(OptCheck):
@property
def type(self):
return 'cmdline'
class VersionCheck:
......@@ -185,7 +189,7 @@ class ComplexOptCheck:
sys.exit('[!] ERROR: empty {} check'.format(self.__class__.__name__))
if len(self.opts) == 1:
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))
self.result = None
......@@ -433,7 +437,8 @@ def add_kconfig_checks(l, arch):
if arch in ('X86_64', 'ARM64', 'X86_32'):
stackleak_is_set = KconfigCheck('self_protection', 'kspp', 'GCC_PLUGIN_STACKLEAK', 'y')
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'):
l += [KconfigCheck('self_protection', 'kspp', 'SCHED_CORE', 'y')]
l += [KconfigCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '65536')]
......@@ -461,7 +466,8 @@ def add_kconfig_checks(l, arch):
l += [KconfigCheck('self_protection', 'clipos', 'STATIC_USERMODEHELPER', 'y')] # needs userspace support
l += [OR(KconfigCheck('self_protection', 'clipos', 'EFI_DISABLE_PCI_DMA', 'y'),
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_CPU', '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):
# 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):
known_options = []
......@@ -724,15 +739,15 @@ def print_checklist(mode, checklist, with_results):
def populate_simple_opt_with_data(opt, data, data_type):
if opt.type == 'complex':
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))
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))
if data_type != opt.type:
return
if data_type == 'kconfig':
if data_type in ('kconfig', 'cmdline'):
opt.state = data.get(opt.name, None)
elif data_type == 'version':
opt.ver = data
......@@ -749,7 +764,7 @@ def populate_opt_with_data(opt, data, data_type):
else:
populate_simple_opt_with_data(o, data, data_type)
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))
populate_simple_opt_with_data(opt, data, data_type)
......@@ -788,6 +803,24 @@ def parse_kconfig_file(parsed_options, fname):
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():
# Report modes:
# * verbose mode for
......@@ -803,6 +836,8 @@ def main():
help='print security hardening preferences for the selected architecture')
parser.add_argument('-c', '--config',
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,
help='choose the report mode')
args = parser.parse_args()
......@@ -818,6 +853,8 @@ def main():
if args.config:
if mode != 'json':
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)
if not arch:
......@@ -840,6 +877,15 @@ def main():
populate_with_data(config_checklist, parsed_kconfig_options, 'kconfig')
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
perform_checks(config_checklist)
......@@ -849,12 +895,15 @@ def main():
print_checklist(mode, config_checklist, True)
sys.exit(0)
elif args.cmdline:
sys.exit('[!] ERROR: checking cmdline doesn\'t work without checking kconfig')
if args.print:
if mode in ('show_ok', 'show_fail'):
sys.exit('[!] ERROR: wrong mode "{}" for --print'.format(mode))
arch = args.print
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_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