[PATCH v2 2/3] lib: Fix length calculations in extract_kvec_to_sg

Christian A. Ehrhardt posted 3 patches 1 week, 4 days ago
[PATCH v2 2/3] lib: Fix length calculations in extract_kvec_to_sg
Posted by Christian A. Ehrhardt 1 week, 4 days ago
When extracting from a kvec to a scatterlist, do not
cross page boundaries. The required length is already
calculated but not used as intended.

Adjust the copied length if the loop runs out auf
sglist entries.

While there return immediately from extract_iter_to_sg
if there are no sglist entries at all.

The changes to the kunit_iov_iter.c in the next commit
demonstrate that the patch is necessary.

Cc: David Howells <dhowells@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: stable@vger.kernel.org # v6.5+
Fixes: 018584697533 ("netfs: Add a function to extract an iterator into a scatterlist")
Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
---
 lib/scatterlist.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index d773720d11bf..befdc4b9c11d 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -1247,7 +1247,7 @@ static ssize_t extract_kvec_to_sg(struct iov_iter *iter,
 			else
 				page = virt_to_page((void *)kaddr);
 
-			sg_set_page(sg, page, len, off);
+			sg_set_page(sg, page, seg, off);
 			sgtable->nents++;
 			sg++;
 			sg_max--;
@@ -1256,6 +1256,7 @@ static ssize_t extract_kvec_to_sg(struct iov_iter *iter,
 			kaddr += PAGE_SIZE;
 			off = 0;
 		} while (len > 0 && sg_max > 0);
+		ret -= len;
 
 		if (maxsize <= 0 || sg_max == 0)
 			break;
@@ -1409,7 +1410,7 @@ ssize_t extract_iter_to_sg(struct iov_iter *iter, size_t maxsize,
 			   struct sg_table *sgtable, unsigned int sg_max,
 			   iov_iter_extraction_t extraction_flags)
 {
-	if (maxsize == 0)
+	if (maxsize == 0 || sg_max == 0)
 		return 0;
 
 	switch (iov_iter_type(iter)) {
-- 
2.43.0
Re: [PATCH v2 2/3] lib: Fix length calculations in extract_kvec_to_sg
Posted by Josh Law 1 week, 4 days ago

On 24 March 2026 20:34:52 GMT, "Christian A. Ehrhardt" <lk@c--e.de> wrote:
>When extracting from a kvec to a scatterlist, do not
>cross page boundaries. The required length is already
>calculated but not used as intended.
>
>Adjust the copied length if the loop runs out auf
>sglist entries.

Nit: "auf" > of?? (Probably a typo)

>While there return immediately from extract_iter_to_sg
>if there are no sglist entries at all.

Suggestion: You could change it  to "While there**,** return immediately from extract_iter_to_sg if there are no sglist entries at all." It is something a bit "silly" so it doesn't matter much

>The changes to the kunit_iov_iter.c in the next commit
>demonstrate that the patch is necessary.
>
>Cc: David Howells <dhowells@redhat.com>
>Cc: Andrew Morton <akpm@linux-foundation.org>
>Cc: stable@vger.kernel.org # v6.5+
>Fixes: 018584697533 ("netfs: Add a function to extract an iterator into a scatterlist")
>Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
>---
> lib/scatterlist.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
>diff --git a/lib/scatterlist.c b/lib/scatterlist.c
>index d773720d11bf..befdc4b9c11d 100644
>--- a/lib/scatterlist.c
>+++ b/lib/scatterlist.c
>@@ -1247,7 +1247,7 @@ static ssize_t extract_kvec_to_sg(struct iov_iter *iter,
> 			else
> 				page = virt_to_page((void *)kaddr);
> 
>-			sg_set_page(sg, page, len, off);
>+			sg_set_page(sg, page, seg, off);
> 			sgtable->nents++;
> 			sg++;
> 			sg_max--;
>@@ -1256,6 +1256,7 @@ static ssize_t extract_kvec_to_sg(struct iov_iter *iter,
> 			kaddr += PAGE_SIZE;
> 			off = 0;
> 		} while (len > 0 && sg_max > 0);
>+		ret -= len;
> 
> 		if (maxsize <= 0 || sg_max == 0)
> 			break;
>@@ -1409,7 +1410,7 @@ ssize_t extract_iter_to_sg(struct iov_iter *iter, size_t maxsize,
> 			   struct sg_table *sgtable, unsigned int sg_max,
> 			   iov_iter_extraction_t extraction_flags)
> {
>-	if (maxsize == 0)
>+	if (maxsize == 0 || sg_max == 0)
> 		return 0;
> 
> 	switch (iov_iter_type(iter)) {


This C is absolutely perfect! No nits here


V/R 


Josh Law