From: "Kiryl Shutsemau (Meta)" <[email protected]>

change_non_present_huge_pmd() rewrites a writable device-private PMD
swap entry into a readable one without carrying pmd_swp_uffd_wp()
across. The PTE-level change_softleaf_pte() does this correctly;
mirror that here, matching what copy_huge_pmd() does for the fork
path. Without the carry, a plain mprotect() over a UFFD_WP-marked
device-private THP strips the bit and the trap is bypassed on
swap-in.

Fixes: 368076f52ebe ("mm/huge_memory: add device-private THP support to PMD 
operations")
Cc: [email protected]
Reported-by: Sashiko AI review <[email protected]>
Signed-off-by: Kiryl Shutsemau <[email protected]>
---
 mm/huge_memory.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 42b86e8ab7c0..b7c895b1d366 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2663,6 +2663,8 @@ static void change_non_present_huge_pmd(struct mm_struct 
*mm,
        } else if (softleaf_is_device_private_write(entry)) {
                entry = make_readable_device_private_entry(swp_offset(entry));
                newpmd = swp_entry_to_pmd(entry);
+               if (pmd_swp_uffd_wp(*pmd))
+                       newpmd = pmd_swp_mkuffd_wp(newpmd);
        } else {
                newpmd = *pmd;
        }
-- 
2.54.0


Reply via email to