CVE-2025-37964 (GCVE-0-2025-37964)
Vulnerability from cvelistv5
Published
2025-05-20 16:01
Modified
2026-08-05 11:58
Summary
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.
Impacted products
Vendor Product Version
Linux Linux Version: 848b5815177582de0e1d0118725378e0fbadca20
Version: b47002ed65ade940839b7f439ff4a194e7d5ec28
Version: a04fe3bfc71e28009e20357b79df1e8ef7c9d600
Version: 3dbe889a1b829b4c07e0836ff853fe649e51ce4f
Version: 6db2526c1d694c91c6e05e2f186c085e9460f202
Version: 6db2526c1d694c91c6e05e2f186c085e9460f202
Version: d1347977661342cb09a304a17701eb2d4aa21dec
Version: 5.15.179   
Version: 6.1.129   
Version: 6.6.79   
Version: 6.12.16   
Version: 6.13.4   
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "providerMetadata": {
          "dateUpdated": "2025-11-03T19:57:49.771Z",
          "orgId": "af854a3a-2127-422b-91ae-364da2661108",
          "shortName": "CVE"
        },
        "references": [
          {
            "url": "https://lists.debian.org/debian-lts-announce/2025/08/msg00010.html"
          }
        ],
        "title": "CVE Program Container"
      },
      {
        "affected": [
          {
            "defaultStatus": "unknown",
            "product": "SIMATIC S7-1500 CPU 1518-4 PN/DP MFP",
            "vendor": "Siemens",
            "versions": [
              {
                "lessThan": "*",
                "status": "affected",
                "version": "V3.1.6",
                "versionType": "custom"
              }
            ]
          },
          {
            "defaultStatus": "unknown",
            "product": "SIMATIC S7-1500 CPU 1518-4 PN/DP MFP",
            "vendor": "Siemens",
            "versions": [
              {
                "lessThan": "*",
                "status": "affected",
                "version": "V3.1.6",
                "versionType": "custom"
              }
            ]
          },
          {
            "defaultStatus": "unknown",
            "product": "SIMATIC S7-1500 CPU 1518F-4 PN/DP MFP",
            "vendor": "Siemens",
            "versions": [
              {
                "lessThan": "*",
                "status": "affected",
                "version": "V3.1.6",
                "versionType": "custom"
              }
            ]
          },
          {
            "defaultStatus": "unknown",
            "product": "SIMATIC S7-1500 CPU 1518F-4 PN/DP MFP",
            "vendor": "Siemens",
            "versions": [
              {
                "lessThan": "*",
                "status": "affected",
                "version": "V3.1.6",
                "versionType": "custom"
              }
            ]
          },
          {
            "defaultStatus": "unknown",
            "product": "SIPLUS S7-1500 CPU 1518-4 PN/DP MFP",
            "vendor": "Siemens",
            "versions": [
              {
                "lessThan": "*",
                "status": "affected",
                "version": "V3.1.6",
                "versionType": "custom"
              }
            ]
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-07-14T12:41:16.660Z",
          "orgId": "0b142b55-0307-4c5a-b3c9-f314f3fb7c5e",
          "shortName": "siemens-SADP"
        },
        "references": [
          {
            "url": "https://cert-portal.siemens.com/productcert/html/ssa-019113.html"
          }
        ],
        "x_adpType": "supplier"
      }
    ],
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "arch/x86/mm/tlb.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "12f703811af043d32b1c8a30001b2fa04d5cd0ac",
              "status": "affected",
              "version": "848b5815177582de0e1d0118725378e0fbadca20",
              "versionType": "git"
            },
            {
              "lessThan": "02ad4ce144bd27f71f583f667fdf3b3ba0753477",
              "status": "affected",
              "version": "b47002ed65ade940839b7f439ff4a194e7d5ec28",
              "versionType": "git"
            },
            {
              "lessThan": "d41072906abec8bb8e01ed16afefbaa558908c89",
              "status": "affected",
              "version": "a04fe3bfc71e28009e20357b79df1e8ef7c9d600",
              "versionType": "git"
            },
            {
              "lessThan": "d87392094f96e162fa5fa5a8640d70cc0952806f",
              "status": "affected",
              "version": "3dbe889a1b829b4c07e0836ff853fe649e51ce4f",
              "versionType": "git"
            },
            {
              "lessThan": "399ec9ca8fc4999e676ff89a90184ec40031cf59",
              "status": "affected",
              "version": "6db2526c1d694c91c6e05e2f186c085e9460f202",
              "versionType": "git"
            },
            {
              "lessThan": "fea4e317f9e7e1f449ce90dedc27a2d2a95bee5a",
              "status": "affected",
              "version": "6db2526c1d694c91c6e05e2f186c085e9460f202",
              "versionType": "git"
            },
            {
              "status": "affected",
              "version": "d1347977661342cb09a304a17701eb2d4aa21dec",
              "versionType": "git"
            },
            {
              "lessThan": "5.15.183",
              "status": "affected",
              "version": "5.15.179",
              "versionType": "semver"
            },
            {
              "lessThan": "6.1.139",
              "status": "affected",
              "version": "6.1.129",
              "versionType": "semver"
            },
            {
              "lessThan": "6.6.91",
              "status": "affected",
              "version": "6.6.79",
              "versionType": "semver"
            },
            {
              "lessThan": "6.12.29",
              "status": "affected",
              "version": "6.12.16",
              "versionType": "semver"
            },
            {
              "lessThan": "6.14",
              "status": "affected",
              "version": "6.13.4",
              "versionType": "semver"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "arch/x86/mm/tlb.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "6.14"
            },
            {
              "lessThan": "6.14",
              "status": "unaffected",
              "version": "0",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "5.15.*",
              "status": "unaffected",
              "version": "5.15.183",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.1.*",
              "status": "unaffected",
              "version": "6.1.139",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.6.*",
              "status": "unaffected",
              "version": "6.6.91",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.12.*",
              "status": "unaffected",
              "version": "6.12.29",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.14.*",
              "status": "unaffected",
              "version": "6.14.7",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "6.15",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "5.15.183",
                  "versionStartIncluding": "5.15.179",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.1.139",
                  "versionStartIncluding": "6.1.129",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.6.91",
                  "versionStartIncluding": "6.6.79",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.12.29",
                  "versionStartIncluding": "6.12.16",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.14.7",
                  "versionStartIncluding": "6.14",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.15",
                  "versionStartIncluding": "6.14",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionStartIncluding": "6.13.4",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nx86/mm: Eliminate window where TLB flushes may be inadvertently skipped\n\ntl;dr: There is a window in the mm switching code where the new CR3 is\nset and the CPU should be getting TLB flushes for the new mm.  But\nshould_flush_tlb() has a bug and suppresses the flush.  Fix it by\nwidening the window where should_flush_tlb() sends an IPI.\n\nLong Version:\n\n=== History ===\n\nThere were a few things leading up to this.\n\nFirst, updating mm_cpumask() was observed to be too expensive, so it was\nmade lazier.  But being lazy caused too many unnecessary IPIs to CPUs\ndue to the now-lazy mm_cpumask().  So code was added to cull\nmm_cpumask() periodically[2].  But that culling was a bit too aggressive\nand skipped sending TLB flushes to CPUs that need them.  So here we are\nagain.\n\n=== Problem ===\n\nThe too-aggressive code in should_flush_tlb() strikes in this window:\n\n\t// Turn on IPIs for this CPU/mm combination, but only\n\t// if should_flush_tlb() agrees:\n\tcpumask_set_cpu(cpu, mm_cpumask(next));\n\n\tnext_tlb_gen = atomic64_read(\u0026next-\u003econtext.tlb_gen);\n\tchoose_new_asid(next, next_tlb_gen, \u0026new_asid, \u0026need_flush);\n\tload_new_mm_cr3(need_flush);\n\t// ^ After \u0027need_flush\u0027 is set to false, IPIs *MUST*\n\t// be sent to this CPU and not be ignored.\n\n        this_cpu_write(cpu_tlbstate.loaded_mm, next);\n\t// ^ Not until this point does should_flush_tlb()\n\t// become true!\n\nshould_flush_tlb() will suppress TLB flushes between load_new_mm_cr3()\nand writing to \u0027loaded_mm\u0027, which is a window where they should not be\nsuppressed.  Whoops.\n\n=== Solution ===\n\nThankfully, the fuzzy \"just about to write CR3\" window is already marked\nwith loaded_mm==LOADED_MM_SWITCHING.  Simply checking for that state in\nshould_flush_tlb() is sufficient to ensure that the CPU is targeted with\nan IPI.\n\nThis will cause more TLB flush IPIs.  But the window is relatively small\nand I do not expect this to cause any kind of measurable performance\nimpact.\n\nUpdate the comment where LOADED_MM_SWITCHING is written since it grew\nyet another user.\n\nPeter Z also raised a concern that should_flush_tlb() might not observe\n\u0027loaded_mm\u0027 and \u0027is_lazy\u0027 in the same order that switch_mm_irqs_off()\nwrites them.  Add a barrier to ensure that they are observed in the\norder they are written."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "baseScore": 7.8,
            "baseSeverity": "HIGH",
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
            "version": "3.1"
          },
          "scenarios": [
            {
              "lang": "en",
              "value": "AV:L - The race is driven entirely through local syscalls (`madvise(MADV_DONTNEED)`/`mprotect`/`munmap` plus thread creation and CPU affinity) combined with scheduler-driven `switch_mm_irqs_off()` transitions; there is no network-reachable path into `arch/x86/mm/tlb.c`.\nAC:L - The attacker controls both sides of the race \u2014 one pinned thread loops TLB-flushing operations on a shared mm while other threads force repeated context switches into that mm on another CPU \u2014 and can retry millions of times per second; the window spans the CR3 write, and the bug was observed triggering under ordinary production workloads without adversarial tuning.\nPR:L - Every ingredient (multithreaded process, `madvise`/`mprotect` on its own anonymous memory, `sched_setaffinity`, `sched_yield`) is available to any unprivileged local user with no capabilities and no namespace tricks required.\nUI:N - The attacking process triggers the missed flush entirely on its own; no victim action, mount, or file open is involved.\nS:U - The stale TLB entry and the resulting memory corruption are both within the kernel/OS security authority; no hypervisor, IOMMU, or sandbox boundary is crossed as defined by CVSS scope.\nC:H - A suppressed flush leaves a live user mapping to a physical page the kernel has already freed and reallocated, allowing the attacker to read page-cache contents, other processes\u0027 anonymous memory, or kernel data placed in that page \u2014 effectively arbitrary memory disclosure.\nI:H - The retained mapping is writable, so the attacker can write into reallocated pages including page tables and kernel slab objects, yielding an arbitrary-write primitive and privilege escalation; missed flushes after COW/KSM write-protect additionally allow writing pages now shared with other processes.\nA:H - Writes through stale entries into recycled kernel page tables and slab objects corrupt kernel state, producing oopses and panics \u2014 the class of corruption that prompted the original production bug report."
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-08-05T11:58:41.507Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/12f703811af043d32b1c8a30001b2fa04d5cd0ac"
        },
        {
          "url": "https://git.kernel.org/stable/c/02ad4ce144bd27f71f583f667fdf3b3ba0753477"
        },
        {
          "url": "https://git.kernel.org/stable/c/d41072906abec8bb8e01ed16afefbaa558908c89"
        },
        {
          "url": "https://git.kernel.org/stable/c/d87392094f96e162fa5fa5a8640d70cc0952806f"
        },
        {
          "url": "https://git.kernel.org/stable/c/399ec9ca8fc4999e676ff89a90184ec40031cf59"
        },
        {
          "url": "https://git.kernel.org/stable/c/fea4e317f9e7e1f449ce90dedc27a2d2a95bee5a"
        }
      ],
      "title": "x86/mm: Eliminate window where TLB flushes may be inadvertently skipped",
      "x_generator": {
        "engine": "bippy-1.2.0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2025-37964",
    "datePublished": "2025-05-20T16:01:56.013Z",
    "dateReserved": "2025-04-16T04:51:23.974Z",
    "dateUpdated": "2026-08-05T11:58:41.507Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…

Loading…