Skip normalize_cmdline_options() for the iommu cmdline parameter
[kconfig-hardened-check.git] / kconfig_hardened_check / __init__.py
index 8f244985ecbb4d55f6ee53426e9ac6462d9eeb7f..086e21e3769d3569ec4eb4672b7920614d4fc9c5 100644 (file)
@@ -1,9 +1,7 @@
 #!/usr/bin/python3
 
 """
-This tool helps me to check Linux kernel options against
-my security hardening preferences for X86_64, ARM64, X86_32, and ARM.
-Let the computers do their job!
+This tool is for checking the security hardening options of the Linux kernel.
 
 Author: Alexander Popov <alex.popov@linux.com>
 
@@ -12,6 +10,7 @@ This module performs input/output.
 
 # pylint: disable=missing-function-docstring,line-too-long,invalid-name,too-many-branches,too-many-statements
 
+import gzip
 import sys
 from argparse import ArgumentParser
 from collections import OrderedDict
@@ -19,11 +18,19 @@ import re
 import json
 from .__about__ import __version__
 from .checks import add_kconfig_checks, add_cmdline_checks, normalize_cmdline_options
-from .engine import populate_with_data, perform_checks
+from .engine import populate_with_data, perform_checks, override_expected_value
+
+
+def _open(file: str, *args, **kwargs):
+    open_method = open
+    if file.endswith(".gz"):
+        open_method = gzip.open
+
+    return open_method(file, *args, **kwargs)
 
 
 def detect_arch(fname, archs):
-    with open(fname, 'r', encoding='utf-8') as f:
+    with _open(fname, 'rt', encoding='utf-8') as f:
         arch_pattern = re.compile("CONFIG_[a-zA-Z0-9_]*=y")
         arch = None
         for line in f.readlines():
@@ -40,7 +47,7 @@ def detect_arch(fname, archs):
 
 
 def detect_kernel_version(fname):
-    with open(fname, 'r', encoding='utf-8') as f:
+    with _open(fname, 'rt', encoding='utf-8') as f:
         ver_pattern = re.compile("# Linux/.* Kernel Configuration")
         for line in f.readlines():
             if ver_pattern.match(line):
@@ -58,7 +65,7 @@ def detect_kernel_version(fname):
 def detect_compiler(fname):
     gcc_version = None
     clang_version = None
-    with open(fname, 'r', encoding='utf-8') as f:
+    with _open(fname, 'rt', encoding='utf-8') as f:
         gcc_version_pattern = re.compile("CONFIG_GCC_VERSION=[0-9]*")
         clang_version_pattern = re.compile("CONFIG_CLANG_VERSION=[0-9]*")
         for line in f.readlines():
@@ -146,7 +153,7 @@ def print_checklist(mode, checklist, with_results):
 
 
 def parse_kconfig_file(parsed_options, fname):
-    with open(fname, 'r', encoding='utf-8') as f:
+    with _open(fname, 'rt', encoding='utf-8') as f:
         opt_is_on = re.compile("CONFIG_[a-zA-Z0-9_]*=[a-zA-Z0-9_\"]*")
         opt_is_off = re.compile("# CONFIG_[a-zA-Z0-9_]* is not set")
 
@@ -202,11 +209,11 @@ def main():
                             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 security hardening preferences for the selected architecture')
+                        help='print security hardening options for the selected architecture')
     parser.add_argument('-c', '--config',
-                        help='check the kernel kconfig file against these preferences')
+                        help='check security hardening options in the kernel kconfig file (also supports *.gz files)')
     parser.add_argument('-l', '--cmdline',
-                        help='check the kernel cmdline file against these preferences')
+                        help='check security hardening options in the kernel cmdline file')
     parser.add_argument('-m', '--mode', choices=report_modes,
                         help='choose the report mode')
     args = parser.parse_args()
@@ -268,6 +275,11 @@ def main():
             parse_cmdline_file(parsed_cmdline_options, args.cmdline)
             populate_with_data(config_checklist, parsed_cmdline_options, 'cmdline')
 
+        # hackish refinement of the CONFIG_ARCH_MMAP_RND_BITS check
+        mmap_rnd_bits_max = parsed_kconfig_options.get('CONFIG_ARCH_MMAP_RND_BITS_MAX', None)
+        if mmap_rnd_bits_max:
+            override_expected_value(config_checklist, 'CONFIG_ARCH_MMAP_RND_BITS', mmap_rnd_bits_max)
+
         # now everything is ready, perform the checks
         perform_checks(config_checklist)
 
@@ -292,7 +304,7 @@ def main():
         add_kconfig_checks(config_checklist, arch)
         add_cmdline_checks(config_checklist, arch)
         if mode != 'json':
-            print(f'[+] Printing kernel security hardening preferences for {arch}...')
+            print(f'[+] Printing kernel security hardening options for {arch}...')
         print_checklist(mode, config_checklist, False)
         sys.exit(0)