• David Hildenbrand's avatar
    mm/gup: trigger FAULT_FLAG_UNSHARE when R/O-pinning a possibly shared anonymous page · a7f22660
    David Hildenbrand authored
    Whenever GUP currently ends up taking a R/O pin on an anonymous page that
    might be shared -- mapped R/O and !PageAnonExclusive() -- any write fault
    on the page table entry will end up replacing the mapped anonymous page
    due to COW, resulting in the GUP pin no longer being consistent with the
    page actually mapped into the page table.
    
    The possible ways to deal with this situation are:
     (1) Ignore and pin -- what we do right now.
     (2) Fail to pin -- which would be rather surprising to callers and
         could break user space.
     (3) Trigger unsharing and pin the now exclusive page -- reliable R/O
         pins.
    
    Let's implement 3) because it provides the clearest semantics and allows
    for checking in unpin_user_pages() and friends for possible BUGs: when
    trying to unpin a page that's no longer exclusive, clearly something went
    very wrong and might result in memory corruptions that might be hard to
    debug.  So we better have a nice way to spot such issues.
    
    This change implies that whenever user space *wrote* to a private mapping
    (IOW, we have an anonymous page mapped), that GUP pins will always remain
    consistent: reliable R/O GUP pins of anonymous pages.
    
    As a side note, this commit fixes the COW security issue for hugetlb with
    FOLL_PIN as documented in:
      https://lore.kernel.org/r/3ae33b08-d9ef-f846-56fb-645e3b9b4c66@redhat.com
    The vmsplice reproducer still applies, because vmsplice uses FOLL_GET
    instead of FOLL_PIN.
    
    Note that follow_huge_pmd() doesn't apply because we cannot end up in
    there with FOLL_PIN.
    
    This commit is heavily based on prototype patches by Andrea.
    
    Link: https://lkml.kernel.org/r/20220428083441.37290-17-david@redhat.comSigned-off-by: default avatarAndrea Arcangeli <aarcange@redhat.com>
    Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
    Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
    Co-developed-by: default avatarAndrea Arcangeli <aarcange@redhat.com>
    Cc: Christoph Hellwig <hch@lst.de>
    Cc: David Rientjes <rientjes@google.com>
    Cc: Don Dutile <ddutile@redhat.com>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: Jan Kara <jack@suse.cz>
    Cc: Jann Horn <jannh@google.com>
    Cc: Jason Gunthorpe <jgg@nvidia.com>
    Cc: John Hubbard <jhubbard@nvidia.com>
    Cc: Khalid Aziz <khalid.aziz@oracle.com>
    Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
    Cc: Liang Zhang <zhangliang5@huawei.com>
    Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
    Cc: Michal Hocko <mhocko@kernel.org>
    Cc: Mike Kravetz <mike.kravetz@oracle.com>
    Cc: Mike Rapoport <rppt@linux.ibm.com>
    Cc: Nadav Amit <namit@vmware.com>
    Cc: Oded Gabbay <oded.gabbay@gmail.com>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Pedro Demarchi Gomes <pedrodemargomes@gmail.com>
    Cc: Peter Xu <peterx@redhat.com>
    Cc: Rik van Riel <riel@surriel.com>
    Cc: Roman Gushchin <guro@fb.com>
    Cc: Shakeel Butt <shakeelb@google.com>
    Cc: Yang Shi <shy828301@gmail.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    a7f22660
gup.c 85.4 KB