Xen Security Advisory 488 v1 - x86: Floating Point Divider State Sampling

Xen.org security team posted 1 patch 2 weeks ago
Failed in applying to current master (apply log)
Xen Security Advisory 488 v1 - x86: Floating Point Divider State Sampling
Posted by Xen.org security team 2 weeks ago
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

                    Xen Security Advisory XSA-488

              x86: Floating Point Divider State Sampling

ISSUE DESCRIPTION
=================

Researchers from the CISPA Helmholtz Center for Information Security have
discovered Floating Point Divider State Sampling.  It is detailed in a paper
titled "TREVEX: A Black-Box Detection Framework For Data-Flow Transient
Execution Vulnerabilities"

For more information, see:
  https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7053.html
  https://roots.ec/blog/fpdss/

IMPACT
======

An attacker might be able to infer data belonging to other contexts,
including data belonging to other guests.

VULNERABLE SYSTEMS
==================

Systems running all versions of Xen are affected.

Only AMD Fam17h CPUs (Zen1 microarchitecture) are believed to be
vulnerable.  Other AMD CPUs and CPUs from other manufacturers are not
known to be affected.

MITIGATION
==========

There are no mitigations.

RESOLUTION
==========

Applying the appropriate attached patch resolves this issue.

Note that patches for released versions are generally prepared to
apply to the stable branches, and may not apply cleanly to the most
recent release tarball.  Downstreams are encouraged to update to the
tip of the stable branch before applying these patches.

xsa488.patch           xen-unstable - Xen 4.21.x
xsa488-4.20.patch      Xen 4.20.x - Xen 4.19.x
xsa488-4.18.patch      Xen 4.18.x
xsa488-4.17.patch      Xen 4.17.x

$ sha256sum xsa488*
3dde61413eb75cb65fbd20b58165f673f9f4610804ec532ff0bf3c3f469454c1  xsa488.patch
7822abb0ed5a5f8e2b8697db41d46e030fd69bf8ca8cb965022484b287d9ea26  xsa488-4.17.patch
6668f9d1433863522b8554dc324f57efcfcf3e00c9261c0ee5c2db17f63bccd6  xsa488-4.18.patch
275c35d05951c4583056904869183972b9699549f0ec59f946faa92d5cef4b21  xsa488-4.20.patch
$

DEPLOYMENT DURING EMBARGO
=========================

Deployment of the patches and/or mitigations described above (or
others which are substantially similar) is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators.

But: Distribution of updated software is prohibited (except to other
members of the predisclosure list).

Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.


(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable.  This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)

For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
  http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----

iQFABAEBCAAqFiEEI+MiLBRfRHX6gGCng/4UyVfoK9kFAmnhBsUMHHBncEB4ZW4u
b3JnAAoJEIP+FMlX6CvZR90IAJ4bu4Ig/J4NOiTOPysLApkrzjyqrrDFqVvsUJe7
UDyll64Yuj4ljj25nDewGDG14EgdMJwqsWqM9gKl07eTzKnOxzzlsymyvX8BxiMt
F7hlcsc2WW96jE2FMNpNUjoBTORQ6u+rYsG1J7Kv85PdM4KHivrXzXRswTQlGWBU
d3VFnyQYE6jIGNGz1WXgA0/CxkdkTUAC0iN0NB6PSlurfkGCDqJEE3/LrTGWUEhI
T30jEc4cCjfukI4YtrCiecCKtSUvzdiRZ+5ZLYrzOYePBOmGOXrxlFfHt4zE6mK0
J9IzVS5BJJVhXjQWZyoZdDgFKMlk6rTQy73hWyPNFyBUiY4=
=xsxg
-----END PGP SIGNATURE-----
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/amd: Mitigate AMD-SN-7053 / FP-DSS

This is XSA-488 / CVE-2025-54505

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 45b55b7a8cf9..712734a6e723 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -947,6 +947,42 @@ void amd_init_de_cfg(const struct cpuinfo_x86 *c)
     wrmsr(MSR_AMD64_DE_CFG, val | new);
 }
 
+static void amd_init_fp_cfg(const struct cpuinfo_x86 *c)
+{
+    uint64_t val, new = 0;
+
+    /* If virtualised, we won't have mutable access even if we can read it. */
+    if ( cpu_has_hypervisor )
+        return;
+
+    /*
+     * On Zen1, mitigate SB-7053 / FP-DSS Floating Point Divider State
+     * Sampling by setting bit 9 as instructed.
+     */
+    if ( c->family == 0x17 && is_zen1_uarch() )
+        new |= 1 << 9;
+
+    /*
+     * Avoid reading FP_CFG if we don't intend to change anything.  The
+     * register doesn't exist on all families.
+     */
+    if ( !new )
+        return;
+
+    val = rdmsr(MSR_AMD64_FP_CFG);
+
+    if ( (val & new) == new )
+        return;
+
+    /*
+     * FP_CFG is a Core-scoped MSR, and this write is racy.  However, both
+     * threads calculate the new value from state which expected to be
+     * consistent across CPUs and unrelated to the old value, so the result
+     * should be consistent.
+     */
+    wrmsr(MSR_AMD64_FP_CFG, val | new);
+}
+
 void __init amd_init_lfence_dispatch(void)
 {
     struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -1019,6 +1055,7 @@ static void cf_check init_amd(struct cpuinfo_x86 *c)
 	uint64_t value;
 
 	amd_init_de_cfg(c);
+	amd_init_fp_cfg(c);
 
 	if (c == &boot_cpu_data)
 		amd_init_lfence_dispatch(); /* Needs amd_init_de_cfg() */
diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h
index b92a278611cb..ad1c6c97f8f7 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -431,6 +431,7 @@
 #define MSR_AMD64_LS_CFG		0xc0011020U
 #define MSR_AMD64_IC_CFG		0xc0011021U
 #define MSR_AMD64_DC_CFG		0xc0011022U
+#define MSR_AMD64_FP_CFG		0xc0011028U
 #define MSR_AMD64_DE_CFG		0xc0011029U
 #define AMD64_DE_CFG_LFENCE_SERIALISE	(_AC(1, ULL) << 1)
 #define MSR_AMD64_EX_CFG		0xc001102cU
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/amd: Mitigate AMD-SN-7053 / FP-DSS

This is XSA-488 / CVE-2025-54505

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 2838725bab98..3312d896dd90 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -982,6 +982,42 @@ static void cf_check fam17_disable_c6(void *arg)
 	wrmsrl(MSR_AMD_CSTATE_CFG, val & mask);
 }
 
+static void amd_init_fp_cfg(const struct cpuinfo_x86 *c)
+{
+    uint64_t val, new = 0;
+
+    /* If virtualised, we won't have mutable access even if we can read it. */
+    if ( cpu_has_hypervisor )
+        return;
+
+    /*
+     * On Zen1, mitigate SB-7053 / FP-DSS Floating Point Divider State
+     * Sampling by setting bit 9 as instructed.
+     */
+    if ( c->x86 == 0x17 && is_zen1_uarch() )
+        new |= 1 << 9;
+
+    /*
+     * Avoid reading FP_CFG if we don't intend to change anything.  The
+     * register doesn't exist on all families.
+     */
+    if ( !new )
+        return;
+
+    rdmsrl(MSR_AMD64_FP_CFG, val);
+
+    if ( (val & new) == new )
+        return;
+
+    /*
+     * FP_CFG is a Core-scoped MSR, and this write is racy.  However, both
+     * threads calculate the new value from state which expected to be
+     * consistent across CPUs and unrelated to the old value, so the result
+     * should be consistent.
+     */
+    wrmsrl(MSR_AMD64_FP_CFG, val | new);
+}
+
 static void amd_check_erratum_1485(void)
 {
 	uint64_t val, chickenbit = (1 << 5);
@@ -1009,6 +1045,8 @@ static void cf_check init_amd(struct cpuinfo_x86 *c)
 
 	unsigned long long value;
 
+	amd_init_fp_cfg(c);
+
 	/* Disable TLB flush filter by setting HWCR.FFDIS on K8
 	 * bit 6 of msr C001_0015
 	 *
diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h
index 521079191af7..bed0ab7b213c 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -386,6 +386,7 @@
 #define MSR_AMD64_LS_CFG		0xc0011020
 #define MSR_AMD64_IC_CFG		0xc0011021
 #define MSR_AMD64_DC_CFG		0xc0011022
+#define MSR_AMD64_FP_CFG		0xc0011028
 #define MSR_AMD64_DE_CFG		0xc0011029
 #define AMD64_DE_CFG_LFENCE_SERIALISE	(_AC(1, ULL) << 1)
 #define MSR_AMD64_EX_CFG		0xc001102c
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/amd: Mitigate AMD-SN-7053 / FP-DSS

This is XSA-488 / CVE-2025-54505

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index c448997be551..43cd3ae9ba4d 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -1009,6 +1009,42 @@ static void cf_check fam17_disable_c6(void *arg)
 	wrmsrl(MSR_AMD_CSTATE_CFG, val & mask);
 }
 
+static void amd_init_fp_cfg(const struct cpuinfo_x86 *c)
+{
+    uint64_t val, new = 0;
+
+    /* If virtualised, we won't have mutable access even if we can read it. */
+    if ( cpu_has_hypervisor )
+        return;
+
+    /*
+     * On Zen1, mitigate SB-7053 / FP-DSS Floating Point Divider State
+     * Sampling by setting bit 9 as instructed.
+     */
+    if ( c->x86 == 0x17 && is_zen1_uarch() )
+        new |= 1 << 9;
+
+    /*
+     * Avoid reading FP_CFG if we don't intend to change anything.  The
+     * register doesn't exist on all families.
+     */
+    if ( !new )
+        return;
+
+    rdmsrl(MSR_AMD64_FP_CFG, val);
+
+    if ( (val & new) == new )
+        return;
+
+    /*
+     * FP_CFG is a Core-scoped MSR, and this write is racy.  However, both
+     * threads calculate the new value from state which expected to be
+     * consistent across CPUs and unrelated to the old value, so the result
+     * should be consistent.
+     */
+    wrmsrl(MSR_AMD64_FP_CFG, val | new);
+}
+
 static void amd_check_bp_cfg(void)
 {
 	uint64_t val, new = 0;
@@ -1053,6 +1089,8 @@ static void cf_check init_amd(struct cpuinfo_x86 *c)
 
 	unsigned long long value;
 
+	amd_init_fp_cfg(c);
+
 	/* Disable TLB flush filter by setting HWCR.FFDIS on K8
 	 * bit 6 of msr C001_0015
 	 *
diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h
index c9f980cd577f..516ee26d7079 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -411,6 +411,7 @@
 #define MSR_AMD64_LS_CFG		0xc0011020
 #define MSR_AMD64_IC_CFG		0xc0011021
 #define MSR_AMD64_DC_CFG		0xc0011022
+#define MSR_AMD64_FP_CFG		0xc0011028
 #define MSR_AMD64_DE_CFG		0xc0011029
 #define AMD64_DE_CFG_LFENCE_SERIALISE	(_AC(1, ULL) << 1)
 #define MSR_AMD64_EX_CFG		0xc001102c
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/amd: Mitigate AMD-SN-7053 / FP-DSS

This is XSA-488 / CVE-2025-54505

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index d5069a7ec18e..43883e04dbb9 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -982,6 +982,42 @@ void amd_init_de_cfg(const struct cpuinfo_x86 *c)
     wrmsrl(MSR_AMD64_DE_CFG, val | new);
 }
 
+static void amd_init_fp_cfg(const struct cpuinfo_x86 *c)
+{
+    uint64_t val, new = 0;
+
+    /* If virtualised, we won't have mutable access even if we can read it. */
+    if ( cpu_has_hypervisor )
+        return;
+
+    /*
+     * On Zen1, mitigate SB-7053 / FP-DSS Floating Point Divider State
+     * Sampling by setting bit 9 as instructed.
+     */
+    if ( c->x86 == 0x17 && is_zen1_uarch() )
+        new |= 1 << 9;
+
+    /*
+     * Avoid reading FP_CFG if we don't intend to change anything.  The
+     * register doesn't exist on all families.
+     */
+    if ( !new )
+        return;
+
+    rdmsrl(MSR_AMD64_FP_CFG, val);
+
+    if ( (val & new) == new )
+        return;
+
+    /*
+     * FP_CFG is a Core-scoped MSR, and this write is racy.  However, both
+     * threads calculate the new value from state which expected to be
+     * consistent across CPUs and unrelated to the old value, so the result
+     * should be consistent.
+     */
+    wrmsrl(MSR_AMD64_FP_CFG, val | new);
+}
+
 void __init amd_init_lfence_dispatch(void)
 {
     struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -1055,6 +1091,7 @@ static void cf_check init_amd(struct cpuinfo_x86 *c)
 	unsigned long long value;
 
 	amd_init_de_cfg(c);
+	amd_init_fp_cfg(c);
 
 	if (c == &boot_cpu_data)
 		amd_init_lfence_dispatch(); /* Needs amd_init_de_cfg() */
diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h
index 6f2c3147e343..70e5f09a2de4 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -411,6 +411,7 @@
 #define MSR_AMD64_LS_CFG		0xc0011020U
 #define MSR_AMD64_IC_CFG		0xc0011021U
 #define MSR_AMD64_DC_CFG		0xc0011022U
+#define MSR_AMD64_FP_CFG		0xc0011028U
 #define MSR_AMD64_DE_CFG		0xc0011029U
 #define AMD64_DE_CFG_LFENCE_SERIALISE	(_AC(1, ULL) << 1)
 #define MSR_AMD64_EX_CFG		0xc001102cU