Add the l1tf check
[kconfig-hardened-check.git] / kconfig_hardened_check / __init__.py
index 3ac7aa7e1ba85f1e79924ee62f95077cdbd94b07..a926402426c3eba4ba100a9fb0f17b4a81d4bcfa 100644 (file)
@@ -16,8 +16,6 @@
 #    Mitigations of CPU vulnerabilities:
 #       Аrch-independent:
 #       X86:
-#           spec_store_bypass_disable=on
-#           l1tf=full,force
 #           l1d_flush=on (a part of the l1tf option)
 #           mds=full,nosmt
 #           tsx=off
@@ -74,8 +72,7 @@ from .__about__ import __version__
 SIMPLE_OPTION_TYPES = ('kconfig', 'version', 'cmdline')
 
 class OptCheck:
-    # Constructor without the 'expected' parameter is for option presence checks (any value is OK)
-    def __init__(self, reason, decision, name, expected=None):
+    def __init__(self, reason, decision, name, expected):
         assert(name and name == name.strip() and len(name.split()) == 1), \
                'invalid name "{}" for {}'.format(name, self.__class__.__name__)
         self.name = name
@@ -88,16 +85,18 @@ class OptCheck:
                'invalid reason "{}" for "{}" check'.format(reason, name)
         self.reason = reason
 
-        if expected:
-            assert(expected == expected.strip()), \
-                   'invalid expected value "{}" for "{}" check (1)'.format(expected, name)
-            val_len = len(expected.split())
-            if val_len == 3:
-                assert(expected == 'is not set' or expected == 'is not off'), \
+        assert(expected and expected == expected.strip()), \
+               'invalid expected value "{}" for "{}" check (1)'.format(expected, name)
+        val_len = len(expected.split())
+        if val_len == 3:
+            assert(expected == 'is not set' or expected == 'is not off'), \
                    'invalid expected value "{}" for "{}" check (2)'.format(expected, name)
-            else:
-                assert(val_len == 1), \
+        elif val_len == 2:
+            assert(expected == 'is present'), \
                    'invalid expected value "{}" for "{}" check (3)'.format(expected, name)
+        else:
+            assert(val_len == 1), \
+                   'invalid expected value "{}" for "{}" check (4)'.format(expected, name)
         self.expected = expected
 
         self.state = None
@@ -108,8 +107,8 @@ class OptCheck:
         return None
 
     def check(self):
-        # handle the option presence check
-        if self.expected is None:
+        # handle the 'is present' check
+        if self.expected == 'is present':
             if self.state is None:
                 self.result = 'FAIL: is not present'
             else:
@@ -138,11 +137,7 @@ class OptCheck:
             self.result = 'FAIL: "' + self.state + '"'
 
     def table_print(self, _mode, with_results):
-        if self.expected is None:
-            expected = ''
-        else:
-            expected = self.expected
-        print('{:<40}|{:^7}|{:^12}|{:^10}|{:^18}'.format(self.name, self.type, expected, self.decision, self.reason), end='')
+        print('{:<40}|{:^7}|{:^12}|{:^10}|{:^18}'.format(self.name, self.type, self.expected, self.decision, self.reason), end='')
         if with_results:
             print('| {}'.format(self.result), end='')
 
@@ -599,7 +594,7 @@ def add_kconfig_checks(l, arch):
     l += [OR(KconfigCheck('cut_attack_surface', 'kspp', 'IO_STRICT_DEVMEM', 'y'),
              devmem_not_set)] # refers to LOCKDOWN
     l += [AND(KconfigCheck('cut_attack_surface', 'kspp', 'LDISC_AUTOLOAD', 'is not set'),
-              KconfigCheck('cut_attack_surface', 'kspp', 'LDISC_AUTOLOAD'))] # option presence check
+              KconfigCheck('cut_attack_surface', 'kspp', 'LDISC_AUTOLOAD', 'is present'))]
     if arch == 'ARM':
         l += [OR(KconfigCheck('cut_attack_surface', 'kspp', 'STRICT_DEVMEM', 'y'),
                  devmem_not_set)] # refers to LOCKDOWN
@@ -735,8 +730,17 @@ def add_cmdline_checks(l, arch):
     l += [CmdlineCheck('self_protection', 'defconfig', 'nopti', 'is not set')]
     l += [CmdlineCheck('self_protection', 'defconfig', 'nospectre_v1', 'is not set')]
     l += [CmdlineCheck('self_protection', 'defconfig', 'nospectre_v2', 'is not set')]
+    l += [CmdlineCheck('self_protection', 'defconfig', 'nospec_store_bypass_disable', 'is not set')]
     l += [OR(CmdlineCheck('self_protection', 'defconfig', 'mitigations', 'is not off'),
              CmdlineCheck('self_protection', 'defconfig', 'mitigations', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'spectre_v2', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'spectre_v2', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'spectre_v2_user', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'spectre_v2_user', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'spec_store_bypass_disable', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'spec_store_bypass_disable', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'l1tf', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'l1tf', 'is not set'))]
     if arch == 'ARM64':
         l += [OR(CmdlineCheck('self_protection', 'defconfig', 'rodata', 'full'),
                  AND(KconfigCheck('self_protection', 'defconfig', 'RODATA_FULL_DEFAULT_ENABLED', 'y'),
@@ -746,7 +750,7 @@ def add_cmdline_checks(l, arch):
                  CmdlineCheck('self_protection', 'defconfig', 'rodata', 'is not set'))]
 
     # 'self_protection', 'kspp'
-    l += [CmdlineCheck('self_protection', 'kspp', 'nosmt')] # option presence check
+    l += [CmdlineCheck('self_protection', 'kspp', 'nosmt', 'is present')]
     l += [OR(CmdlineCheck('self_protection', 'kspp', 'init_on_alloc', '1'),
              AND(KconfigCheck('self_protection', 'kspp', 'INIT_ON_ALLOC_DEFAULT_ON', 'y'),
                  CmdlineCheck('self_protection', 'kspp', 'init_on_alloc', 'is not set')))]
@@ -756,9 +760,9 @@ def add_cmdline_checks(l, arch):
              AND(CmdlineCheck('self_protection', 'kspp', 'page_poison', '1'),
                  KconfigCheck('self_protection', 'kspp', 'PAGE_POISONING_ZERO', 'y'),
                  CmdlineCheck('self_protection', 'kspp', 'slub_debug', 'P')))]
-    l += [OR(CmdlineCheck('self_protection', 'kspp', 'slab_nomerge'),
+    l += [OR(CmdlineCheck('self_protection', 'kspp', 'slab_nomerge', 'is present'),
              AND(KconfigCheck('self_protection', 'clipos', 'SLAB_MERGE_DEFAULT', 'is not set'),
-                 CmdlineCheck('self_protection', 'kspp', 'slab_merge', 'is not set')))] # option presence check
+                 CmdlineCheck('self_protection', 'kspp', 'slab_merge', 'is not set')))]
     l += [OR(CmdlineCheck('self_protection', 'kspp', 'iommu.strict', '1'),
              AND(KconfigCheck('self_protection', 'kspp', 'IOMMU_DEFAULT_DMA_STRICT', 'y'),
                  CmdlineCheck('self_protection', 'kspp', 'iommu.strict', 'is not set')))]
@@ -783,9 +787,6 @@ def add_cmdline_checks(l, arch):
 
     # 'self_protection', 'clipos'
     l += [CmdlineCheck('self_protection', 'clipos', 'page_alloc.shuffle', '1')]
-    if arch in ('X86_64', 'X86_32'):
-        l += [AND(CmdlineCheck('self_protection', 'clipos', 'spectre_v2', 'on'),
-                  CmdlineCheck('self_protection', 'defconfig', 'nospectre_v2', 'is not set'))]
 
     # 'cut_attack_surface', 'kspp'
     if arch == 'X86_64':
@@ -942,17 +943,26 @@ def parse_kconfig_file(parsed_options, fname):
 def normalize_cmdline_options(option, value):
     # Don't normalize the cmdline option values if
     # the Linux kernel doesn't use kstrtobool() for them
+    if option == 'debugfs':
+        # See debugfs_kernel() in fs/debugfs/inode.c
+        return value
+    if option == 'mitigations':
+        # See mitigations_parse_cmdline() in kernel/cpu.c
+        return value
     if option == 'pti':
-        # See pti_check_boottime_disable() in linux/arch/x86/mm/pti.c
+        # See pti_check_boottime_disable() in arch/x86/mm/pti.c
         return value
     if option == 'spectre_v2':
-        # See spectre_v2_parse_cmdline() in linux/arch/x86/kernel/cpu/bugs.c
+        # See spectre_v2_parse_cmdline() in arch/x86/kernel/cpu/bugs.c
         return value
-    if option == 'debugfs':
-        # See debugfs_kernel() in fs/debugfs/inode.c
+    if option == 'spectre_v2_user':
+        # See spectre_v2_parse_user_cmdline() in arch/x86/kernel/cpu/bugs.c
         return value
-    if option == 'mitigations':
-        # See mitigations_parse_cmdline() in linux/kernel/cpu.c
+    if option == 'spec_store_bypass_disable':
+        # See ssb_parse_cmdline() in arch/x86/kernel/cpu/bugs.c
+        return value
+    if option == 'l1tf':
+        # See l1tf_cmdline() in arch/x86/kernel/cpu/bugs.c
         return value
 
     # Implement a limited part of the kstrtobool() logic