History

mm/huge_memory: preserve pmd_swp_uffd_wp on device-private PMD downgrade

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.

Kiryl Shutsemau (Meta) committed 5 months ago

Commit f7e2c211 parent e92d92b1 file · +2 −0Browse files

Unified · Split

mm/huge_memory.c+2−0
@@ -2565,6 +2565,8 @@ static void change_non_present_huge_pmd(struct mm_struct *mm, · 2564 unmodified lines
2565 } else if (softleaf_is_device_private_write(entry)) {2565 } else if (softleaf_is_device_private_write(entry)) {
2566 entry = make_readable_device_private_entry(swp_offset(entry));2566 entry = make_readable_device_private_entry(swp_offset(entry));
2567 newpmd = swp_entry_to_pmd(entry);2567 newpmd = swp_entry_to_pmd(entry);
2568 if (pmd_swp_uffd_wp(*pmd))
2569 newpmd = pmd_swp_mkuffd_wp(newpmd);
2568 } else {2570 } else {
2569 newpmd = *pmd;2571 newpmd = *pmd;
2570 }2572 }