Skip to content

Commit 873aefb

Browse files
committed
vfio/type1: Unpin zero pages
There's currently a reference count leak on the zero page. We increment the reference via pin_user_pages_remote(), but the page is later handled as an invalid/reserved page, therefore it's not accounted against the user and not unpinned by our put_pfn(). Introducing special zero page handling in put_pfn() would resolve the leak, but without accounting of the zero page, a single user could still create enough mappings to generate a reference count overflow. The zero page is always resident, so for our purposes there's no reason to keep it pinned. Therefore, add a loop to walk pages returned from pin_user_pages_remote() and unpin any zero pages. Cc: [email protected] Reported-by: Luboslav Pivarc <[email protected]> Reviewed-by: David Hildenbrand <[email protected]> Link: https://lore.kernel.org/r/166182871735.3518559.8884121293045337358.stgit@omen Signed-off-by: Alex Williamson <[email protected]>
1 parent b90cb10 commit 873aefb

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

drivers/vfio/vfio_iommu_type1.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,18 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
558558
ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM,
559559
pages, NULL, NULL);
560560
if (ret > 0) {
561+
int i;
562+
563+
/*
564+
* The zero page is always resident, we don't need to pin it
565+
* and it falls into our invalid/reserved test so we don't
566+
* unpin in put_pfn(). Unpin all zero pages in the batch here.
567+
*/
568+
for (i = 0 ; i < ret; i++) {
569+
if (unlikely(is_zero_pfn(page_to_pfn(pages[i]))))
570+
unpin_user_page(pages[i]);
571+
}
572+
561573
*pfn = page_to_pfn(pages[0]);
562574
goto done;
563575
}

0 commit comments

Comments
 (0)