mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: james@codeconstruct.com.au
Cc: jk@codeconstruct.com.au, matt@codeconstruct.com.au,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, kees@kernel.org,
	gustavoars@kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org
Subject: Re: [PATCH net-next v2 6/7] net: mctp: usblib: Add initial kunit tx tests
Date: Wed, 09 Sep 2026 05:43:24 +0000	[thread overview]
Message-ID: <178893260401.219967.13741401547777040850@kernel.org> (raw)
In-Reply-To: <20260903-dev-mctp-usb-lib-test-v2-6-313cf15e0b56@codeconstruct.com.au>

Thank you for your contribution! Sashiko AI review found 3 potential
issue(s) to consider:

Critical: 0 · High: 1 · Medium: 0 · Low: 2

- [High] Hard compile error: `static_assert(!sends[ARRAY_SIZE(sends) -
  1].more, ...)` in mctp_usblib_test_tx_multi_push()…
- [Low] mctp_usblib_test_tx_multi_push() (drivers/net/mctp/mctp-usblib-
  test.c:796-869) is documented as "Test sending multiple packets in the…
- [Low] mctp_usblib_test_tx_send() (drivers/net/mctp/mctp-usblib-
  test.c:39-59) calls mctp_usblib_tx_send_complete(tx_ctx, ndev, true)…

--

net: mctp: usblib: Add initial kunit tx tests

This adds KUnit coverage for the mctp-usblib transmit path: a spanning
transfer that is expected to succeed, the failure paths when ops->send
returns an error, and a sequence of larger pushes. The tests record each
->send() call in a list and compare the resulting bytes against the
expected MCTP-over-USB headers and payload.

> diff --git a/drivers/net/mctp/mctp-usblib-test.c b/drivers/net/mctp/mctp-usblib-test.c
> index 64c758013854..73bda4745433 100644
> --- a/drivers/net/mctp/mctp-usblib-test.c
> +++ b/drivers/net/mctp/mctp-usblib-test.c

[ ... ]

> @@ -24,9 +32,104 @@ struct mctp_usblib_test_dev {
>  
>  struct mctp_usblib_test_ctx {
>  	struct mctp_usblib_test_dev *dev;
> +	struct list_head tx_xfers;
>  	struct mctp_route rt;
>  };
>  
> +static int mctp_usblib_test_tx_send(struct mctp_usblib_tx_ctx *tx_ctx,
> +				    void *data, size_t len)
> +{
> +	struct mctp_usblib_test_ctx *ctx;
> +	struct tx_buff *new_node;
> +	struct net_device *ndev;
> +
> +	ctx = mctp_usblib_tx_ctx_priv(tx_ctx);
> +	ndev = ctx->dev->ndev;
> +
> +	new_node = kzalloc_flex(*new_node, data, len, GFP_KERNEL);
> +	if (!new_node)
> +		return -ENOMEM;
> +
> +	new_node->length = len;
> +	memcpy(new_node->data, data, len);
> +	list_add_tail(&new_node->list, &ctx->tx_xfers);
> +
> +	mctp_usblib_tx_send_complete(tx_ctx, ndev, true);
> +	return 0;
> +}

[Severity: Low]

Is completing the transfer inline here consistent with the documented
ops->send contract?

include/linux/usb/mctp-usb.h says, for struct mctp_usblib_tx_ops::send:

	/* Start a USB TX for @data. On returning success, the implementation
	 * must arrange for mctp_usblib_tx_send_complete() to be called at some
	 * later point (eg., on urb completion).
	 */

mctp_usblib_test_tx_send() instead calls mctp_usblib_tx_send_complete()
(which runs mctp_usblib_tx_stats_update() and mctp_usblib_tx_ctx_free())
and then returns 0, so the tx context is already freed at the point
success is reported.  The only in-tree implementer,
mctp_usb_out_complete() in drivers/net/mctp/mctp-usb.c, completes
asynchronously from URB completion.

Nothing breaks today: mctp_usblib_tx_send() reads ctx->tx->ops.send, buf
and ctx->len before the call and only returns the result, and both send
sites in mctp_usblib_tx_push() touch the context afterwards only under
if (rc).  But if the library ever legitimately inspects the context after
a successful ->send(), this harness would report it as a KASAN
use-after-free in the test rather than a driver bug.

Would it be better to either record the context and complete it after the
push returns, or to relax the header comment to explicitly allow
synchronous completion?

[ ... ]

> +static u8 *mctp_usblib_test_flatten_tx_buff(struct kunit *test,
> +					    struct list_head *in,
> +					    size_t *length_out)
> +{
[ ... ]
> +	tail = buf;
> +	list_for_each_entry(pos, in, list) {
> +		memcpy(tail, pos->data, pos->length);
> +		tail += pos->length;
> +	}
> +
> +	*length_out = length;
> +	return buf;
> +}

[ ... ]

> @@ -584,6 +717,156 @@ static void mctp_usblib_test_rx_nonspanning_partial(struct kunit *test)
>  	KUNIT_EXPECT_EQ(test, dev->rx_pkts.qlen, 0);
>  }
>  
> +static void mctp_usblib_test_tx_pkt_span(struct kunit *test)
> +{

[ ... ]

> +/* Test sending multiple packets in the same transfer, followed by one that
> + * spans multiple subsequent transfers.
> + */
> +static void mctp_usblib_test_tx_multi_push(struct kunit *test)
> +{

[Severity: Low]

Do the assertions in this test actually observe either of the two
properties named in the comment?

mctp_usblib_test_tx_send() records every ops->send() call as its own
tx_buff node, but mctp_usblib_test_flatten_tx_buff() concatenates all of
them into one buffer before any comparison, so the transfer count and the
transfer boundaries are discarded.  If mctp_usblib_tx_append() or
mctp_usblib_tx_should_send() regressed and the {1000, true} and
{500, false} packets each went out in their own transfer, the flattened
byte stream would be identical and the test would still pass.

For the second half of the comment, the {5000, false} entry does not span
transfers at the ops layer.  mctp_usblib_tx_push() calls
mctp_usblib_tx_ctx_create(tx, skb, single = !more), and:

drivers/net/mctp/mctp-usblib.c:mctp_usblib_tx_ctx_create() {
	...
	if (single || skb->len > TX_SPAN_MAX) {
		type = TX_SINGLE;
	} else {
	...
}

so with more == false (and skb->len of 5004 exceeding TX_SPAN_MAX anyway)
mctp_usblib_tx_send() issues exactly one ops->send() carrying all 5004
bytes; the library never splits one MCTP packet over several ->send()
calls.

The same naming question applies to mctp_usblib_test_tx_pkt_span(), which
also pushes with more == false and produces a single ->send(), so what it
really covers is the v1.1 13-bit length path in
mctp_usblib_tx_skb_prepare() rather than spanning.

Could the comment and the test names be reworded, and could the
per-transfer boundaries be checked instead of flattened, so the packing
behaviour is actually asserted?

> +	struct mctp_usblib_test_ctx *ctx;
> +	size_t i, max_length, tx_length;
> +	struct mctp_usblib_tx_ops ops;
> +	u8 *buf, *flat_tx, *index;
> +	struct mctp_usblib_tx *tx;
> +	struct net_device *ndev;
> +	struct sk_buff *skb;
> +	const struct {
> +		size_t len;
> +		bool more;
> +	} sends[] = {
> +		{ 1000, true  },
> +		{  500, false },
> +		{ 5000, false },
> +	};
> +	int rc;
> +
> +	static_assert(!sends[ARRAY_SIZE(sends) - 1].more,
> +		      "The last push must claim there will be no more");

[Severity: High]

Does this static_assert() compile?

sends[] is a block-scope object with automatic storage duration; the const
qualifier does not make a read of one of its members an integer constant
expression, which is what _Static_assert() requires.  include/linux/build_bug.h
expands static_assert() straight through:

	#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
	#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)

so gcc reports "expression in static assertion is not constant" and clang
reports "static assertion expression is not an integral constant
expression" here.

Because drivers/net/mctp/mctp-usblib.c textually includes this file:

	#if IS_ENABLED(CONFIG_MCTP_TRANSPORT_USBLIB_TEST)
	#include "mctp-usblib-test.c"
	#endif

the failure takes out the whole translation unit, so
drivers/net/mctp/mctp-usblib.o does not build whenever
CONFIG_MCTP_TRANSPORT_USBLIB_TEST is enabled, which is exactly the config
needed to run these tests.  The same static_assert is still present in
mctp_usblib_test_tx_multi_push() at the end of the series (7b7c42135cec),
so nothing later in the series fixes it.

Would BUILD_BUG_ON(), which relies on optimizer folding, or a run-time
KUNIT_ASSERT_FALSE(test, sends[ARRAY_SIZE(sends) - 1].more) express the
same invariant?

> +
> +	max_length = 0;
> +	for (i = 0; i < ARRAY_SIZE(sends); i++) {
> +		if (sends[i].len > max_length)
> +			max_length = sends[i].len;
> +	}

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260903-dev-mctp-usb-lib-test-v2-0-313cf15e0b56%40codeconstruct.com.au

  reply	other threads:[~2026-09-09  5:43 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-03  2:42 [PATCH net-next v2 0/7] net: mctp: usblib: Increase coverage of kunit testing James Lee
2026-09-03  2:42 ` [PATCH net-next v2 1/7] net: mctp: usblib: Add to parameterized kunit tests James Lee
2026-09-09  5:43   ` netdev-bot+sashiko
2026-09-03  2:42 ` [PATCH net-next v2 2/7] net: mctp: usblib: Add test for splits inside headers James Lee
2026-09-09  5:43   ` netdev-bot+sashiko
2026-09-09  7:12   ` Simon Horman
2026-09-03  2:42 ` [PATCH net-next v2 3/7] net: mctp: usblib: Add tests of invalid headers James Lee
2026-09-09  5:43   ` netdev-bot+sashiko
2026-09-03  2:42 ` [PATCH net-next v2 4/7] net: mctp: usblib: Complete rx tests James Lee
2026-09-09  5:43   ` netdev-bot+sashiko
2026-09-03  2:42 ` [PATCH net-next v2 5/7] net: mctp: usblib: Simplify allocation logic in mctp_usblib_test_rx_init James Lee
2026-09-03  2:42 ` [PATCH net-next v2 6/7] net: mctp: usblib: Add initial kunit tx tests James Lee
2026-09-09  5:43   ` netdev-bot+sashiko [this message]
2026-09-03  2:42 ` [PATCH net-next v2 7/7] net: mctp: usblib: Add test for failing append James Lee
2026-09-09  5:43   ` netdev-bot+sashiko

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=178893260401.219967.13741401547777040850@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=gustavoars@kernel.org \
    --cc=james@codeconstruct.com.au \
    --cc=jk@codeconstruct.com.au \
    --cc=kees@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=matt@codeconstruct.com.au \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /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

all inboxes | Powered by JetHome®