* [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 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
* 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
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®