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.
Showing the changes to include/uapi (1 of 7 files). Show all
Unified · Split
| @@ -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 to | 70 | * Valid ioctl command number range with this API is from 0x00 to |