| From 2671342870798a200601a203e622e40d731cb970 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 21 Jul 2021 19:03:47 +0200 |
| Subject: iov_iter: Fix iov_iter_get_pages{,_alloc} page fault return value |
| |
| From: Andreas Gruenbacher <agruenba@redhat.com> |
| |
| [ Upstream commit 814a66741b9ffb5e1ba119e368b178edb0b7322d ] |
| |
| Both iov_iter_get_pages and iov_iter_get_pages_alloc return the number |
| of bytes of the iovec they could get the pages for. When they cannot |
| get any pages, they're supposed to return 0, but when the start of the |
| iovec isn't page aligned, the calculation goes wrong and they return a |
| negative value. Fix both functions. |
| |
| In addition, change iov_iter_get_pages_alloc to return NULL in that case |
| to prevent resource leaks. |
| |
| Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| lib/iov_iter.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| diff --git a/lib/iov_iter.c b/lib/iov_iter.c |
| index 41b06af195368..957e3e58df652 100644 |
| --- a/lib/iov_iter.c |
| +++ b/lib/iov_iter.c |
| @@ -1302,7 +1302,7 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, |
| res = get_user_pages_fast(addr, n, |
| iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, |
| pages); |
| - if (unlikely(res < 0)) |
| + if (unlikely(res <= 0)) |
| return res; |
| return (res == n ? len : res * PAGE_SIZE) - *start; |
| 0;}),({ |
| @@ -1384,8 +1384,9 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, |
| return -ENOMEM; |
| res = get_user_pages_fast(addr, n, |
| iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p); |
| - if (unlikely(res < 0)) { |
| + if (unlikely(res <= 0)) { |
| kvfree(p); |
| + *pages = NULL; |
| return res; |
| } |
| *pages = p; |
| -- |
| 2.33.0 |
| |