CVE-2025-38170

arm64/fpsimd: Discard stale CPU state when handling SME traps

published July 3, 2025

CVSS
—
EPSS
0%
Percentile
5.6
In the wild
Unconfirmed
What it is

In the Linux kernel, the following vulnerability has been resolved:

arm64/fpsimd: Discard stale CPU state when handling SME traps

The logic for handling SME traps manipulates saved FPSIMD/SVE/SME state

incorrectly, and a race with preemption can result in a task having

TIF_SME set and TIF_FOREIGN_FPSTATE clear even though the live CPU state

is stale (e.g. with SME traps enabled). This can result in warnings from

do_sme_acc() where SME traps are not expected while TIF_SME is set:

| /* With TIF_SME userspace shouldn't generate any traps */

| if (test_and_set_thread_flag(TIF_SME))

| WARN_ON(1);

This is very similar to the SVE issue we fixed in commit:

751ecf6afd6568ad ("arm64/sve: Discard stale CPU state when handling SVE traps")

The race can occur when the SME trap handler is preempted before and

after manipulating the saved FPSIMD/SVE/SME state, starting and ending on

the same CPU, e.g.

| void do_sme_acc(unsigned long esr, struct pt_regs *regs)

| {

| // Trap on CPU 0 with TIF_SME clear, SME traps enabled

| // task->fpsimd_cpu is 0.

| // per_cpu_ptr(&fpsimd_last_state, 0) is task.

|

| ...

|

| // Preempted; migrated from CPU 0 to CPU 1.

| // TIF_FOREIGN_FPSTATE is set.

|

| get_cpu_fpsimd_context();

|

| /* With TIF_SME userspace shouldn't generate any traps */

| if (test_and_set_thread_flag(TIF_SME))

| WARN_ON(1);

|

| if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {

| unsigned long vq_minus_one =

| sve_vq_from_vl(task_get_sme_vl(current)) - 1;

| sme_set_vq(vq_minus_one);

|

| fpsimd_bind_task_to_cpu();

| }

|

| put_cpu_fpsimd_context();

|

| // Preempted; migrated from CPU 1 to CPU 0.

| // task->fpsimd_cpu is still 0

| // If per_cpu_ptr(&fpsimd_last_state, 0) is still task then:

| // - Stale HW state is reused (with SME traps enabled)

| // - TIF_FOREIGN_FPSTATE is cleared

| // - A return to userspace skips HW state restore

| }

Fix the case where the state is not live and TIF_FOREIGN_FPSTATE is set

by calling fpsimd_flush_task_state() to detach from the saved CPU

state. This ensures that a subsequent context switch will not reuse the

stale CPU state, and will instead set TIF_FOREIGN_FPSTATE, forcing the

new state to be reloaded from memory prior to a return to userspace.

Note: this was originallly posted as [1].

[ Rutland: rewrite commit message ]

The record
Technical detail
CVSS
Not scored
CVSS v4.0
Not supplied
EPSS
0.00166 · 5.6th percentile
Published
2025-07-03T08:36Z
EPSS history
Timeline
  • 03 JUL 08:36Z
    arm64/fpsimd: Discard stale CPU state when handling SME traps
    cvelistv5