* [PATCH v3 0/5] Fix bugs in extract_iter_to_sg()
@ 2026-03-26 21:49 Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 1/5] lib/scatterlist: Fix length calculations in extract_kvec_to_sg Christian A. Ehrhardt
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Christian A. Ehrhardt @ 2026-03-26 21:49 UTC (permalink / raw)
To: David Howells, Andrew Morton, linux-kernel
Cc: Christian A. Ehrhardt, Kees Cook, Petr Mladek, David Gow
Fix bugs in the kvec and user variants of extract_iter_to_sg.
This series is growing due to useful remarks made by sashiko.dev.
The main bugs are:
- The length for an sglist entry when extracting from
a kvec can exceed the number of bytes in the page. This
is obviously not intended.
- When extracting a user buffer the sglist is temporarily
used as a scratch buffer for extracted page pointers.
If the sglist already contains some elements this scratch
buffer could overlap with existing entries in the sglist.
The series adds test cases to the kunit_iov_iter test that
demonstrate all of these bugs. Additionally, there is a
memory leak fix for the test itself.
The bugs were orignally introduced into kernel v6.3 where the
function lived in fs/netfs/iterator.c. It was later moved
to lib/scatterlist.c in v6.5. Thus the actual fix is only
marked for backports to v6.5+.
---
Changes in v2:
Addresss valid issues raised by AI review
https://sashiko.dev/#/patchset/20260323212350.807118-1-lk@c--e.de:
- Add kunit assertions for OOM conditions in the test
- Reorder commits.
- Fix sg_max == 0 case.
- Fix return value if we run out of sg entries.
- Adjust tests to catch these cases, too.
Changes in v3:
- Add fix and test for extract_user_to_sg()
- Fix memory leak in the unit test.
- Re-order commits: Code fixes first, then tests.
---
Christian A. Ehrhardt (5):
lib/scatterlist: Fix length calculations in extract_kvec_to_sg
lib/scatterlist: Fix temp buffer in extract_user_to_sg()
lib: kunit_iov_iter: Fix memory leaks
lib: kunit_iov_iter: Improve error detection
lib: kunit_iov_iter: Add tests for extract_iter_to_sg
lib/scatterlist.c | 8 +-
lib/tests/kunit_iov_iter.c | 224 +++++++++++++++++++++++++++++++++++--
2 files changed, 221 insertions(+), 11 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 1/5] lib/scatterlist: Fix length calculations in extract_kvec_to_sg
2026-03-26 21:49 [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Christian A. Ehrhardt
@ 2026-03-26 21:49 ` Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 2/5] lib/scatterlist: Fix temp buffer in extract_user_to_sg() Christian A. Ehrhardt
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Christian A. Ehrhardt @ 2026-03-26 21:49 UTC (permalink / raw)
To: David Howells, Andrew Morton, linux-kernel
Cc: Christian A. Ehrhardt, Kees Cook, Petr Mladek, David Gow
When extracting from a kvec to a scatterlist, do not
cross page boundaries. The required length was already
calculated but not used as intended.
Adjust the copied length if the loop runs out of
sglist entries without extracting everything.
While there, return immediately from extract_iter_to_sg
if there are no sglist entries at all.
A subsequent commit will add kunit test cases that
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
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 2/5] lib/scatterlist: Fix temp buffer in extract_user_to_sg()
2026-03-26 21:49 [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 1/5] lib/scatterlist: Fix length calculations in extract_kvec_to_sg Christian A. Ehrhardt
@ 2026-03-26 21:49 ` Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 3/5] lib: kunit_iov_iter: Fix memory leaks Christian A. Ehrhardt
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Christian A. Ehrhardt @ 2026-03-26 21:49 UTC (permalink / raw)
To: David Howells, Andrew Morton, linux-kernel
Cc: Christian A. Ehrhardt, Kees Cook, Petr Mladek, David Gow
Instead of allocating a temporary buffer for extracted
user pages extract_user_to_sg() uses the end of the
to be filled scatterlist as a temporary buffer.
Fix the calculation of the start address if the scatterlist
already contains elements. The unused space starts at
sgtable->sgl + sgtable->nents not directly at sgtable->nents
and the temporary buffer is placed at the end of this unused
space.
A subsequent commit will add kunit test cases that
demonstrate that the patch is necessary.
Pointed out by sashiko.dev on a previous iteration of this series.
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 | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index befdc4b9c11d..b7fe91ef35b8 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -1123,8 +1123,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter,
size_t len, off;
/* We decant the page list into the tail of the scatterlist */
- pages = (void *)sgtable->sgl +
- array_size(sg_max, sizeof(struct scatterlist));
+ pages = (void *)sg + array_size(sg_max, sizeof(struct scatterlist));
pages -= sg_max;
do {
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 3/5] lib: kunit_iov_iter: Fix memory leaks
2026-03-26 21:49 [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 1/5] lib/scatterlist: Fix length calculations in extract_kvec_to_sg Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 2/5] lib/scatterlist: Fix temp buffer in extract_user_to_sg() Christian A. Ehrhardt
@ 2026-03-26 21:49 ` Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 4/5] lib: kunit_iov_iter: Improve error detection Christian A. Ehrhardt
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Christian A. Ehrhardt @ 2026-03-26 21:49 UTC (permalink / raw)
To: David Howells, Andrew Morton, linux-kernel
Cc: Christian A. Ehrhardt, Kees Cook, Petr Mladek, David Gow
Use vfree() instead of vunmap() to free the buffer allocated
by iov_kunit_create_buffer() because vunmap() does not honour
VM_MAP_PUT_PAGES. In order for this to work the page array
itself must not be managed by kunit.
Remove the folio_put() when destroying a folioq. This is handled
by vfree(), now.
Pointed out by sashiko.dev on a previous iteration of this series.
Tested by running the kunit test 10000 times in a loop.
Cc: David Howells <dhowells@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Fixes: 2d71340ff1d4 ("iov_iter: Kunit tests for copying to/from an iterator")
Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
---
lib/tests/kunit_iov_iter.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/lib/tests/kunit_iov_iter.c b/lib/tests/kunit_iov_iter.c
index bb847e5010eb..d16449bdb833 100644
--- a/lib/tests/kunit_iov_iter.c
+++ b/lib/tests/kunit_iov_iter.c
@@ -42,7 +42,7 @@ static inline u8 pattern(unsigned long x)
static void iov_kunit_unmap(void *data)
{
- vunmap(data);
+ vfree(data);
}
static void *__init iov_kunit_create_buffer(struct kunit *test,
@@ -53,17 +53,22 @@ static void *__init iov_kunit_create_buffer(struct kunit *test,
unsigned long got;
void *buffer;
- pages = kunit_kcalloc(test, npages, sizeof(struct page *), GFP_KERNEL);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pages);
+ pages = kzalloc_objs(struct page *, npages, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pages);
*ppages = pages;
got = alloc_pages_bulk(GFP_KERNEL, npages, pages);
if (got != npages) {
release_pages(pages, got);
+ kvfree(pages);
KUNIT_ASSERT_EQ(test, got, npages);
}
buffer = vmap(pages, npages, VM_MAP | VM_MAP_PUT_PAGES, PAGE_KERNEL);
+ if (buffer == NULL) {
+ release_pages(pages, got);
+ kvfree(pages);
+ }
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer);
kunit_add_action_or_reset(test, iov_kunit_unmap, buffer);
@@ -369,9 +374,6 @@ static void iov_kunit_destroy_folioq(void *data)
for (folioq = data; folioq; folioq = next) {
next = folioq->next;
- for (int i = 0; i < folioq_nr_slots(folioq); i++)
- if (folioq_folio(folioq, i))
- folio_put(folioq_folio(folioq, i));
kfree(folioq);
}
}
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 4/5] lib: kunit_iov_iter: Improve error detection
2026-03-26 21:49 [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Christian A. Ehrhardt
` (2 preceding siblings ...)
2026-03-26 21:49 ` [PATCH v3 3/5] lib: kunit_iov_iter: Fix memory leaks Christian A. Ehrhardt
@ 2026-03-26 21:49 ` Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg Christian A. Ehrhardt
2026-03-26 22:39 ` [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Andrew Morton
5 siblings, 0 replies; 10+ messages in thread
From: Christian A. Ehrhardt @ 2026-03-26 21:49 UTC (permalink / raw)
To: David Howells, Andrew Morton, linux-kernel
Cc: Christian A. Ehrhardt, Kees Cook, Petr Mladek, David Gow
In the kunit_iov_iter test prevent the kernel buffer from
being a single physically contiguous region.
Additionally, make sure that the test pattern written to
a page in the buffer depends on the offset of the page within
the buffer.
Cc: David Howells <dhowells@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
---
lib/tests/kunit_iov_iter.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/tests/kunit_iov_iter.c b/lib/tests/kunit_iov_iter.c
index d16449bdb833..64a4e2f3eafa 100644
--- a/lib/tests/kunit_iov_iter.c
+++ b/lib/tests/kunit_iov_iter.c
@@ -13,6 +13,7 @@
#include <linux/uio.h>
#include <linux/bvec.h>
#include <linux/folio_queue.h>
+#include <linux/minmax.h>
#include <kunit/test.h>
MODULE_DESCRIPTION("iov_iter testing");
@@ -37,7 +38,7 @@ static const struct kvec_test_range kvec_test_ranges[] = {
static inline u8 pattern(unsigned long x)
{
- return x & 0xff;
+ return (u8)x + (u8)(x >> 8) + (u8)(x >> 16);
}
static void iov_kunit_unmap(void *data)
@@ -52,6 +53,7 @@ static void *__init iov_kunit_create_buffer(struct kunit *test,
struct page **pages;
unsigned long got;
void *buffer;
+ unsigned int i;
pages = kzalloc_objs(struct page *, npages, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pages);
@@ -63,6 +65,9 @@ static void *__init iov_kunit_create_buffer(struct kunit *test,
kvfree(pages);
KUNIT_ASSERT_EQ(test, got, npages);
}
+ /* Make sure that we don't get a physically contiguous buffer. */
+ for (i = 0; i < npages / 4; ++i)
+ swap(pages[i], pages[i + npages / 2]);
buffer = vmap(pages, npages, VM_MAP | VM_MAP_PUT_PAGES, PAGE_KERNEL);
if (buffer == NULL) {
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg
2026-03-26 21:49 [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Christian A. Ehrhardt
` (3 preceding siblings ...)
2026-03-26 21:49 ` [PATCH v3 4/5] lib: kunit_iov_iter: Improve error detection Christian A. Ehrhardt
@ 2026-03-26 21:49 ` Christian A. Ehrhardt
2026-04-21 5:45 ` David Gow
2026-03-26 22:39 ` [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Andrew Morton
5 siblings, 1 reply; 10+ messages in thread
From: Christian A. Ehrhardt @ 2026-03-26 21:49 UTC (permalink / raw)
To: David Howells, Andrew Morton, linux-kernel
Cc: Christian A. Ehrhardt, Kees Cook, Petr Mladek, David Gow
Add test cases that test extract_iter_to_sg.
For each iterator type an iterator is loaded with a suitable
buffer. The iterator is then extracted to a scatterlist with
multiple calls to extract_iter_to_sg. The final scatterlist
is copied into a scratch buffer.
The test passes if the scratch buffer contains the same data
as the original buffer.
The new tests demonstrate bugs in extract_iter_to_sg
for kvec and user iterators that are fixed by the previous
commits.
Cc: David Howells <dhowells@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
---
lib/tests/kunit_iov_iter.c | 203 +++++++++++++++++++++++++++++++++++++
1 file changed, 203 insertions(+)
diff --git a/lib/tests/kunit_iov_iter.c b/lib/tests/kunit_iov_iter.c
index 64a4e2f3eafa..37bd6eb25896 100644
--- a/lib/tests/kunit_iov_iter.c
+++ b/lib/tests/kunit_iov_iter.c
@@ -13,7 +13,9 @@
#include <linux/uio.h>
#include <linux/bvec.h>
#include <linux/folio_queue.h>
+#include <linux/scatterlist.h>
#include <linux/minmax.h>
+#include <linux/mman.h>
#include <kunit/test.h>
MODULE_DESCRIPTION("iov_iter testing");
@@ -1016,6 +1018,202 @@ static void __init iov_kunit_extract_pages_xarray(struct kunit *test)
KUNIT_SUCCEED(test);
}
+struct iov_kunit_iter_to_sg_data {
+ struct sg_table *sgt;
+ u8 *buffer, *scratch;
+ u8 __user *ubuf;
+ struct page **pages;
+ size_t npages;
+};
+
+static void __init
+iov_kunit_iter_unpin_sgt(void *data)
+{
+ struct sg_table *sgt = data;
+
+ for (unsigned int i = 0; i < sgt->nents; ++i)
+ unpin_user_page(sg_page(&sgt->sgl[i]));
+}
+
+static void __init
+iov_kunit_iter_to_sg_init(struct kunit *test, size_t bufsize, bool user,
+ struct iov_kunit_iter_to_sg_data *data)
+{
+ struct page **spages;
+ struct scatterlist *sg;
+ unsigned long uaddr;
+ size_t i;
+
+ data->npages = bufsize / PAGE_SIZE;
+ sg = kunit_kmalloc_array(test, data->npages, sizeof(*sg), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sg);
+ sg_init_table(sg, data->npages);
+ data->sgt = kunit_kzalloc(test, sizeof(*data->sgt), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, data->sgt);
+ data->sgt->orig_nents = 0;
+ data->sgt->sgl = sg;
+
+ data->buffer = NULL;
+ data->ubuf = NULL;
+ if (user) {
+ uaddr = kunit_vm_mmap(test, NULL, 0, bufsize,
+ PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, 0);
+ KUNIT_ASSERT_NE(test, uaddr, 0);
+ data->ubuf = (u8 __user *)uaddr;
+ for (i = 0; i < bufsize; ++i)
+ put_user(pattern(i), data->ubuf + i);
+ } else {
+ data->buffer = iov_kunit_create_buffer(test, &data->pages,
+ data->npages);
+ for (i = 0; i < bufsize; ++i)
+ data->buffer[i] = pattern(i);
+ }
+ data->scratch = iov_kunit_create_buffer(test, &spages, data->npages);
+ memset(data->scratch, 0, bufsize);
+}
+
+static void __init
+iov_kunit_iter_to_sg_check(struct kunit *test, struct iov_iter *iter,
+ size_t bufsize,
+ struct iov_kunit_iter_to_sg_data *data)
+{
+ static const size_t tail = 16 * PAGE_SIZE;
+ size_t i;
+
+ KUNIT_ASSERT_LT(test, tail, bufsize);
+
+ if (iov_iter_extract_will_pin(iter))
+ kunit_add_action_or_reset(test, iov_kunit_iter_unpin_sgt,
+ data->sgt);
+
+ i = extract_iter_to_sg(iter, bufsize, data->sgt, 0, 0);
+ KUNIT_ASSERT_EQ(test, i, 0);
+ KUNIT_ASSERT_EQ(test, data->sgt->nents, 0);
+
+ i = extract_iter_to_sg(iter, bufsize - tail, data->sgt, 1, 0);
+ KUNIT_ASSERT_LE(test, i, bufsize - tail);
+ KUNIT_ASSERT_EQ(test, data->sgt->nents, 1);
+
+ i += extract_iter_to_sg(iter, bufsize - tail - i, data->sgt,
+ data->npages - data->sgt->nents, 0);
+ KUNIT_ASSERT_EQ(test, i, bufsize - tail);
+ KUNIT_ASSERT_LE(test, data->sgt->nents, data->npages);
+
+ i += extract_iter_to_sg(iter, tail, data->sgt,
+ data->npages - data->sgt->nents, 0);
+ KUNIT_ASSERT_EQ(test, i, bufsize);
+ KUNIT_ASSERT_LE(test, data->sgt->nents, data->npages);
+
+ sg_mark_end(&data->sgt->sgl[data->sgt->nents - 1]);
+
+ i = sg_copy_to_buffer(data->sgt->sgl, data->sgt->nents,
+ data->scratch, bufsize);
+ KUNIT_ASSERT_EQ(test, i, bufsize);
+
+ for (i = 0; i < bufsize; ++i) {
+ KUNIT_EXPECT_EQ_MSG(test, data->scratch[i], pattern(i),
+ "at i=%zx", i);
+ if (data->scratch[i] != pattern(i))
+ break;
+ }
+
+ KUNIT_EXPECT_EQ(test, i, bufsize);
+}
+
+static void __init iov_kunit_iter_to_sg_kvec(struct kunit *test)
+{
+ struct iov_kunit_iter_to_sg_data data;
+ struct iov_iter iter;
+ struct kvec kvec;
+ size_t bufsize;
+
+ bufsize = 0x100000;
+ iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
+
+ kvec.iov_base = data.buffer;
+ kvec.iov_len = bufsize;
+ iov_iter_kvec(&iter, READ, &kvec, 1, bufsize);
+
+ iov_kunit_iter_to_sg_check(test, &iter, bufsize, &data);
+}
+
+static void __init iov_kunit_iter_to_sg_bvec(struct kunit *test)
+{
+ struct iov_kunit_iter_to_sg_data data;
+ struct page *p, *can_merge = NULL;
+ size_t i, k, bufsize;
+ struct bio_vec *bvec;
+ struct iov_iter iter;
+
+ bufsize = 0x100000;
+ iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
+
+ bvec = kunit_kmalloc_array(test, data.npages, sizeof(*bvec),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bvec);
+ k = 0;
+ for (i = 0; i < data.npages; ++i) {
+ p = data.pages[i];
+ if (p == can_merge)
+ bvec[k-1].bv_len += PAGE_SIZE;
+ else
+ bvec_set_page(&bvec[k++], p, PAGE_SIZE, 0);
+ can_merge = p + 1;
+ }
+ iov_iter_bvec(&iter, READ, bvec, k, bufsize);
+
+ iov_kunit_iter_to_sg_check(test, &iter, bufsize, &data);
+}
+
+static void __init iov_kunit_iter_to_sg_folioq(struct kunit *test)
+{
+ struct iov_kunit_iter_to_sg_data data;
+ struct folio_queue *folioq;
+ struct iov_iter iter;
+ size_t bufsize;
+
+ bufsize = 0x100000;
+ iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
+
+ folioq = iov_kunit_create_folioq(test);
+ iov_kunit_load_folioq(test, &iter, READ, folioq, data.pages,
+ data.npages);
+
+ iov_kunit_iter_to_sg_check(test, &iter, bufsize, &data);
+}
+
+static void __init iov_kunit_iter_to_sg_xarray(struct kunit *test)
+{
+ struct iov_kunit_iter_to_sg_data data;
+ struct xarray *xarray;
+ struct iov_iter iter;
+ size_t bufsize;
+
+ bufsize = 0x100000;
+ iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
+
+ xarray = iov_kunit_create_xarray(test);
+ iov_kunit_load_xarray(test, &iter, READ, xarray, data.pages,
+ data.npages);
+
+ iov_kunit_iter_to_sg_check(test, &iter, bufsize, &data);
+}
+
+static void __init iov_kunit_iter_to_sg_ubuf(struct kunit *test)
+{
+ struct iov_kunit_iter_to_sg_data data;
+ struct iov_iter iter;
+ size_t bufsize;
+
+ bufsize = 0x100000;
+ iov_kunit_iter_to_sg_init(test, bufsize, true, &data);
+
+ iov_iter_ubuf(&iter, READ, data.ubuf, bufsize);
+
+ iov_kunit_iter_to_sg_check(test, &iter, bufsize, &data);
+}
+
static struct kunit_case __refdata iov_kunit_cases[] = {
KUNIT_CASE(iov_kunit_copy_to_kvec),
KUNIT_CASE(iov_kunit_copy_from_kvec),
@@ -1029,6 +1227,11 @@ static struct kunit_case __refdata iov_kunit_cases[] = {
KUNIT_CASE(iov_kunit_extract_pages_bvec),
KUNIT_CASE(iov_kunit_extract_pages_folioq),
KUNIT_CASE(iov_kunit_extract_pages_xarray),
+ KUNIT_CASE(iov_kunit_iter_to_sg_kvec),
+ KUNIT_CASE(iov_kunit_iter_to_sg_bvec),
+ KUNIT_CASE(iov_kunit_iter_to_sg_folioq),
+ KUNIT_CASE(iov_kunit_iter_to_sg_xarray),
+ KUNIT_CASE(iov_kunit_iter_to_sg_ubuf),
{}
};
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 0/5] Fix bugs in extract_iter_to_sg()
2026-03-26 21:49 [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Christian A. Ehrhardt
` (4 preceding siblings ...)
2026-03-26 21:49 ` [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg Christian A. Ehrhardt
@ 2026-03-26 22:39 ` Andrew Morton
5 siblings, 0 replies; 10+ messages in thread
From: Andrew Morton @ 2026-03-26 22:39 UTC (permalink / raw)
To: Christian A. Ehrhardt
Cc: David Howells, linux-kernel, Kees Cook, Petr Mladek, David Gow
On Thu, 26 Mar 2026 22:49:00 +0100 "Christian A. Ehrhardt" <lk@c--e.de> wrote:
> Fix bugs in the kvec and user variants of extract_iter_to_sg.
> This series is growing due to useful remarks made by sashiko.dev.
>
> The main bugs are:
> - The length for an sglist entry when extracting from
> a kvec can exceed the number of bytes in the page. This
> is obviously not intended.
> - When extracting a user buffer the sglist is temporarily
> used as a scratch buffer for extracted page pointers.
> If the sglist already contains some elements this scratch
> buffer could overlap with existing entries in the sglist.
>
> The series adds test cases to the kunit_iov_iter test that
> demonstrate all of these bugs. Additionally, there is a
> memory leak fix for the test itself.
>
> The bugs were orignally introduced into kernel v6.3 where the
> function lived in fs/netfs/iterator.c. It was later moved
> to lib/scatterlist.c in v6.5. Thus the actual fix is only
> marked for backports to v6.5+.
Great. I'll add this to mm.git's mm-unstable branch, targetting an
upstream merge into 7.1-rc1.
As far as I understand, this means that the cc:stable patches will be
presented to the -stable maintainers some time after that upstreaming.
I don't believe that more urgency is needed.
DavidH, please review the sg changes?
DavidG, please check the kunit changes?
Thanks all.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg
2026-03-26 21:49 ` [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg Christian A. Ehrhardt
@ 2026-04-21 5:45 ` David Gow
2026-04-21 6:30 ` Christian A. Ehrhardt
0 siblings, 1 reply; 10+ messages in thread
From: David Gow @ 2026-04-21 5:45 UTC (permalink / raw)
To: Christian A. Ehrhardt, David Howells, Andrew Morton, linux-kernel
Cc: Kees Cook, Petr Mladek
Le 27/03/2026 à 05:49, Christian A. Ehrhardt a écrit :
> Add test cases that test extract_iter_to_sg.
>
> For each iterator type an iterator is loaded with a suitable
> buffer. The iterator is then extracted to a scatterlist with
> multiple calls to extract_iter_to_sg. The final scatterlist
> is copied into a scratch buffer.
>
> The test passes if the scratch buffer contains the same data
> as the original buffer.
>
> The new tests demonstrate bugs in extract_iter_to_sg
> for kvec and user iterators that are fixed by the previous
> commits.
>
> Cc: David Howells <dhowells@redhat.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
> ---
Hmm... this is failing on powerpc, where PAGE_SIZE is 64k:
[13:20:40] # iov_kunit_iter_to_sg_kvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:1084
[13:20:40] Expected tail < bufsize, but
[13:20:40] tail == 1048576 (0x100000)
[13:20:40] bufsize == 1048576 (0x100000)
[13:20:40] [FAILED] iov_kunit_iter_to_sg_kvec
[13:20:40] # iov_kunit_iter_to_sg_bvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:1084
[13:20:40] Expected tail < bufsize, but
[13:20:40] tail == 1048576 (0x100000)
[13:20:40] bufsize == 1048576 (0x100000)
[13:20:40] [FAILED] iov_kunit_iter_to_sg_bvec
[13:20:40] # iov_kunit_iter_to_sg_folioq: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:1084
[13:20:40] Expected tail < bufsize, but
[13:20:40] tail == 1048576 (0x100000)
[13:20:40] bufsize == 1048576 (0x100000)
[13:20:40] [FAILED] iov_kunit_iter_to_sg_folioq
[13:20:40] # iov_kunit_iter_to_sg_xarray: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:1084
[13:20:40] Expected tail < bufsize, but
[13:20:40] tail == 1048576 (0x100000)
[13:20:40] bufsize == 1048576 (0x100000)
[13:20:40] [FAILED] iov_kunit_iter_to_sg_xarray
[13:20:40] # iov_kunit_iter_to_sg_ubuf: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:1084
[13:20:40] Expected tail < bufsize, but
[13:20:40] tail == 1048576 (0x100000)
[13:20:40] bufsize == 1048576 (0x100000)
[13:20:40] [FAILED] iov_kunit_iter_to_sg_ubuf
[13:20:40] # module: kunit_iov_iter
[13:20:40] # iov_iter: pass:12 fail:5 skip:0 total:17
[13:20:40] # Totals: pass:12 fail:5 skip:0 total:17
Any chance we could bump up the buffer size (at least) on systems with
larger PAGE_SIZE?
Cheers,
-- David
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg
2026-04-21 5:45 ` David Gow
@ 2026-04-21 6:30 ` Christian A. Ehrhardt
2026-04-21 6:49 ` David Gow
0 siblings, 1 reply; 10+ messages in thread
From: Christian A. Ehrhardt @ 2026-04-21 6:30 UTC (permalink / raw)
To: David Gow
Cc: David Howells, Andrew Morton, linux-kernel, Kees Cook, Petr Mladek
Hi David,
On Tue, Apr 21, 2026 at 01:45:33PM +0800, David Gow wrote:
> Le 27/03/2026 à 05:49, Christian A. Ehrhardt a écrit :
> > Add test cases that test extract_iter_to_sg.
> >
> > For each iterator type an iterator is loaded with a suitable
> > buffer. The iterator is then extracted to a scatterlist with
> > multiple calls to extract_iter_to_sg. The final scatterlist
> > is copied into a scratch buffer.
> >
> > The test passes if the scratch buffer contains the same data
> > as the original buffer.
> >
> > The new tests demonstrate bugs in extract_iter_to_sg
> > for kvec and user iterators that are fixed by the previous
> > commits.
> >
> > Cc: David Howells <dhowells@redhat.com>
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
> > ---
>
> Hmm... this is failing on powerpc, where PAGE_SIZE is 64k:
>
> [13:20:40] # iov_kunit_iter_to_sg_kvec: ASSERTION FAILED at
Sorry about that! I wasn't aware of the large page size on powerpc.
This should fix it. I will prepare a proper patch but it would
be cool if you could verify that it actually helps.
Best regards,
Christian
diff --git a/lib/tests/kunit_iov_iter.c b/lib/tests/kunit_iov_iter.c
index 37bd6eb25896..f02f7b7aa796 100644
--- a/lib/tests/kunit_iov_iter.c
+++ b/lib/tests/kunit_iov_iter.c
@@ -1128,7 +1128,7 @@ static void __init iov_kunit_iter_to_sg_kvec(struct kunit *test)
struct kvec kvec;
size_t bufsize;
- bufsize = 0x100000;
+ bufsize = 0x200000;
iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
kvec.iov_base = data.buffer;
@@ -1146,7 +1146,7 @@ static void __init iov_kunit_iter_to_sg_bvec(struct kunit *test)
struct bio_vec *bvec;
struct iov_iter iter;
- bufsize = 0x100000;
+ bufsize = 0x200000;
iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
bvec = kunit_kmalloc_array(test, data.npages, sizeof(*bvec),
@@ -1173,7 +1173,7 @@ static void __init iov_kunit_iter_to_sg_folioq(struct kunit *test)
struct iov_iter iter;
size_t bufsize;
- bufsize = 0x100000;
+ bufsize = 0x200000;
iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
folioq = iov_kunit_create_folioq(test);
@@ -1190,7 +1190,7 @@ static void __init iov_kunit_iter_to_sg_xarray(struct kunit *test)
struct iov_iter iter;
size_t bufsize;
- bufsize = 0x100000;
+ bufsize = 0x200000;
iov_kunit_iter_to_sg_init(test, bufsize, false, &data);
xarray = iov_kunit_create_xarray(test);
@@ -1206,7 +1206,7 @@ static void __init iov_kunit_iter_to_sg_ubuf(struct kunit *test)
struct iov_iter iter;
size_t bufsize;
- bufsize = 0x100000;
+ bufsize = 0x200000;
iov_kunit_iter_to_sg_init(test, bufsize, true, &data);
iov_iter_ubuf(&iter, READ, data.ubuf, bufsize);
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg
2026-04-21 6:30 ` Christian A. Ehrhardt
@ 2026-04-21 6:49 ` David Gow
0 siblings, 0 replies; 10+ messages in thread
From: David Gow @ 2026-04-21 6:49 UTC (permalink / raw)
To: Christian A. Ehrhardt
Cc: David Howells, Andrew Morton, linux-kernel, Kees Cook, Petr Mladek
Le 21/04/2026 à 14:30, Christian A. Ehrhardt a écrit :
>
> Hi David,
>
> On Tue, Apr 21, 2026 at 01:45:33PM +0800, David Gow wrote:
>> Le 27/03/2026 à 05:49, Christian A. Ehrhardt a écrit :
>>> Add test cases that test extract_iter_to_sg.
>>>
>>> For each iterator type an iterator is loaded with a suitable
>>> buffer. The iterator is then extracted to a scatterlist with
>>> multiple calls to extract_iter_to_sg. The final scatterlist
>>> is copied into a scratch buffer.
>>>
>>> The test passes if the scratch buffer contains the same data
>>> as the original buffer.
>>>
>>> The new tests demonstrate bugs in extract_iter_to_sg
>>> for kvec and user iterators that are fixed by the previous
>>> commits.
>>>
>>> Cc: David Howells <dhowells@redhat.com>
>>> Cc: Andrew Morton <akpm@linux-foundation.org>
>>> Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
>>> ---
>>
>> Hmm... this is failing on powerpc, where PAGE_SIZE is 64k:
>>
>> [13:20:40] # iov_kunit_iter_to_sg_kvec: ASSERTION FAILED at
>
> Sorry about that! I wasn't aware of the large page size on powerpc.
> This should fix it. I will prepare a proper patch but it would
> be cool if you could verify that it actually helps.
>
> Best regards,
> Christian
>
Works here, thanks. Sorry I didn't pick it before it went in.
I tested with:
./tools/testing/kunit/kunit.py run --arch powerpc --cross_compile
powerpc64-suse-linux-
(But it'll obviously need some minor tweaks for non-SUSE distros…)
Cheers,
-- David
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-04-21 6:50 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-26 21:49 [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 1/5] lib/scatterlist: Fix length calculations in extract_kvec_to_sg Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 2/5] lib/scatterlist: Fix temp buffer in extract_user_to_sg() Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 3/5] lib: kunit_iov_iter: Fix memory leaks Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 4/5] lib: kunit_iov_iter: Improve error detection Christian A. Ehrhardt
2026-03-26 21:49 ` [PATCH v3 5/5] lib: kunit_iov_iter: Add tests for extract_iter_to_sg Christian A. Ehrhardt
2026-04-21 5:45 ` David Gow
2026-04-21 6:30 ` Christian A. Ehrhardt
2026-04-21 6:49 ` David Gow
2026-03-26 22:39 ` [PATCH v3 0/5] Fix bugs in extract_iter_to_sg() Andrew Morton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®