• Nadav Amit's avatar
    userfaultfd: provide unmasked address on page-fault · 824ddc60
    Nadav Amit authored
    Userfaultfd is supposed to provide the full address (i.e., unmasked) of
    the faulting access back to userspace.  However, that is not the case for
    quite some time.
    
    Even running "userfaultfd_demo" from the userfaultfd man page provides the
    wrong output (and contradicts the man page).  Notice that
    "UFFD_EVENT_PAGEFAULT event" shows the masked address (7fc5e30b3000) and
    not the first read address (0x7fc5e30b300f).
    
    	Address returned by mmap() = 0x7fc5e30b3000
    
    	fault_handler_thread():
    	    poll() returns: nready = 1; POLLIN = 1; POLLERR = 0
    	    UFFD_EVENT_PAGEFAULT event: flags = 0; address = 7fc5e30b3000
    		(uffdio_copy.copy returned 4096)
    	Read address 0x7fc5e30b300f in main(): A
    	Read address 0x7fc5e30b340f in main(): A
    	Read address 0x7fc5e30b380f in main(): A
    	Read address 0x7fc5e30b3c0f in main(): A
    
    The exact address is useful for various reasons and specifically for
    prefetching decisions.  If it is known that the memory is populated by
    certain objects whose size is not page-aligned, then based on the faulting
    address, the uffd-monitor can decide whether to prefetch and prefault the
    adjacent page.
    
    This bug has been for quite some time in the kernel: since commit
    1a29d85e ("mm: use vmf->address instead of of vmf->virtual_address")
    vmf->virtual_address"), which dates back to 2016.  A concern has been
    raised that existing userspace application might rely on the old/wrong
    behavior in which the address is masked.  Therefore, it was suggested to
    provide the masked address unless the user explicitly asks for the exact
    address.
    
    Add a new userfaultfd feature UFFD_FEATURE_EXACT_ADDRESS to direct
    userfaultfd to provide the exact address.  Add a new "real_address" field
    to vmf to hold the unmasked address.  Provide the address to userspace
    accordingly.
    
    Initialize real_address in various code-paths to be consistent with
    address, even when it is not used, to be on the safe side.
    
    [namit@vmware.com: initialize real_address on all code paths, per Jan]
      Link: https://lkml.kernel.org/r/20220226022655.350562-1-namit@vmware.com
    [akpm@linux-foundation.org: fix typo in comment, per Jan]
    
    Link: https://lkml.kernel.org/r/20220218041003.3508-1-namit@vmware.comSigned-off-by: default avatarNadav Amit <namit@vmware.com>
    Acked-by: default avatarPeter Xu <peterx@redhat.com>
    Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
    Acked-by: default avatarMike Rapoport <rppt@linux.ibm.com>
    Reviewed-by: default avatarJan Kara <jack@suse.cz>
    Cc: Andrea Arcangeli <aarcange@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    824ddc60
userfaultfd.c 54.6 KB