CVE-2026-53155

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
25/06/2026
Last modified:
07/07/2026

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> mm/huge_memory: use correct flags for device private PMD entry<br /> <br /> Commit 65edfda6f3f2 ("mm/rmap: extend rmap and migration support<br /> device-private entries") updated set_pmd_migration_entry() to use<br /> pmdp_huge_get_and_clear() in the softleaf case, but made no further<br /> adjustments to the function itself.<br /> <br /> Therefore this function continues to incorrectly use pmd_write(),<br /> pmd_soft_dirty() and pmd_uffd_wp() to determine whether the installed<br /> migration entry should be marked writable, softdirty or uffd-wp<br /> respectively.<br /> <br /> Whilst all are incorrect, the most problematic of these is pmd_write(), as<br /> this can lead to corrupted rmap state.<br /> <br /> On x86-64 _PAGE_SWP_SOFT_DIRTY is aliased to _PAGE_RW. So calling<br /> pmd_write() on a softleaf will return the softdirty state encoded in the<br /> entry, assuming CONFIG_MEM_SOFT_DIRTY was enabled.<br /> <br /> This was observed when running the hmm.hmm_device_private.anon_write_child<br /> selftest:<br /> <br /> 1. The test faults in a range then migrates it such that a device-private<br /> THP range is established.<br /> <br /> 2. The parent then migrates it to a device-private writable PMD entry whose<br /> folio is entirely AnonExclusive with entire_mapcount=1, softdirty set<br /> (accidentally correct write state).<br /> <br /> 3. The parent forks and the PMD entries are set to device-private read only<br /> entries, entire_mapcount=2, softdirty still set.<br /> <br /> 4. [BUG] The child writes to the range then migrates to RAM - intending to<br /> install non-writable migration entries - but replacing parent and child<br /> PMD mappings with WRITABLE entries due to misinterpreting the softdirty<br /> bit.<br /> <br /> 5. In remove_migration_pmd(), if !softleaf_is_migration_read(entry) we<br /> set the RMAP_EXCLUSIVE flag when calling folio_add_anon_rmap_pmd() for<br /> both parent and child, which are therefore AnonExclusive.<br /> <br /> 6. [SPLAT] Child sets migrated folio entire_mapcount=1, parent sets<br /> entire_mapcount=2 and we end up with an AnonExclusive folio with<br /> entire_mapcount=2! Assert fires in __folio_add_anon_rmap():<br /> <br /> VM_WARN_ON_FOLIO(folio_test_large(folio) &amp;&amp;<br /> folio_entire_mapcount(folio) &gt; 1 &amp;&amp;<br /> PageAnonExclusive(cur_page), folio)<br /> <br /> This patch fixes the issue by correctly referencing the softleaf entry<br /> fields for writable, softdirty and uffd-wp in set_pmd_migration_entry().<br /> <br /> It also only updates A/D flags if the entry is present as these are<br /> otherwise not meaningful for a softleaf entry.<br /> <br /> This patch also flips the if (!present) { ... } else { ... } logic in<br /> set_pmd_migration_entry() so it is easier to understand, and adds some<br /> comments to make things clearer.<br /> <br /> I was able to bisect this to commit 775465fd26a3 ("lib/test_hmm: add zone<br /> device private THP test infrastructure") which first exposes this bug as<br /> it was the commit that permitted test_hmm to generate the test.<br /> <br /> However commit 65edfda6f3f2 ("mm/rmap: extend rmap and migration support<br /> device-private entries") is the commit that actually enabled this<br /> behaviour.

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.19 (including) 7.0.13 (excluding)
cpe:2.3:o:linux:linux_kernel:7.1:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc5:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc6:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc7:*:*:*:*:*:*