CVE-2025-37964

In the Linux kernel, the following vulnerability has been resolved: x86/mm: Eliminate window where TLB flushes may be inadvertently skipped tl;dr: There is a window in the mm switching code where the new CR3 is set and the CPU should be getting TLB flushes for the new mm. But should_flush_tlb() has a bug and suppresses the flush. Fix it by widening the window where should_flush_tlb() sends an IPI. Long Version: === History === There were a few things leading up to this. First, updating mm_cpumask() was observed to be too expensive, so it was made lazier. But being lazy caused too many unnecessary IPIs to CPUs due to the now-lazy mm_cpumask(). So code was added to cull mm_cpumask() periodically[2]. But that culling was a bit too aggressive and skipped sending TLB flushes to CPUs that need them. So here we are again. === Problem === The too-aggressive code in should_flush_tlb() strikes in this window: // Turn on IPIs for this CPU/mm combination, but only // if should_flush_tlb() agrees: cpumask_set_cpu(cpu, mm_cpumask(next)); next_tlb_gen = atomic64_read(&next->context.tlb_gen); choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush); load_new_mm_cr3(need_flush); // ^ After 'need_flush' is set to false, IPIs *MUST* // be sent to this CPU and not be ignored. this_cpu_write(cpu_tlbstate.loaded_mm, next); // ^ Not until this point does should_flush_tlb() // become true! should_flush_tlb() will suppress TLB flushes between load_new_mm_cr3() and writing to 'loaded_mm', which is a window where they should not be suppressed. Whoops. === Solution === Thankfully, the fuzzy "just about to write CR3" window is already marked with loaded_mm==LOADED_MM_SWITCHING. Simply checking for that state in should_flush_tlb() is sufficient to ensure that the CPU is targeted with an IPI. This will cause more TLB flush IPIs. But the window is relatively small and I do not expect this to cause any kind of measurable performance impact. Update the comment where LOADED_MM_SWITCHING is written since it grew yet another user. Peter Z also raised a concern that should_flush_tlb() might not observe 'loaded_mm' and 'is_lazy' in the same order that switch_mm_irqs_off() writes them. Add a barrier to ensure that they are observed in the order they are written.
Configurations

Configuration 1 (hide)

OR cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc5:*:*:*:*:*:*

Configuration 2 (hide)

cpe:2.3:o:debian:debian_linux:11.0:*:*:*:*:*:*:*

History

16 Dec 2025, 20:30

Type Values Removed Values Added
CPE cpe:2.3:o:linux:linux_kernel:6.15:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc5:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc2:*:*:*:*:*:*
cpe:2.3:o:debian:debian_linux:11.0:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc1:*:*:*:*:*:*
CVSS v2 : unknown
v3 : unknown
v2 : unknown
v3 : 5.5
First Time Linux
Debian
Debian debian Linux
Linux linux Kernel
CWE NVD-CWE-noinfo
References () https://git.kernel.org/stable/c/02ad4ce144bd27f71f583f667fdf3b3ba0753477 - () https://git.kernel.org/stable/c/02ad4ce144bd27f71f583f667fdf3b3ba0753477 - Patch
References () https://git.kernel.org/stable/c/12f703811af043d32b1c8a30001b2fa04d5cd0ac - () https://git.kernel.org/stable/c/12f703811af043d32b1c8a30001b2fa04d5cd0ac - Patch
References () https://git.kernel.org/stable/c/399ec9ca8fc4999e676ff89a90184ec40031cf59 - () https://git.kernel.org/stable/c/399ec9ca8fc4999e676ff89a90184ec40031cf59 - Patch
References () https://git.kernel.org/stable/c/d41072906abec8bb8e01ed16afefbaa558908c89 - () https://git.kernel.org/stable/c/d41072906abec8bb8e01ed16afefbaa558908c89 - Patch
References () https://git.kernel.org/stable/c/d87392094f96e162fa5fa5a8640d70cc0952806f - () https://git.kernel.org/stable/c/d87392094f96e162fa5fa5a8640d70cc0952806f - Patch
References () https://git.kernel.org/stable/c/fea4e317f9e7e1f449ce90dedc27a2d2a95bee5a - () https://git.kernel.org/stable/c/fea4e317f9e7e1f449ce90dedc27a2d2a95bee5a - Patch
References () https://lists.debian.org/debian-lts-announce/2025/08/msg00010.html - () https://lists.debian.org/debian-lts-announce/2025/08/msg00010.html - Third Party Advisory

03 Nov 2025, 20:18

Type Values Removed Values Added
References
  • () https://lists.debian.org/debian-lts-announce/2025/08/msg00010.html -
Summary
  • (es) En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: x86/mm: Eliminar la ventana donde los vaciados de TLB pueden omitirse inadvertidamente tl;dr: Hay una ventana en el código de conmutación mm donde se establece el nuevo CR3 y la CPU debería obtener vaciados de TLB para el nuevo mm. Pero should_flush_tlb() tiene un error y suprime el vaciado. Arréglelo ampliando la ventana donde should_flush_tlb() envía una IPI. Versión larga: === Historial === Hubo algunas cosas que llevaron a esto. Primero, se observó que actualizar mm_cpumask() era demasiado costoso, por lo que se hizo más perezoso. Pero ser perezoso causó demasiados IPI innecesarios a las CPU debido al ahora perezoso mm_cpumask(). Entonces se agregó código para descartar mm_cpumask() periódicamente[2]. Pero ese descarte fue demasiado agresivo y omitió el envío de vaciados de TLB a las CPU que los necesitan. Así que aquí estamos de nuevo. === Problema === El código demasiado agresivo en should_flush_tlb() ataca en esta ventana: // Activa las IPI para esta combinación de CPU/mm, pero solo si should_flush_tlb() está de acuerdo: cpumask_set_cpu(cpu, mm_cpumask(next)); next_tlb_gen = atomic64_read(&next->context.tlb_gen); choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush); load_new_mm_cr3(need_flush); // ^ Después de que 'need_flush' se establece en falso, las IPI *DEBEN* // enviarse a esta CPU y no ignorarse. this_cpu_write(cpu_tlbstate.loaded_mm, next); // ^ ¡No es hasta este punto que should_flush_tlb() // se vuelve verdadero! should_flush_tlb() suprimirá los vaciados de TLB entre load_new_mm_cr3() y la escritura en 'loaded_mm', que es una ventana donde no deberían suprimirse. ¡Uy! === Solución === Afortunadamente, la ventana difusa "a punto de escribir CR3" ya está marcada con load_mm==LOADED_MM_SWITCHING. Simplemente comprobar ese estado en should_flush_tlb() es suficiente para asegurar que la CPU esté dirigida a un IPI. Esto provocará más IPI de vaciado de TLB. Sin embargo, la ventana es relativamente pequeña y no preveo que esto tenga ningún impacto medible en el rendimiento. Actualice el comentario donde se escribe LOADED_MM_SWITCHING, ya que ha generado otro usuario. Peter Z también planteó la preocupación de que should_flush_tlb() podría no observar 'loaded_mm' e 'is_lazy' en el mismo orden en que switch_mm_irqs_off() los escribe. Añade una barrera para garantizar que se observen en el orden en que están escritos.

20 May 2025, 16:15

Type Values Removed Values Added
New CVE

Information

Published : 2025-05-20 16:15

Updated : 2025-12-16 20:30


NVD link : CVE-2025-37964

Mitre link : CVE-2025-37964

CVE.ORG link : CVE-2025-37964


JSON object : View

Products Affected

debian

  • debian_linux

linux

  • linux_kernel