vfio/type1: Unpin zero pages
commit 873aefb376
upstream.
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: stable@vger.kernel.org
Reported-by: Luboslav Pivarc <lpivarc@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Link: https://lore.kernel.org/r/166182871735.3518559.8884121293045337358.stgit@omen
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
7da1afa444
Коммит
5321908ef7
|
@ -561,6 +561,18 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
|
|||
ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM,
|
||||
pages, NULL, NULL);
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The zero page is always resident, we don't need to pin it
|
||||
* and it falls into our invalid/reserved test so we don't
|
||||
* unpin in put_pfn(). Unpin all zero pages in the batch here.
|
||||
*/
|
||||
for (i = 0 ; i < ret; i++) {
|
||||
if (unlikely(is_zero_pfn(page_to_pfn(pages[i]))))
|
||||
unpin_user_page(pages[i]);
|
||||
}
|
||||
|
||||
*pfn = page_to_pfn(pages[0]);
|
||||
goto done;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче