Commit 51d3d5e
mm/userfaultfd: enable writenotify while userfaultfd-wp is enabled for a VMA
Currently, we don't enable writenotify when enabling userfaultfd-wp on a
shared writable mapping (for now only shmem and hugetlb). The consequence
is that vma->vm_page_prot will still include write permissions, to be set
as default for all PTEs that get remapped (e.g., mprotect(), NUMA hinting,
page migration, ...).
So far, vma->vm_page_prot is assumed to be a safe default, meaning that we
only add permissions (e.g., mkwrite) but not remove permissions (e.g.,
wrprotect). For example, when enabling softdirty tracking, we enable
writenotify. With uffd-wp on shared mappings, that changed. More details
on vma->vm_page_prot semantics were summarized in [1].
This is problematic for uffd-wp: we'd have to manually check for a uffd-wp
PTEs/PMDs and manually write-protect PTEs/PMDs, which is error prone.
Prone to such issues is any code that uses vma->vm_page_prot to set PTE
permissions: primarily pte_modify() and mk_pte().
Instead, let's enable writenotify such that PTEs/PMDs/... will be mapped
write-protected as default and we will only allow selected PTEs that are
definitely safe to be mapped without write-protection (see
can_change_pte_writable()) to be writable. In the future, we might want
to enable write-bit recovery -- e.g., can_change_pte_writable() -- at more
locations, for example, also when removing uffd-wp protection.
This fixes two known cases:
(a) remove_migration_pte() mapping uffd-wp'ed PTEs writable, resulting
in uffd-wp not triggering on write access.
(b) do_numa_page() / do_huge_pmd_numa_page() mapping uffd-wp'ed PTEs/PMDs
writable, resulting in uffd-wp not triggering on write access.
Note that do_numa_page() / do_huge_pmd_numa_page() can be reached even
without NUMA hinting (which currently doesn't seem to be applicable to
shmem), for example, by using uffd-wp with a PROT_WRITE shmem VMA. On
such a VMA, userfaultfd-wp is currently non-functional.
Note that when enabling userfaultfd-wp, there is no need to walk page
tables to enforce the new default protection for the PTEs: we know that
they cannot be uffd-wp'ed yet, because that can only happen after enabling
uffd-wp for the VMA in general.
Also note that this makes mprotect() on ranges with uffd-wp'ed PTEs not
accidentally set the write bit -- which would result in uffd-wp not
triggering on later write access. This commit makes uffd-wp on shmem
behave just like uffd-wp on anonymous memory in that regard, even though,
mixing mprotect with uffd-wp is controversial.
[1] https://lkml.kernel.org/r/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Fixes: b1f9e87 ("mm/uffd: enable write protection for shmem & hugetlbfs")
Signed-off-by: David Hildenbrand <[email protected]>
Reported-by: Ives van Hoorne <[email protected]>
Debugged-by: Peter Xu <[email protected]>
Acked-by: Peter Xu <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Alistair Popple <[email protected]>
Cc: Mike Rapoport <[email protected]>
Cc: Nadav Amit <[email protected]>
Cc: Andrea Arcangeli <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>1 parent ab0c3f1 commit 51d3d5e
2 files changed
+26
-6
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
111 | 126 | | |
112 | 127 | | |
113 | 128 | | |
| |||
618 | 633 | | |
619 | 634 | | |
620 | 635 | | |
621 | | - | |
| 636 | + | |
| 637 | + | |
622 | 638 | | |
623 | 639 | | |
624 | 640 | | |
| |||
652 | 668 | | |
653 | 669 | | |
654 | 670 | | |
655 | | - | |
| 671 | + | |
656 | 672 | | |
657 | 673 | | |
658 | 674 | | |
| |||
733 | 749 | | |
734 | 750 | | |
735 | 751 | | |
736 | | - | |
| 752 | + | |
737 | 753 | | |
738 | 754 | | |
739 | 755 | | |
| |||
895 | 911 | | |
896 | 912 | | |
897 | 913 | | |
898 | | - | |
| 914 | + | |
899 | 915 | | |
900 | 916 | | |
901 | 917 | | |
| |||
1463 | 1479 | | |
1464 | 1480 | | |
1465 | 1481 | | |
1466 | | - | |
| 1482 | + | |
1467 | 1483 | | |
1468 | 1484 | | |
1469 | 1485 | | |
| |||
1651 | 1667 | | |
1652 | 1668 | | |
1653 | 1669 | | |
1654 | | - | |
| 1670 | + | |
1655 | 1671 | | |
1656 | 1672 | | |
1657 | 1673 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1524 | 1524 | | |
1525 | 1525 | | |
1526 | 1526 | | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
1527 | 1531 | | |
1528 | 1532 | | |
1529 | 1533 | | |
| |||
0 commit comments