On Mon, Jul 11, 2022 at 5:33 PM Nadav Amit <nadav.amit@xxxxxxxxx> wrote: > > From: Nadav Amit <namit@xxxxxxxxxx> > > Commit 824ddc601adc ("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. > > Fixes: 824ddc601adc ("userfaultfd: provide unmasked address on page-fault") > Reported-by: James Houghton <jthoughton@xxxxxxxxxx> > Cc: Peter Xu <peterx@xxxxxxxxxx> > Cc: David Hildenbrand <david@xxxxxxxxxx> > Cc: Mike Rapoport <rppt@xxxxxxxxxxxxx> > Cc: Jan Kara <jack@xxxxxxx> > Cc: Andrea Arcangeli <aarcange@xxxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> > Signed-off-by: Nadav Amit <namit@xxxxxxxxxx> Reviewed-by: James Houghton <jthoughton@xxxxxxxxxx> Thanks! > --- > fs/userfaultfd.c | 12 +++++++----- > 1 file changed, 7 insertions(+), 5 deletions(-) > > diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c > index e943370107d0..de86f5b2859f 100644 > --- a/fs/userfaultfd.c > +++ b/fs/userfaultfd.c > @@ -192,17 +192,19 @@ static inline void msg_init(struct uffd_msg *msg) > } > > static inline struct uffd_msg userfault_msg(unsigned long address, > + unsigned long real_address, > unsigned int flags, > unsigned long reason, > unsigned int features) > { > struct uffd_msg msg; > + > msg_init(&msg); > msg.event = UFFD_EVENT_PAGEFAULT; > > - if (!(features & UFFD_FEATURE_EXACT_ADDRESS)) > - address &= PAGE_MASK; > - msg.arg.pagefault.address = address; > + msg.arg.pagefault.address = (features & UFFD_FEATURE_EXACT_ADDRESS) ? > + real_address : address; > + > /* > * These flags indicate why the userfault occurred: > * - 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) > > init_waitqueue_func_entry(&uwq.wq, userfaultfd_wake_function); > uwq.wq.private = current; > - uwq.msg = userfault_msg(vmf->real_address, vmf->flags, reason, > - ctx->features); > + uwq.msg = userfault_msg(vmf->address, vmf->real_address, vmf->flags, > + reason, ctx->features); > uwq.ctx = ctx; > uwq.waken = false; > > -- > 2.25.1 >