History

mm/userfaultfd: add RWP fault delivery and expose UFFDIO_REGISTER_MODE_RWP

Wire the fault side of read-write protection tracking and turn the userspace interface on. An RWP-protected PTE is PAGE_NONE with the uffd bit set. The PROT_NONE triggers a fault on any access; the uffd bit distinguishes it from plain mprotect(PROT_NONE) or NUMA hinting. Fault dispatch, per level: PTE handle_pte_fault() -> do_uffd_rwp() PMD __handle_mm_fault() -> do_huge_pmd_uffd_rwp() hugetlb hugetlb_fault() -> hugetlb_handle_userfault() The RWP branches gate on userfaultfd_pte_rwp() / userfaultfd_huge_pmd_rwp() (VM_UFFD_RWP plus the uffd bit) and fall through to do_numa_page() / do_huge_pmd_numa_page() otherwise. Each delivers a UFFD_PAGEFAULT_FLAG_RWP message through handle_userfault(); the handler resolves it with UFFDIO_RWPROTECT clearing MODE_RWP. userfaultfd_must_wait() and userfaultfd_huge_must_wait() add matching protnone+uffd waiters so sync-mode fault handlers block correctly. Expose the UAPI: UFFDIO_REGISTER_MODE_RWP -> UFFD_API_REGISTER_MODES UFFD_FEATURE_RWP -> UFFD_API_FEATURES _UFFDIO_RWPROTECT -> UFFD_API_RANGE_IOCTLS UFFD_API_RANGE_IOCTLS_BASIC UFFD_FEATURE_RWP is masked out at UFFDIO_API time when PROT_NONE is not available or VM_UFFD_RWP aliases VM_NONE (32-bit), so userspace never sees an advertised-but-broken feature. Works on anonymous, shmem, and hugetlb memory.

Kiryl Shutsemau (Meta) committed 4 months ago

Commit 2d427bb1 parent 6eab8f27 files · +114 −8Browse files

Showing the changes to include/uapi (1 of 7 files). Show all

Unified · Split

include/uapi/linux/userfaultfd.h+8−4
@@ -25,7 +25,8 @@ · 24 unmodified lines
25#define UFFD_API ((__u64)0xAA)25#define UFFD_API ((__u64)0xAA)
26#define UFFD_API_REGISTER_MODES (UFFDIO_REGISTER_MODE_MISSING | \26#define UFFD_API_REGISTER_MODES (UFFDIO_REGISTER_MODE_MISSING | \
27 UFFDIO_REGISTER_MODE_WP | \27 UFFDIO_REGISTER_MODE_WP | \
28 UFFDIO_REGISTER_MODE_MINOR)28 UFFDIO_REGISTER_MODE_MINOR | \
29 UFFDIO_REGISTER_MODE_RWP)
29#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | \30#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | \
30 UFFD_FEATURE_EVENT_FORK | \31 UFFD_FEATURE_EVENT_FORK | \
31 UFFD_FEATURE_EVENT_REMAP | \32 UFFD_FEATURE_EVENT_REMAP | \
@@ -42,7 +43,8 @@ · 10 unmodified lines
42 UFFD_FEATURE_WP_UNPOPULATED | \43 UFFD_FEATURE_WP_UNPOPULATED | \
43 UFFD_FEATURE_POISON | \44 UFFD_FEATURE_POISON | \
44 UFFD_FEATURE_WP_ASYNC | \45 UFFD_FEATURE_WP_ASYNC | \
45 UFFD_FEATURE_MOVE)46 UFFD_FEATURE_MOVE | \
47 UFFD_FEATURE_RWP)
46#define UFFD_API_IOCTLS \48#define UFFD_API_IOCTLS \
47 ((__u64)1 << _UFFDIO_REGISTER | \49 ((__u64)1 << _UFFDIO_REGISTER | \
48 (__u64)1 << _UFFDIO_UNREGISTER | \50 (__u64)1 << _UFFDIO_UNREGISTER | \
@@ -54,13 +56,15 @@ · 5 unmodified lines
54 (__u64)1 << _UFFDIO_MOVE | \56 (__u64)1 << _UFFDIO_MOVE | \
55 (__u64)1 << _UFFDIO_WRITEPROTECT | \57 (__u64)1 << _UFFDIO_WRITEPROTECT | \
56 (__u64)1 << _UFFDIO_CONTINUE | \58 (__u64)1 << _UFFDIO_CONTINUE | \
57 (__u64)1 << _UFFDIO_POISON)59 (__u64)1 << _UFFDIO_POISON | \
60 (__u64)1 << _UFFDIO_RWPROTECT)
58#define UFFD_API_RANGE_IOCTLS_BASIC \61#define UFFD_API_RANGE_IOCTLS_BASIC \
59 ((__u64)1 << _UFFDIO_WAKE | \62 ((__u64)1 << _UFFDIO_WAKE | \
60 (__u64)1 << _UFFDIO_COPY | \63 (__u64)1 << _UFFDIO_COPY | \
61 (__u64)1 << _UFFDIO_WRITEPROTECT | \64 (__u64)1 << _UFFDIO_WRITEPROTECT | \
62 (__u64)1 << _UFFDIO_CONTINUE | \65 (__u64)1 << _UFFDIO_CONTINUE | \
63 (__u64)1 << _UFFDIO_POISON)66 (__u64)1 << _UFFDIO_POISON | \
67 (__u64)1 << _UFFDIO_RWPROTECT)
64 68
65/*69/*
66 * Valid ioctl command number range with this API is from 0x00 to70 * Valid ioctl command number range with this API is from 0x00 to