Support separate sysctl checking (without kconfig)
authorAlexander Popov <alex.popov@linux.com>
Sun, 27 Aug 2023 20:31:55 +0000 (23:31 +0300)
committerAlexander Popov <alex.popov@linux.com>
Sun, 27 Aug 2023 20:31:55 +0000 (23:31 +0300)
kconfig_hardened_check/__init__.py
kconfig_hardened_check/checks.py

index 3e4db1c96989a70385becacc6805702e9cbd55a8..5a7ff7f201090de672c3724f77d7616a90722308 100644 (file)
@@ -258,7 +258,6 @@ def main():
     if args.config:
         if args.print:
             sys.exit('[!] ERROR: --config and --print can\'t be used together')
-
         if args.generate:
             sys.exit('[!] ERROR: --config and --generate can\'t be used together')
 
@@ -338,13 +337,38 @@ def main():
 
         # finally print the results
         print_checklist(mode, config_checklist, True)
-
         sys.exit(0)
     elif args.cmdline:
         sys.exit('[!] ERROR: checking cmdline depends on checking Kconfig')
     elif args.sysctl:
-        # TODO: sysctl check should also work separately
-        sys.exit('[!] ERROR: checking sysctl depends on checking Kconfig')
+        # separate sysctl checking (without kconfig)
+        assert(args.config is None and args.cmdline is None), 'unexpected args'
+        if args.print:
+            sys.exit('[!] ERROR: --sysctl and --print can\'t be used together')
+        if args.generate:
+            sys.exit('[!] ERROR: --sysctl and --generate can\'t be used together')
+
+        if mode != 'json':
+            print(f'[+] Sysctl output file to check: {args.sysctl}')
+
+        # add relevant sysctl checks to the checklist
+        add_sysctl_checks(config_checklist, None)
+
+        # populate the checklist with the parsed sysctl data
+        parsed_sysctl_options = OrderedDict()
+        parse_sysctl_file(mode, parsed_sysctl_options, args.sysctl)
+        populate_with_data(config_checklist, parsed_sysctl_options, 'sysctl')
+
+        # now everything is ready, perform the checks
+        perform_checks(config_checklist)
+
+        if mode == 'verbose':
+            # print the parsed options without the checks (for debugging)
+            print_unknown_options(config_checklist, parsed_sysctl_options)
+
+        # finally print the results
+        print_checklist(mode, config_checklist, True)
+        sys.exit(0)
 
     if args.print:
         assert(args.config is None and args.cmdline is None and args.sysctl is None), 'unexpected args'
index 77645093186e7430a4dbd8ce7812eecc4378edcd..4957ad5c4e1a2202267b269d8f400b9bebd3a741 100644 (file)
@@ -15,6 +15,8 @@ from .engine import KconfigCheck, CmdlineCheck, SysctlCheck, VersionCheck, OR, A
 
 
 def add_kconfig_checks(l, arch):
+    assert(arch), 'empty arch'
+
     # Calling the KconfigCheck class constructor:
     #     KconfigCheck(reason, decision, name, expected)
     #
@@ -379,6 +381,8 @@ def add_kconfig_checks(l, arch):
 
 
 def add_cmdline_checks(l, arch):
+    assert(arch), 'empty arch'
+
     # Calling the CmdlineCheck class constructor:
     #     CmdlineCheck(reason, decision, name, expected)
     #
@@ -574,7 +578,6 @@ def normalize_cmdline_options(option, value):
     return value
 
 
-def add_sysctl_checks(l, arch):
 # TODO: draft of security hardening sysctls:
 #    kernel.kptr_restrict=2 (or 1?)
 #    kernel.yama.ptrace_scope=3
@@ -598,7 +601,10 @@ def add_sysctl_checks(l, arch):
 #    kernel.oops_limit (think about a proper value)
 #    kernel.warn_limit (think about a proper value)
 #    net.ipv4.tcp_syncookies=1 (?)
-#
+
+def add_sysctl_checks(l, arch):
+# This function may be called with arch=None
+
 # Calling the SysctlCheck class constructor:
 #   SysctlCheck(reason, decision, name, expected)