From: Souptick Joarder <jrdr.linux@xxxxxxxxx> [ Upstream commit a81072a9c0ae734b7889929b0bc070fe3f353f0e ] Inside __scif_pin_pages(), when map_flags != SCIF_MAP_KERNEL it will call pin_user_pages_fast() to map nr_pages. However, pin_user_pages_fast() might fail with a return value -ERRNO. The return value is stored in pinned_pages->nr_pages. which in turn is passed to unpin_user_pages(), which expects pinned_pages->nr_pages >=0, else disaster. Fix this by assigning pinned_pages->nr_pages to 0 if pin_user_pages_fast() returns -ERRNO. Fixes: ba612aa8b487 ("misc: mic: SCIF memory registration and unregistration") Cc: John Hubbard <jhubbard@xxxxxxxxxx> Cc: Ira Weiny <ira.weiny@xxxxxxxxx> Cc: Dan Carpenter <dan.carpenter@xxxxxxxxxx> Reviewed-by: John Hubbard <jhubbard@xxxxxxxxxx> Signed-off-by: Souptick Joarder <jrdr.linux@xxxxxxxxx> Link: https://lore.kernel.org/r/1600570295-29546-1-git-send-email-jrdr.linux@xxxxxxxxx Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> --- drivers/misc/mic/scif/scif_rma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c index 95745dc4e0ecf..f282c2eaab29b 100644 --- a/drivers/misc/mic/scif/scif_rma.c +++ b/drivers/misc/mic/scif/scif_rma.c @@ -1404,6 +1404,8 @@ int __scif_pin_pages(void *addr, size_t len, int *out_prot, NULL); up_write(&mm->mmap_sem); if (nr_pages != pinned_pages->nr_pages) { + if (pinned_pages->nr_pages < 0) + pinned_pages->nr_pages = 0; if (try_upgrade) { if (ulimit) __scif_dec_pinned_vm_lock(mm, @@ -1424,7 +1426,6 @@ int __scif_pin_pages(void *addr, size_t len, int *out_prot, if (pinned_pages->nr_pages < nr_pages) { err = -EFAULT; - pinned_pages->nr_pages = nr_pages; goto dec_pinned; } @@ -1437,7 +1438,6 @@ int __scif_pin_pages(void *addr, size_t len, int *out_prot, __scif_dec_pinned_vm_lock(mm, nr_pages, 0); /* Something went wrong! Rollback */ error_unmap: - pinned_pages->nr_pages = nr_pages; scif_destroy_pinned_pages(pinned_pages); *pages = NULL; dev_dbg(scif_info.mdev.this_device, -- 2.25.1