[PATCH 6/7] lib/iov_iter: guard iov_iter_alignment() against zero-count iovec/bvec iterators
From: Josh Law
Date: Fri Mar 13 2026 - 14:11:19 EST
When a direct I/O path calls iov_iter_alignment() on an iterator that
has already been fully consumed (count == 0) — which can occur when the
block layer re-checks alignment after draining all bytes — the
iov_iter_alignment_iovec() and iov_iter_alignment_bvec() helpers enter
their do-while loops unconditionally. With count == 0 and a non-zero
first segment length, the subtraction size -= len wraps the unsigned
size_t to a large value, causing the loop to walk off the end of the
iov/bvec array and read garbage memory.
The ubuf path already guards against this (checking if (size) before
accessing the buffer), but the iovec and bvec paths do not.
Found by reviewing the function for consistent handling of edge cases
across all iterator types, noting the ubuf path's explicit zero check
had no equivalent in the other branches.
Add count == 0 guards in iov_iter_alignment() before calling into the
iovec and bvec helpers, matching the ubuf path's behavior.
Signed-off-by: Josh Law <objecting@xxxxxxxxxxxxx>
---
lib/iov_iter.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 18561108aa3a..a5bb4fbd9d38 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -853,10 +853,10 @@ unsigned long iov_iter_alignment(const struct iov_iter *i)
/* iovec and kvec have identical layouts */
if (likely(iter_is_iovec(i) || iov_iter_is_kvec(i)))
- return iov_iter_alignment_iovec(i);
+ return i->count ? iov_iter_alignment_iovec(i) : 0;
if (iov_iter_is_bvec(i))
- return iov_iter_alignment_bvec(i);
+ return i->count ? iov_iter_alignment_bvec(i) : 0;
/* With both xarray and folioq types, we're dealing with whole folios. */
if (iov_iter_is_folioq(i))
--
2.34.1