[PATCH gnupg v7] Disable CPU speculation-related misfeatures
Guido Trentalancia
guido at trentalancia.com
Tue Jul 8 13:05:00 CEST 2025
In the following v7 patch I have improved the commit log and source
code comments, with a better explaination of how to fix CVE-2020-0550
(L1 Data Cache flush).
common: Disable CPU speculative execution security
vulnerabilities (CVE-2018-3639 aka Spectre variant 4,
CVE-2017-5715 and optionally CVE-2020-0550)
* configure.ac: add a new L1D Cache flushing option
(--enable-l1d-cache-flushing) to fix CVE-2020-0550
and check for sys/prctl.h on Linux systems
* common/init.c (early_system_init): Disable CPU
speculative execution security vulnerabilities
potentially causing data leaks:
- Speculative Store Bypass (always disabled)
- Indirect Branch Speculation (always disabled)
- Flush L1D Cache on context switch out of the
task (use the --enable-l1d-cache-flushing
configure option and l1d_flush=on on the boot
command line to mitigate the vulnerability)
For further information see the kernel documentation:
Documentation/userspace-api/spec_ctrl.rst
Documentation/admin-guide/hw-vuln/l1d_flush.rst
Signed-off-by: Guido Trentalancia <guido at trentalancia.com>
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-07 19:02:08.478853360 +0200
@@ -29,6 +29,10 @@
#include <config.h>
+#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H)
+# include <sys/prctl.h>
+#endif
+
#ifdef HAVE_W32_SYSTEM
# if _WIN32_WINNT < 0x0600
# define _WIN32_WINNT 0x0600 /* Required for SetProcessDEPPolicy. */
@@ -132,6 +136,32 @@ writestring_via_estream (int mode, const
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 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)
+ prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, PR_SPEC_ENABLE, 0, 0);
+#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-06 21:56:51.219048292 +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])
+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],
@@ -1313,6 +1323,15 @@ fi
#
+# Level 1 Data Cache flushing on context switch (CVE-2020-0550)
+#
+if test "$l1d_cache_flushing" = yes ; then
+ AC_DEFINE(ENABLE_L1D_CACHE_FLUSH,1,
+ [Define to enable Layer 1 Data Cache flushing])
+fi
+
+
+#
# Checks for header files.
#
AC_MSG_NOTICE([checking for header files])
@@ -1322,6 +1341,13 @@ AC_CHECK_HEADERS([unistd.h langinfo.h te
ucred.h sys/ucred.h sys/sysmacros.h sys/mkdev.h])
+# See whether libc supports the prctl()
+case "${host}" in
+ *-*-linux*)
+ AC_CHECK_HEADERS([sys/prctl.h])
+ ;;
+esac
+
#
# Checks for typedefs, structures, and compiler characteristics.
#
On Mon, 07/07/2025 at 19.17 +0200, Guido Trentalancia via
Gnupg-devel wrote:
> On Mon, 07/07/2025 alle 18.36 +0200, Werner Koch wrote:
> > Hi!
> >
> > On Sun, 6 Jul 2025 21:50, Guido Trentalancia said:
> >
> > > common: Disable CPU speculation-related misfeatures
> >
> > I would prefer to keep the subject clear of an opinion.
>
> It's not an opinion, it's a fact.
>
> The wording is taken from the official Linux kernel documentation,
> however I agree it's probably too delicate, the correct wording is
> "security vulnerabilities".
>
> > > +#if defined(__linux__)
> > > +# include <sys/prctl.h>
> > > +#endif
> >
> > Good. You now provide configure tests. Please also add a general
> > one
> > which checks for this header.
>
> A general check for sys/prctl.h is not needed, as such header file is
> only used on Linux-specific code and it can therefore break things on
> non-Linux systems.
>
> > > +#if defined(__linux__)
> >
> > And use that here ;-)
> >
> > > AC_CHECK_HEADERS([unistd.h langinfo.h termio.h locale.h \
> > > pwd.h inttypes.h signal.h sys/select.h
> > > sys/time.h \
> > > stdint.h signal.h termios.h \
> > > - ucred.h sys/ucred.h sys/sysmacros.h
> > > sys/mkdev.h])
> > > + ucred.h sys/ucred.h sys/sysmacros.h
> > > sys/mkdev.h
> > > \
> > > + sys/prctl.h])
> >
> > Hey, you already got that macro. Thus you can replace the above
> > with
> >
> > #if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
>
> I can replace that, in reversed order. Please see the v6 patch below,
> my last attempt at fixing this...
>
> > and we are good. The ifdef __linux__ here is so that we cater for
> > OSes
> > which have such a header for different purposes. Using the
> > standard
> > configure test along with a ifdef in the code is a good compromise
> > between readibility and regualar autoconf style.
>
> common: Disable CPU speculation-related security
> vulnerabilities (CVE-2018-3639 aka Spectre variant 4,
> CVE-2017-5715 and optionally CVE-2020-0550)
>
> * configure.ac: add a new L1D Cache flushing option
> (--enable-l1d-cache-flushing) to fix CVE-2020-0550
> and check for sys/prctl.h on Linux systems
>
> * common/init.c (early_system_init): Disable CPU
> speculation-related misfeatures which are in fact
> vulnerabilities causing data leaks:
>
> - Speculative Store Bypass (always disabled)
> - Indirect Branch Speculation (always disabled)
> - Flush L1D Cache on context switch out of the
> task (use the --enable-l1d-cache-flushing
> configure option to mitigate the vulnerability)
>
> For further information see the kernel documentation:
> Documentation/userspace-api/spec_ctrl.rst
> Documentation/admin-guide/hw-vuln/l1d_flush.rst
>
> Signed-off-by: Guido Trentalancia <guido at trentalancia.com>
>
> 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-07 19:02:08.478853360 +0200
> @@ -29,6 +29,10 @@
>
> #include <config.h>
>
> +#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H)
> +# include <sys/prctl.h>
> +#endif
> +
> #ifdef HAVE_W32_SYSTEM
> # if _WIN32_WINNT < 0x0600
> # define _WIN32_WINNT 0x0600 /* Required for
> SetProcessDEPPolicy. */
> @@ -132,6 +136,29 @@ writestring_via_estream (int mode, const
> void
> early_system_init (void)
> {
> +#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H)
> +
> +/* Disable CPU speculation-related security vulnerabilities
> + * causing data leaks: see the Linux kernel documentation
> + * Documentation/userspace-api/spec_ctrl.rst
> + *
> + * - Speculative Store Bypass
> + * - Indirect Branch Speculation
> + * - Flush L1D Cache on context switch out of the task
> + */
> +#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)
> + prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, PR_SPEC_ENABLE,
> 0, 0);
> +#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-06 21:56:51.219048292 +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])
> +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],
> @@ -1313,6 +1323,15 @@ fi
>
>
> #
> +# Level 1 Data Cache flushing on context switch (CVE-2020-0550)
> +#
> +if test "$l1d_cache_flushing" = yes ; then
> + AC_DEFINE(ENABLE_L1D_CACHE_FLUSH,1,
> + [Define to enable Layer 1 Data Cache flushing])
> +fi
> +
> +
> +#
> # Checks for header files.
> #
> AC_MSG_NOTICE([checking for header files])
> @@ -1322,6 +1341,13 @@ AC_CHECK_HEADERS([unistd.h langinfo.h te
> ucred.h sys/ucred.h sys/sysmacros.h sys/mkdev.h])
>
>
> +# See whether libc supports the prctl()
> +case "${host}" in
> + *-*-linux*)
> + AC_CHECK_HEADERS([sys/prctl.h])
> + ;;
> +esac
> +
> #
> # Checks for typedefs, structures, and compiler characteristics.
> #
>
> _______________________________________________
> Gnupg-devel mailing list
> Gnupg-devel at gnupg.org
> https://lists.gnupg.org/mailman/listinfo/gnupg-devel
More information about the Gnupg-devel
mailing list