lkml.org 
[lkml]   [2022]   [Aug]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.18 06/88] userfaultfd: provide properly masked address for huge-pages
    Date
    From: Nadav Amit <namit@vmware.com>

    commit d172b1a3bd065dd89234eac547fc62cf80681631 upstream.

    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.

    Link: https://lkml.kernel.org/r/20220711165906.2682-1-namit@vmware.com
    Fixes: 824ddc601adc ("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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/userfaultfd.c | 12 +++++++-----
    1 file changed, 7 insertions(+), 5 deletions(-)

    --- a/fs/userfaultfd.c
    +++ b/fs/userfaultfd.c
    @@ -191,17 +191,19 @@ static inline void msg_init(struct uffd_
    }

    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.
    @@ -485,8 +487,8 @@ vm_fault_t handle_userfault(struct vm_fa

    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;


    \
     
     \ /
      Last update: 2022-08-01 14:13    [W:7.457 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site