On 7/8/25 14:38, Guido Trentalancia via Gnupg-devel wrote:
The following new v10 patch has been created to fix a missing #ifdef
and header file check for the case of L1D cache flushing.
[...]

Two major issues, further explained inline below:

    - You are installing the signal handler incorrectly; this will interfere with other possible uses of SIGBUS.

    - Your message from configure when testing the option to request L1 cache flushes is misleading.

Further, none of this actually *fixes* anything; these are *workarounds* for widespread hardware bugs.

Also, have you actually tested this on a machine where the request for L1 cache flushes raises SIGBUS?


diff -pru a/common/init.c b/common/init.c
--- a/common/init.c     2025-05-25 15:43:45.871984100 +0200
+++ b/common/init.c     2025-07-08 21:29:23.071406450 +0200
[...]
  /* This function should be the first called after main.  */
  void
  early_system_init (void)
  {
+#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H)
+
+/* Disable CPU speculative execution security vulnerabilities
+ * causing data leaks: see the Linux kernel documentation
+ * Documentation/userspace-api/spec_ctrl.rst
+ *
+ * - Speculative Store Bypass (CVE-2018-3639, always
+ *   disabled)
+ * - Indirect Branch Speculation (CVE-2017-5715, always
+ *   disabled)
+ * - Flush L1D Cache on context switch out of the task (it
+ *   requires the "nosmt l1d_flush=on" kernel boot parameter)
+ */
+#ifdef PR_SPEC_STORE_BYPASS
+  prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 
0, 0);
+#endif
+
+#ifdef PR_SPEC_INDIRECT_BRANCH
+  prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 
PR_SPEC_FORCE_DISABLE, 0, 0);
+#endif
+
+#if defined(ENABLE_L1D_CACHE_FLUSH) && defined(PR_SPEC_L1D_FLUSH)
+  if (signal(SIGBUS, sigbus_handler) == SIG_ERR)
+    {
+      log_info ("Warning: cannot catch the SIGBUS signal.\n");
+    }

You cannot use signal() here in a library because you must restore any previous signal handler immediately after the prctl() call.  Other code in the program might have its own reasons to catch SIGBUS, and this handler will interfere with that. You must use sigaction() here to obtain the old handler in a form that you can use to restore it after calling prctl().

+  if (prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, PR_SPEC_ENABLE, 0, 0) 
< 0)
+    {
+      log_info ("Warning: Level 1 Data Cache flushing requires the \"l1d_flush=on\" 
boot parameter.\n");
+    }

This is where you need to restore the previous state of SIGBUS handling.

+#endif
+
+#endif /* __linux__ && HAVE_SYS_PRCTL_H */
  }
diff -pru a/configure.ac b/configure.ac
--- a/configure.ac      2025-07-06 18:01:54.128546282 +0200
+++ b/configure.ac      2025-07-08 21:32:32.674405293 +0200
@@ -244,6 +244,16 @@ AC_ARG_ENABLE(selinux-support,
  AC_MSG_RESULT($selinux_support)
+# Fix security vulnerability CVE-2020-0550 by enabling
+# Level 1 Data Cache flushing on context switch.
+AC_MSG_CHECKING([whether Level 1 Data Cache is flushed on context switch])

This message does not accurately describe what is going on.  This should say "whether L1 data cache should be flushed on context switch" because it does *not* test whether the cache is *actually* flushed, but only if the option to *request* flushing the cache is set.

+AC_ARG_ENABLE(l1d-cache-flushing,
+              AS_HELP_STRING([--enable-l1d-cache-flushing],
+                             [enable L1D cache flushing]),
+              l1d_cache_flushing=$enableval, l1d_cache_flushing=no)
+AC_MSG_RESULT($l1d_cache_flushing)
+
+
  AC_MSG_CHECKING([whether to allocate extra secure memory])
  AC_ARG_ENABLE(large-secmem,
                AS_HELP_STRING([--enable-large-secmem],
[...]


-- Jacob
_______________________________________________
Gnupg-devel mailing list
Gnupg-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gnupg-devel

Reply via email to