]>
Commit | Line | Data |
---|---|---|
5c17fab8 GKH |
1 | From c5977c95dff182d6ee06f4d6f60bcb0284912969 Mon Sep 17 00:00:00 2001 |
2 | From: Peter Xu <peterx@redhat.com> | |
3 | Date: Fri, 5 Apr 2024 19:19:20 -0400 | |
4 | Subject: mm/userfaultfd: allow hugetlb change protection upon poison entry | |
5 | ||
6 | From: Peter Xu <peterx@redhat.com> | |
7 | ||
8 | commit c5977c95dff182d6ee06f4d6f60bcb0284912969 upstream. | |
9 | ||
10 | After UFFDIO_POISON, there can be two kinds of hugetlb pte markers, either | |
11 | the POISON one or UFFD_WP one. | |
12 | ||
13 | Allow change protection to run on a poisoned marker just like !hugetlb | |
14 | cases, ignoring the marker irrelevant of the permission. | |
15 | ||
16 | Here the two bits are mutual exclusive. For example, when install a | |
17 | poisoned entry it must not be UFFD_WP already (by checking pte_none() | |
18 | before such install). And it also means if UFFD_WP is set there must have | |
19 | no POISON bit set. It makes sense because UFFD_WP is a bit to reflect | |
20 | permission, and permissions do not apply if the pte is poisoned and | |
21 | destined to sigbus. | |
22 | ||
23 | So here we simply check uffd_wp bit set first, do nothing otherwise. | |
24 | ||
25 | Attach the Fixes to UFFDIO_POISON work, as before that it should not be | |
26 | possible to have poison entry for hugetlb (e.g., hugetlb doesn't do swap, | |
27 | so no chance of swapin errors). | |
28 | ||
29 | Link: https://lkml.kernel.org/r/20240405231920.1772199-1-peterx@redhat.com | |
30 | Link: https://lore.kernel.org/r/000000000000920d5e0615602dd1@google.com | |
31 | Fixes: fc71884a5f59 ("mm: userfaultfd: add new UFFDIO_POISON ioctl") | |
32 | Signed-off-by: Peter Xu <peterx@redhat.com> | |
33 | Reported-by: syzbot+b07c8ac8eee3d4d8440f@syzkaller.appspotmail.com | |
34 | Reviewed-by: David Hildenbrand <david@redhat.com> | |
35 | Reviewed-by: Axel Rasmussen <axelrasmussen@google.com> | |
36 | Cc: <stable@vger.kernel.org> [6.6+] | |
37 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
38 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
39 | --- | |
40 | mm/hugetlb.c | 10 +++++++--- | |
41 | 1 file changed, 7 insertions(+), 3 deletions(-) | |
42 | ||
43 | --- a/mm/hugetlb.c | |
44 | +++ b/mm/hugetlb.c | |
45 | @@ -6943,9 +6943,13 @@ long hugetlb_change_protection(struct vm | |
46 | if (!pte_same(pte, newpte)) | |
47 | set_huge_pte_at(mm, address, ptep, newpte, psize); | |
48 | } else if (unlikely(is_pte_marker(pte))) { | |
49 | - /* No other markers apply for now. */ | |
50 | - WARN_ON_ONCE(!pte_marker_uffd_wp(pte)); | |
51 | - if (uffd_wp_resolve) | |
52 | + /* | |
53 | + * Do nothing on a poison marker; page is | |
54 | + * corrupted, permissons do not apply. Here | |
55 | + * pte_marker_uffd_wp()==true implies !poison | |
56 | + * because they're mutual exclusive. | |
57 | + */ | |
58 | + if (pte_marker_uffd_wp(pte) && uffd_wp_resolve) | |
59 | /* Safe to modify directly (non-present->none). */ | |
60 | huge_pte_clear(mm, address, ptep, psize); | |
61 | } else if (!huge_pte_none(pte)) { |