Add the srbds check
[kconfig-hardened-check.git] / kconfig_hardened_check / __init__.py
index 3ac7aa7e1ba85f1e79924ee62f95077cdbd94b07..4dc9fe721058df14ccdd050b308387714dcb43eb 100644 (file)
 #    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
 #       ARM64:
 #           kpti=on
@@ -74,8 +71,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 +84,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 +106,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 +136,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 +593,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 +729,27 @@ 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'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'mds', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'mds', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'tsx_async_abort', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'tsx_async_abort', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'srbds', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'srbds', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'mmio_stale_data', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'mmio_stale_data', 'is not set'))]
+    l += [OR(CmdlineCheck('self_protection', 'defconfig', 'retbleed', 'is not off'),
+             CmdlineCheck('self_protection', 'defconfig', 'retbleed', '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 +759,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 +769,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 +796,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 +952,41 @@ 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
+    if option == 'mds':
+        # See mds_cmdline() in arch/x86/kernel/cpu/bugs.c
+        return value
+    if option == 'tsx_async_abort':
+        # See tsx_async_abort_parse_cmdline() in arch/x86/kernel/cpu/bugs.c
+        return value
+    if option == 'srbds':
+        # See srbds_parse_cmdline() in arch/x86/kernel/cpu/bugs.c
+        return value
+    if option == 'mmio_stale_data':
+        # See mmio_stale_data_parse_cmdline() in arch/x86/kernel/cpu/bugs.c
+        return value
+    if option == 'retbleed':
+        # See retbleed_parse_cmdline() in arch/x86/kernel/cpu/bugs.c
         return value
 
     # Implement a limited part of the kstrtobool() logic