Linux 9p file system development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "David Howells" <dhowells@redhat.com>
Cc: v9fs@lists.linux.dev, "Chuck Lever" <cel@kernel.org>,
	"Jeff Layton" <jlayton@kernel.org>,
	"Anna Schumaker" <anna@kernel.org>
Subject: Re: [PATCH v16 05/15] iov_iter: Add a bvecq kunit test
Date: Sat, 07 Nov 2026 17:01:17 +0000	[thread overview]
Message-ID: <sashiko-outbox-203082@kernel.org> (raw)
In-Reply-To: <20261107160823.1465553-6-dhowells@redhat.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Medium] iov_iter: kunit_bvecq marks test functions __init with
  kunit_test_suites()
- [Low] iov_iter: folio leak and unchecked action registration in
  kunit_bvecq
- [Low] iov_iter: bvecq_kunit_advance() bounds revert steps by left
  instead of pos
--

commit 078e4c29ad244b5b9e915f77ff2e3db4692905e6
Author: David Howells <dhowells@redhat.com>

iov_iter: Add a bvecq kunit test

This commit adds a KUnit test suite for the bvecq iterator covering advance,
revert, copy-out, iov_iter_npages(), and iov_iter_alignment() across various
bvecq chain recipes and partial folio configurations.

> diff --git a/lib/tests/kunit_bvecq.c b/lib/tests/kunit_bvecq.c
> new file mode 100644
> index 0000000000000..7cdd455df6929
> --- /dev/null
> +++ b/lib/tests/kunit_bvecq.c
> @@ -0,0 +1,599 @@

[ ... ]

> +static void __init iov_bvecq_alloc_folios(struct kunit *test)
> +{
> +	struct folio *folio, **folios = bvecq_kunit_folios;
> +	const int nr = ARRAY_SIZE(bvecq_kunit_folios);
> +
> +	bvecq_kunit_pagemap_nr = 0;
> +	memset(bvecq_kunit_pagemap, 0, sizeof(bvecq_kunit_pagemap));
> +	memset(bvecq_kunit_folios, 0, sizeof(bvecq_kunit_folios));
> +
> +	for (int i = 0; i < nr; i++) {
> +		folio = folio_alloc(GFP_KERNEL, bvecq_kunit_orders[i]);
> +		KUNIT_ASSERT_NOT_NULL(test, folio);
> +		folios[i] = folio;
> +
> +		/* Fill each subpage with a different but predictable pattern. */
> +		for (int j = 0; j < folio_nr_pages(folio); j++) {
> +			u8 *p = kmap_local_folio(folio, PAGE_SIZE * j);
> +
> +			for (int k = 0; k < PAGE_SIZE; k++)
> +				p[k] = bvecq_kunit_pattern(i, j, k);
> +			kunmap_local(p);
> +		}
> +	}
> +
> +	kunit_add_action_or_reset(test, bvecq_kunit_release_folios, folios);
> +}
> +
> +/*
> + * Follow the specified recipe to allocate a bvecq chain and stick the folios
> + * and empty gaps into it.  Further, the offset into and length of each folio
> + * is adjusted from the partials list.  Each ALLOC command will append a new
> + * bvecq to the chain and move to filling that.
> + */
> +static struct bvecq *__init bvecq_kunit_load_chain(
> +	struct kunit *test,
> +	const struct bvecq_test_recipe *rec,
> +	const struct bvecq_test_partials *parts,
> +	size_t *size)
> +{
> +	struct bvecq *head = NULL, *bq = NULL, *p;
> +	size_t pos = 0;
> +	int folio_index = 0;
> +
> +	*size = 0;
> +
> +	for (; rec->cmd != BVECQ_KUNIT_STOP; rec++) {
> +		if (!head)
> +			KUNIT_ASSERT_EQ(test, rec->cmd, BVECQ_KUNIT_ALLOC);
> +
> +		switch (rec->cmd) {
> +		case BVECQ_KUNIT_STOP:
> +			break;
> +
> +		case BVECQ_KUNIT_ALLOC:
> +			p = bvecq_alloc_one(rec->count, GFP_KERNEL, false);
> +			KUNIT_ASSERT_NOT_NULL(test, p);
> +
> +			if (!head) {
> +				head = p;
> +				kunit_add_action_or_reset(test, bvecq_kunit_bvecq_put, head);
> +				bq = p;
> +			} else {

[Severity: Low]
Does iov_bvecq_alloc_folios() leak already-allocated folios if folio_alloc()
fails after the first iteration?  KUNIT_ASSERT_NOT_NULL() aborts the test
before kunit_add_action_or_reset() is reached, and
bvecq_kunit_release_folios() passes the full array size to release_pages(),
which cannot handle NULL entries in a partially populated array.

Also, neither iov_bvecq_alloc_folios() nor bvecq_kunit_load_chain() checks
the return value of kunit_add_action_or_reset().  If action allocation fails,
the cleanup callback runs immediately to free the folios or head bvecq while
the test continues, causing a NULL pointer dereference or use-after-free.

[ ... ]

> +		/* 3 steps forward. */
> +		part = min(left, 3);
> +		iov_iter_advance(&iter, 3); /* May be short. */
> +		pos += part;
> +		left -= part;
> +		bvecq_kunit_check_next(test, &iter, &pos, &left, 3);
> +
> +		/* 2 steps back */
> +		part = umin(2, left);
> +		iov_iter_revert(&iter, part);
> +		pos -= part;
> +		left += part;
> +		bvecq_kunit_check_next(test, &iter, &pos, &left, 2);
> +
> +		/* 1 more step back */
> +		part = umin(1, left);
> +		iov_iter_revert(&iter, part);
> +		pos -= part;
> +		left += part;
> +		bvecq_kunit_check_next(test, &iter, &pos, &left, 1);

[Severity: Low]
Should these two revert steps clamp against pos (or size - left) rather than
left?  left is the unread byte count remaining ahead, so when the forward
advance and check reach the end of the iterator (left == 0), both reverts
become 0-byte no-ops instead of rewinding.

[ ... ]

> +#define TEST(CHECK, PARTIALS, RECIPE) \
> +static void __init bvecq_kunit_##CHECK##_##PARTIALS##_##RECIPE(struct kunit *test) \
> +{ \
> +	bvecq_kunit_##CHECK(test, \
> +			    bvecq_test_recipe_##RECIPE,	      \
> +			    bvecq_test_partials_##PARTIALS);  \
> +}
> +
> +/* Emit test stub functions. */
> +ADVANCE_TESTS(advance);
> +ADVANCE_TESTS(jump);
> +#undef TEST
> +
> +#define TEST(CHECK, PARTIALS, RECIPE)				\
> +	KUNIT_CASE(bvecq_kunit_##CHECK##_##PARTIALS##_##RECIPE),
> +
> +static struct kunit_case __refdata bvecq_kunit_cases[] = {
> +	ADVANCE_TESTS(advance)
> +	ADVANCE_TESTS(jump)
> +	{}
> +};
> +
> +static struct kunit_suite bvecq_kunit_suite = {
> +	.name = "bvecq",
> +	.test_cases = bvecq_kunit_cases,
> +};
> +
> +kunit_test_suites(&bvecq_kunit_suite);

[Severity: Medium]
Can triggering this suite via /sys/kernel/debug/kunit/bvecq/run after boot or
module load jump into freed .init.text memory?

All test functions and helpers in this file are marked __init, while
kunit_test_suites() registers bvecq_kunit_suite with is_init = false, which
causes kunit_debugfs_create_suite() to expose the debugfs run file.  Should
this either drop __init and __refdata or register the suite with
kunit_test_init_section_suites()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261107160823.1465553-1-dhowells@redhat.com?part=5

  reply	other threads:[~2026-11-07 17:01 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-07 16:08 [PATCH v16 00/15] netfs, iov_iter: Use a chain of bio_vec arrays instead of folio_queue David Howells
2026-11-07 16:08 ` [PATCH v16 01/15] Add a function to kmap one page of a multipage bio_vec David Howells
2026-11-07 16:15   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 02/15] iov_iter: Add a segmented queue of bio_vec[] David Howells
2026-11-07 16:31   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 03/15] netfs: Add some tools for managing bvecq chains David Howells
2026-11-07 16:46   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 04/15] iov_iter: Add an API document for the bvecq structure David Howells
2026-11-07 16:47   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 05/15] iov_iter: Add a bvecq kunit test David Howells
2026-11-07 17:01   ` sashiko-bot [this message]
2026-11-07 16:08 ` [PATCH v16 06/15] afs: Fix an inconsistency in the symlink code David Howells
2026-11-07 17:09   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 07/15] netfs: Explicitly pass tail padding to netfs_writeback_single() David Howells
2026-11-07 17:46   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 08/15] netfs: Change netfs_writeback_single() to not look inside the iterator David Howells
2026-11-07 18:09   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 09/15] afs: Use a bvecq to hold dir content rather than folioq David Howells
2026-11-07 18:34   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 10/15] cifs: Use a bvecq for buffering instead of a folioq David Howells
2026-11-07 18:51   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 11/15] smbdirect: Support ITER_BVECQ in smbdirect_map_sges_from_iter() David Howells
2026-11-07 18:57   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 12/15] netfs: Switch folioq to bvecq David Howells
2026-11-07 19:25   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 13/15] smbdirect: Remove support for ITER_FOLIOQ from smbdirect_map_sges_from_iter() David Howells
2026-11-07 19:29   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 14/15] iov_iter: Remove ITER_FOLIOQ David Howells
2026-11-07 19:31   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 15/15] netfs: Remove folio_queue David Howells
2026-11-07 19:35   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-203082@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=anna@kernel.org \
    --cc=cel@kernel.org \
    --cc=dhowells@redhat.com \
    --cc=jlayton@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=v9fs@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox