mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
mm/hugetlb: disable PMD sharing for UFFD missing mode
For UFFDIO_POISON to install a poison marker in a hugetlb mapping, it is
sufficient to have the VMA registered for missing mode.
However, UFFD missing mode does currently not block PMD table sharing, so
installing the marker will be visible to everyone using the shared PMD
table, which is wrong as UFFDIO_POISON must stay local to the process.
To fix it, make uffd_disable_huge_pmd_share() cover VM_UFFD_MISSING as
well. With missing mode covered, hugetlb PMD sharing is disabled for all
userfaultfd registered VMAs, so the helper can simply return whether the
VMA has a userfaultfd context instead of testing individual UFFD mode
flags. Add a debug check on the marker installation path.
The existing registration path will then unshare PMD tables, and
subsequent faults will not share them while the mapping remains
registered.
The alternative would be to unshare PMD tables selectively when
installing poison markers, which results in way more complexity. Or
alternatively, simply failing the marker installation, which might break
some use cases.
This also disables PMD sharing for userfaultfd registrations that never
use UFFDIO_POISON.
Link: https://lore.kernel.org/20261022034543.51226-3-lizhe.67@bytedance.com
Fixes: 8a13897fb0 ("mm: userfaultfd: support UFFDIO_POISON for hugetlbfs")
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Li Zhe <lizhe.67@bytedance.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Suggested-by: Li Zhe <lizhe.67@bytedance.com>
Suggested-by: Mike Rapoport <rppt@kernel.org>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Peter Xu <peterx@redhat.com>
Cc: Jose A. Perez de Azpillaga <azpijr@gmail.com>
This commit is contained in:
parent
dfb190302d
commit
809cbe72ac
|
|
@ -168,22 +168,12 @@ static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *vma,
|
|||
}
|
||||
|
||||
/*
|
||||
* Never enable huge pmd sharing on some uffd registered vmas:
|
||||
*
|
||||
* - VM_UFFD_WP and VM_UFFD_RWP VMAs, because the write protect / access
|
||||
* tracking information is per pgtable entry.
|
||||
*
|
||||
* - VM_UFFD_MINOR VMAs, because otherwise we would never get minor faults for
|
||||
* VMAs which share huge pmds. (If you have two mappings to the same
|
||||
* underlying pages, and fault in the non-UFFD-registered one with a write,
|
||||
* with huge pmd sharing this would *also* setup the second UFFD-registered
|
||||
* mapping, and we'd not get minor faults.)
|
||||
* Never enable huge pmd sharing on userfaultfd registered VMAs, because
|
||||
* userfaultfd state can be tracked per VMA or per page table entry.
|
||||
*/
|
||||
static inline bool uffd_disable_huge_pmd_share(struct vm_area_struct *vma)
|
||||
{
|
||||
return vma_test_any_mask(vma,
|
||||
mk_vma_flags_from_masks(VMA_UFFD_WP, VMA_UFFD_RWP,
|
||||
VMA_UFFD_MINOR));
|
||||
return vma->vm_userfaultfd_ctx.ctx;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6388,6 +6388,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
|
|||
return -EEXIST;
|
||||
}
|
||||
|
||||
VM_WARN_ON_ONCE(size == PMD_SIZE && hugetlb_pmd_shared(dst_pte));
|
||||
_dst_pte = make_pte_marker(PTE_MARKER_POISONED);
|
||||
set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte, size);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user