mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-12 16:34:05 -04:00
userfaultfd: add UFFDIO_REGISTER_MODE_RWP and UFFDIO_RWPROTECT plumbing
Add the userspace interface for read-write protection tracking:
- UFFDIO_REGISTER_MODE_RWP register a range for RWP tracking
- UFFD_FEATURE_RWP capability bit
- UFFDIO_RWPROTECT install / remove RWP on a range
Introduce CONFIG_USERFAULTFD_RWP, auto-selected on 64-bit kernels with
ARCH_HAS_PTE_PROTNONE and HAVE_ARCH_USERFAULTFD_WP. The symbol gates
VM_UFFD_RWP (previously aliased to VM_NONE) and the smaps/trace-flag hooks
added in the preparatory patches; without it the UAPI bits added here have
nothing to drive and would be unreachable.
Registration sets VM_UFFD_RWP on the VMA. Combining MODE_WP with MODE_RWP
is rejected because both modes claim the uffd PTE bit.
UFFDIO_RWPROTECT is the bidirectional counterpart of
UFFDIO_WRITEPROTECT:
- MODE_RWP change_protection() with MM_CP_UFFD_RWP
installs PAGE_NONE and sets the uffd bit on
present PTEs
- !MODE_RWP change_protection() with MM_CP_UFFD_RWP_RESOLVE
restores vma->vm_page_prot and clears the bit
userfaultfd_clear_vma() runs the same resolve pass on unregister so RWP
state cannot outlive the uffd.
Re-registering a range must not drop a mode that installs per-PTE markers
(WP or RWP); doing so returns -EBUSY. This also closes a pre-existing
window where re-registering without MODE_WP would strand uffd-wp markers:
before, those caused extra write-faults but were otherwise benign; with
RWP preservation in place, a subsequent mprotect() on a VM_UFFD_RWP VMA
would silently promote the stale markers to RWP.
The feature is not yet advertised. UFFDIO_REGISTER_MODE_RWP,
UFFD_FEATURE_RWP, and _UFFDIO_RWPROTECT are intentionally absent from
UFFD_API_REGISTER_MODES, UFFD_API_FEATURES, and UFFD_API_RANGE_IOCTLS, so
UFFDIO_API masks them out and the register-mode validator rejects the bit.
The follow-up patch adds fault dispatch and exposes the UAPI.
Link: https://lore.kernel.org/20260708111417.173443-10-kirill@shutemov.name
Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
Assisted-by: Claude:claude-opus-4-6
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: James Houghton <jthoughton@google.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Liam Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: SeongJae Park <sj@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
7974c23853
commit
6eab8f2cc6
@@ -79,6 +79,7 @@
|
||||
#define _UFFDIO_WRITEPROTECT (0x06)
|
||||
#define _UFFDIO_CONTINUE (0x07)
|
||||
#define _UFFDIO_POISON (0x08)
|
||||
#define _UFFDIO_RWPROTECT (0x09)
|
||||
#define _UFFDIO_API (0x3F)
|
||||
|
||||
/* userfaultfd ioctl ids */
|
||||
@@ -103,6 +104,8 @@
|
||||
struct uffdio_continue)
|
||||
#define UFFDIO_POISON _IOWR(UFFDIO, _UFFDIO_POISON, \
|
||||
struct uffdio_poison)
|
||||
#define UFFDIO_RWPROTECT _IOWR(UFFDIO, _UFFDIO_RWPROTECT, \
|
||||
struct uffdio_rwprotect)
|
||||
|
||||
/* read() structure */
|
||||
struct uffd_msg {
|
||||
@@ -158,6 +161,7 @@ struct uffd_msg {
|
||||
#define UFFD_PAGEFAULT_FLAG_WRITE (1<<0) /* If this was a write fault */
|
||||
#define UFFD_PAGEFAULT_FLAG_WP (1<<1) /* If reason is VM_UFFD_WP */
|
||||
#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2) /* If reason is VM_UFFD_MINOR */
|
||||
#define UFFD_PAGEFAULT_FLAG_RWP (1<<3) /* If reason is VM_UFFD_RWP */
|
||||
|
||||
struct uffdio_api {
|
||||
/* userland asks for an API number and the features to enable */
|
||||
@@ -230,6 +234,11 @@ struct uffdio_api {
|
||||
*
|
||||
* UFFD_FEATURE_MOVE indicates that the kernel supports moving an
|
||||
* existing page contents from userspace.
|
||||
*
|
||||
* UFFD_FEATURE_RWP indicates that the kernel supports
|
||||
* UFFDIO_REGISTER_MODE_RWP for read-write protection tracking.
|
||||
* Pages are made inaccessible via UFFDIO_RWPROTECT and faults
|
||||
* are delivered when the pages are re-accessed.
|
||||
*/
|
||||
#define UFFD_FEATURE_PAGEFAULT_FLAG_WP (1<<0)
|
||||
#define UFFD_FEATURE_EVENT_FORK (1<<1)
|
||||
@@ -248,6 +257,7 @@ struct uffdio_api {
|
||||
#define UFFD_FEATURE_POISON (1<<14)
|
||||
#define UFFD_FEATURE_WP_ASYNC (1<<15)
|
||||
#define UFFD_FEATURE_MOVE (1<<16)
|
||||
#define UFFD_FEATURE_RWP (1<<17)
|
||||
__u64 features;
|
||||
|
||||
__u64 ioctls;
|
||||
@@ -263,6 +273,7 @@ struct uffdio_register {
|
||||
#define UFFDIO_REGISTER_MODE_MISSING ((__u64)1<<0)
|
||||
#define UFFDIO_REGISTER_MODE_WP ((__u64)1<<1)
|
||||
#define UFFDIO_REGISTER_MODE_MINOR ((__u64)1<<2)
|
||||
#define UFFDIO_REGISTER_MODE_RWP ((__u64)1<<3)
|
||||
__u64 mode;
|
||||
|
||||
/*
|
||||
@@ -356,6 +367,14 @@ struct uffdio_poison {
|
||||
__s64 updated;
|
||||
};
|
||||
|
||||
struct uffdio_rwprotect {
|
||||
struct uffdio_range range;
|
||||
/* !RWP means undo RWP-protection */
|
||||
#define UFFDIO_RWPROTECT_MODE_RWP ((__u64)1<<0)
|
||||
#define UFFDIO_RWPROTECT_MODE_DONTWAKE ((__u64)1<<1)
|
||||
__u64 mode;
|
||||
};
|
||||
|
||||
struct uffdio_move {
|
||||
__u64 dst;
|
||||
__u64 src;
|
||||
|
||||
Reference in New Issue
Block a user