Skip to content

Commit d172b1a

Browse files
anadavakpm00
authored andcommitted
userfaultfd: provide properly masked address for huge-pages
Commit 824ddc6 ("userfaultfd: provide unmasked address on page-fault") was introduced to fix an old bug, in which the offset in the address of a page-fault was masked. Concerns were raised - although were never backed by actual code - that some userspace code might break because the bug has been around for quite a while. To address these concerns a new flag was introduced, and only when this flag is set by the user, userfaultfd provides the exact address of the page-fault. The commit however had a bug, and if the flag is unset, the offset was always masked based on a base-page granularity. Yet, for huge-pages, the behavior prior to the commit was that the address is masked to the huge-page granulrity. While there are no reports on real breakage, fix this issue. If the flag is unset, use the address with the masking that was done before. Link: https://lkml.kernel.org/r/20220711165906.2682-1-namit@vmware.com Fixes: 824ddc6 ("userfaultfd: provide unmasked address on page-fault") Signed-off-by: Nadav Amit <namit@vmware.com> Reported-by: James Houghton <jthoughton@google.com> Reviewed-by: Mike Rapoport <rppt@linux.ibm.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: James Houghton <jthoughton@google.com> Cc: David Hildenbrand <david@redhat.com> Cc: Jan Kara <jack@suse.cz> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent c80af0c commit d172b1a

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

fs/userfaultfd.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,19 @@ static inline void msg_init(struct uffd_msg *msg)
192192
}
193193

194194
static inline struct uffd_msg userfault_msg(unsigned long address,
195+
unsigned long real_address,
195196
unsigned int flags,
196197
unsigned long reason,
197198
unsigned int features)
198199
{
199200
struct uffd_msg msg;
201+
200202
msg_init(&msg);
201203
msg.event = UFFD_EVENT_PAGEFAULT;
202204

203-
if (!(features & UFFD_FEATURE_EXACT_ADDRESS))
204-
address &= PAGE_MASK;
205-
msg.arg.pagefault.address = address;
205+
msg.arg.pagefault.address = (features & UFFD_FEATURE_EXACT_ADDRESS) ?
206+
real_address : address;
207+
206208
/*
207209
* These flags indicate why the userfault occurred:
208210
* - UFFD_PAGEFAULT_FLAG_WP indicates a write protect fault.
@@ -488,8 +490,8 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
488490

489491
init_waitqueue_func_entry(&uwq.wq, userfaultfd_wake_function);
490492
uwq.wq.private = current;
491-
uwq.msg = userfault_msg(vmf->real_address, vmf->flags, reason,
492-
ctx->features);
493+
uwq.msg = userfault_msg(vmf->address, vmf->real_address, vmf->flags,
494+
reason, ctx->features);
493495
uwq.ctx = ctx;
494496
uwq.waken = false;
495497

0 commit comments

Comments
 (0)