[tip: x86/fpu] x86/fpu: Fix potential underflow in xstate_calculate_size()

From: tip-bot2 for Andrei Vagin

Date: Fri Sep 25 2026 - 21:12:50 EST


The following commit has been merged into the x86/fpu branch of tip:

Commit-ID: f1751b220bc8a9bd2dc38ecf61f5c29f3826ace0
Gitweb: https://git.kernel.org/tip/f1751b220bc8a9bd2dc38ecf61f5c29f3826ace0
Author: Andrei Vagin <avagin@xxxxxxxxxx>
AuthorDate: Fri, 25 Sep 2026 16:24:51
Committer: Borislav Petkov (AMD) <bp@xxxxxxxxx>
CommitterDate: Fri, 25 Sep 2026 12:25:54 -07:00

x86/fpu: Fix potential underflow in xstate_calculate_size()

xstate_calculate_size() calculates the size required for a given set of
xfeatures. It determines the topmost feature by finding the most
significant bit in xfeatures using fls64(xfeatures) - 1.

If xfeatures is 0, fls64(0) returns 0, and topmost becomes -1.
Previously, topmost was unsigned int, so -1 underflowed to UINT_MAX.
This caused the subsequent check `topmost <= XFEATURE_SSE` to fail, and
the code proceeded to access xstate arrays using topmost (UINT_MAX) as
an index, leading to an out-of-bounds access.

[ bp: Remove text explaining what the patch does. ]

Fixes: d6d6d50f1e80 ("x86/fpu/xstate: Consolidate size calculations")
Signed-off-by: Andrei Vagin <avagin@xxxxxxxxxx>
Signed-off-by: Borislav Petkov (AMD) <bp@xxxxxxxxx>
Reviewed-by: Alexander Mikhalitsyn <alexander@xxxxxxxxxxxxx>
Reviewed-by: Chang S. Bae <chang.seok.bae@xxxxxxxxx>
Link: https://patch.msgid.link/20260925162454.1403405-6-avagin@xxxxxxxxxx
---
arch/x86/kernel/fpu/xstate.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 97cfd4f..efa7879 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -589,12 +589,13 @@ static bool __init check_xstate_against_struct(int nr)

static unsigned int xstate_calculate_size(u64 xfeatures, bool compacted)
{
- unsigned int topmost = fls64(xfeatures) - 1;
- unsigned int offset, i;
+ unsigned int topmost, offset, i;

- if (topmost <= XFEATURE_SSE)
+ if (!(xfeatures & ~XFEATURE_MASK_FPSSE))
return sizeof(struct xregs_state);

+ topmost = fls64(xfeatures) - 1;
+
if (compacted) {
offset = xfeature_get_offset(xfeatures, topmost);
} else {