Add an --autodetect option
authorjvoisin <julien.voisin@dustri.org>
Tue, 8 Oct 2024 20:32:45 +0000 (22:32 +0200)
committerAlexander Popov <alex.popov@linux.com>
Sat, 9 Nov 2024 17:49:36 +0000 (20:49 +0300)
Instead of having to specify Kconfig file and /proc/cmdline, --autodetect will try to infer them.

This is related to #129, and replaces #130.

kernel_hardening_checker/__init__.py

index ac4da67107ccf8c9a57ff379a96a63551f190cbd..bed2ba0081948f6b02819332e36de21d514ccfc8 100755 (executable)
@@ -14,6 +14,9 @@ This module performs input/output.
 import os
 import gzip
 import sys
+import glob
+import tempfile
+import subprocess
 from argparse import ArgumentParser
 from typing import List, Tuple, Dict, TextIO
 import re
@@ -378,6 +381,9 @@ def main() -> None:
                         help='print the security hardening recommendations for the selected microarchitecture')
     parser.add_argument('-g', '--generate', choices=SUPPORTED_ARCHS,
                         help='generate a Kconfig fragment with the security hardening options for the selected microarchitecture')
+    parser.add_argument('-a', '--autodetect',
+                        help='autodetect the running kernel and infer the corresponding Kconfig file',
+                        action='store_true')
     args = parser.parse_args()
 
     mode = None
@@ -386,6 +392,38 @@ def main() -> None:
         if mode != 'json':
             print(f'[+] Special report mode: {mode}')
 
+    if args.autodetect:
+        cmdline = '/proc/cmdline'
+        config = '/proc/config.gz'
+        if os.path.isfile('/proc/config.gz'):
+            kernel_version, msg = detect_kernel_version(config)
+            assert kernel_version
+            kernel_version_str = '.'.join(map(str, kernel_version))
+        else:
+            kernel_version, msg = detect_kernel_version('/proc/version')
+            assert kernel_version
+            kernel_version_str = '.'.join(map(str, kernel_version))
+            config_files = glob.glob(f'/boot/config-{kernel_version_str}-*')
+            if not config_files:
+                sys.exit(f'[!] ERROR: unable to find a Kconfig file for {kernel_version_str}')
+            config = config_files[0]
+            if mode != 'json':
+                if len(config_files) > 1:
+                    print(f'[+] Multiple Kconfig files found for {kernel_version_str}, picking {config}')
+
+        _, tmpfile = tempfile.mkstemp()
+        with open(tmpfile, 'w', encoding='utf-8') as f:
+            subprocess.call(['sysctl', '-a'], stdout=f, stderr=subprocess.DEVNULL, shell=False)
+
+        if mode != 'json':
+            print(f'[+] Detected running kernel version: {kernel_version_str}')
+            print(f'[+] Kconfig file to check: {config}')
+
+        perform_checking(mode, kernel_version, config, cmdline, tmpfile)
+
+        os.remove(tmpfile)
+        sys.exit(0)
+
     if mode != 'json':
         if args.config:
             print(f'[+] Kconfig file to check: {args.config}')