[PATCH 1/7] lib/iov_iter: fix missing allocation failure check in iov_iter_extract_bvec_pages()
From: Josh Law
Date: Fri Mar 13 2026 - 14:11:08 EST
When iterating bvec pages for direct I/O submission on a block device
under heavy memory pressure, want_pages_array() can return 0 if the
internal kvmalloc_objs() call fails. Every other call site in the file
(iter_folioq_get_pages, iter_xarray_get_pages, iov_iter_extract_kvec_pages,
iov_iter_extract_user_pages, __iov_iter_get_pages_alloc) checks for this
and returns -ENOMEM, but iov_iter_extract_bvec_pages() does not.
When the allocation fails, *pages is left NULL and maxpages is set to 0,
but the while loop still enters because bi.bi_size is nonzero. The
subsequent (*pages)[k++] = bv.bv_page dereferences the NULL pointer,
causing a kernel oops.
This was found through code review comparing the error handling patterns
across all want_pages_array() call sites in the file and noticing the
one that was inconsistent.
Add the same !maxpages check present at every other call site.
Signed-off-by: Josh Law <objecting@xxxxxxxxxxxxx>
---
lib/iov_iter.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 0a63c7fba313..852f9ed40e5c 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1628,6 +1628,8 @@ static ssize_t iov_iter_extract_bvec_pages(struct iov_iter *i,
bi.bi_bvec_done = skip;
maxpages = want_pages_array(pages, maxsize, skip, maxpages);
+ if (!maxpages)
+ return -ENOMEM;
while (bi.bi_size && bi.bi_idx < i->nr_segs) {
struct bio_vec bv = bvec_iter_bvec(i->bvec, bi);
--
2.34.1