From: "Kiryl Shutsemau (Meta)" 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: stable@vger.kernel.org Reported-by: Sashiko AI review Signed-off-by: Kiryl Shutsemau --- 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