Skip to content

Commit c5977c9

Browse files
xzpeterakpm00
authored andcommitted
mm/userfaultfd: allow hugetlb change protection upon poison entry
After UFFDIO_POISON, there can be two kinds of hugetlb pte markers, either the POISON one or UFFD_WP one. Allow change protection to run on a poisoned marker just like !hugetlb cases, ignoring the marker irrelevant of the permission. Here the two bits are mutual exclusive. For example, when install a poisoned entry it must not be UFFD_WP already (by checking pte_none() before such install). And it also means if UFFD_WP is set there must have no POISON bit set. It makes sense because UFFD_WP is a bit to reflect permission, and permissions do not apply if the pte is poisoned and destined to sigbus. So here we simply check uffd_wp bit set first, do nothing otherwise. Attach the Fixes to UFFDIO_POISON work, as before that it should not be possible to have poison entry for hugetlb (e.g., hugetlb doesn't do swap, so no chance of swapin errors). Link: https://lkml.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected] Fixes: fc71884 ("mm: userfaultfd: add new UFFDIO_POISON ioctl") Signed-off-by: Peter Xu <[email protected]> Reported-by: [email protected] Reviewed-by: David Hildenbrand <[email protected]> Reviewed-by: Axel Rasmussen <[email protected]> Cc: <[email protected]> [6.6+] Signed-off-by: Andrew Morton <[email protected]>
1 parent 7401745 commit c5977c9

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

mm/hugetlb.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7044,9 +7044,13 @@ long hugetlb_change_protection(struct vm_area_struct *vma,
70447044
if (!pte_same(pte, newpte))
70457045
set_huge_pte_at(mm, address, ptep, newpte, psize);
70467046
} else if (unlikely(is_pte_marker(pte))) {
7047-
/* No other markers apply for now. */
7048-
WARN_ON_ONCE(!pte_marker_uffd_wp(pte));
7049-
if (uffd_wp_resolve)
7047+
/*
7048+
* Do nothing on a poison marker; page is
7049+
* corrupted, permissons do not apply. Here
7050+
* pte_marker_uffd_wp()==true implies !poison
7051+
* because they're mutual exclusive.
7052+
*/
7053+
if (pte_marker_uffd_wp(pte) && uffd_wp_resolve)
70507054
/* Safe to modify directly (non-present->none). */
70517055
huge_pte_clear(mm, address, ptep, psize);
70527056
} else if (!huge_pte_none(pte)) {

0 commit comments

Comments
 (0)