about summary refs log tree commit diff
path: root/nixos/modules/security/misc.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/security/misc.nix')
-rw-r--r--nixos/modules/security/misc.nix110
1 files changed, 98 insertions, 12 deletions
diff --git a/nixos/modules/security/misc.nix b/nixos/modules/security/misc.nix
index 42f872b7b088..4506a67487d4 100644
--- a/nixos/modules/security/misc.nix
+++ b/nixos/modules/security/misc.nix
@@ -22,18 +22,104 @@ with lib;
         a user namespace fails with "no space left on device" (ENOSPC).
       '';
     };
-  };
 
-  config = mkIf (!config.security.allowUserNamespaces) {
-    # Setting the number of allowed user namespaces to 0 effectively disables
-    # the feature at runtime.  Note that root may raise the limit again
-    # at any time.
-    boot.kernel.sysctl."user.max_user_namespaces" = 0;
-
-    assertions = [
-      { assertion = config.nix.useSandbox -> config.security.allowUserNamespaces;
-        message = "`nix.useSandbox = true` conflicts with `!security.allowUserNamespaces`.";
-      }
-    ];
+    security.protectKernelImage = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to prevent replacing the running kernel image.
+      '';
+    };
+
+    security.allowSimultaneousMultithreading = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to allow SMT/hyperthreading.  Disabling SMT means that only
+        physical CPU cores will be usable at runtime, potentially at
+        significant performance cost.
+        </para>
+
+        <para>
+        The primary motivation for disabling SMT is to mitigate the risk of
+        leaking data between threads running on the same CPU core (due to
+        e.g., shared caches).  This attack vector is unproven.
+        </para>
+
+        <para>
+        Disabling SMT is a supplement to the L1 data cache flushing mitigation
+        (see <xref linkend="opt-security.virtualization.flushL1DataCache"/>)
+        versus malicious VM guests (SMT could "bring back" previously flushed
+        data).
+        </para>
+        <para>
+      '';
+    };
+
+    security.virtualization.flushL1DataCache = mkOption {
+      type = types.nullOr (types.enum [ "never" "cond" "always" ]);
+      default = null;
+      description = ''
+        Whether the hypervisor should flush the L1 data cache before
+        entering guests.
+        See also <xref linkend="opt-security.allowSimultaneousMultithreading"/>.
+        </para>
+
+        <para>
+          <variablelist>
+          <varlistentry>
+            <term><literal>null</literal></term>
+            <listitem><para>uses the kernel default</para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>"never"</literal></term>
+            <listitem><para>disables L1 data cache flushing entirely.
+            May be appropriate if all guests are trusted.</para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>"cond"</literal></term>
+            <listitem><para>flushes L1 data cache only for pre-determined
+            code paths.  May leak information about the host address space
+            layout.</para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>"always"</literal></term>
+            <listitem><para>flushes L1 data cache every time the hypervisor
+            enters the guest.  May incur significant performance cost.
+            </para></listitem>
+          </varlistentry>
+          </variablelist>
+      '';
+    };
   };
+
+  config = mkMerge [
+    (mkIf (!config.security.allowUserNamespaces) {
+      # Setting the number of allowed user namespaces to 0 effectively disables
+      # the feature at runtime.  Note that root may raise the limit again
+      # at any time.
+      boot.kernel.sysctl."user.max_user_namespaces" = 0;
+
+      assertions = [
+        { assertion = config.nix.useSandbox -> config.security.allowUserNamespaces;
+          message = "`nix.useSandbox = true` conflicts with `!security.allowUserNamespaces`.";
+        }
+      ];
+    })
+
+    (mkIf config.security.protectKernelImage {
+      # Disable hibernation (allows replacing the running kernel)
+      boot.kernelParams = [ "nohibernate" ];
+      # Prevent replacing the running kernel image w/o reboot
+      boot.kernel.sysctl."kernel.kexec_load_disabled" = mkDefault true;
+    })
+
+    (mkIf (!config.security.allowSimultaneousMultithreading) {
+      boot.kernelParams = [ "nosmt" ];
+    })
+
+    (mkIf (config.security.virtualization.flushL1DataCache != null) {
+      boot.kernelParams = [ "kvm-intel.vmentry_l1d_flush=${config.security.virtualization.flushL1DataCache}" ];
+    })
+  ];
 }