All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Théo Lebrun" <theo.lebrun@bootlin.com>
To: "Paolo Abeni" <pabeni@redhat.com>
Cc: <conor.dooley@microchip.com>, <andrew+netdev@lunn.ch>,
	<davem@davemloft.net>, <edumazet@google.com>, <kuba@kernel.org>,
	<richardcochran@gmail.com>, <linux@armlinux.org.uk>,
	<netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<nicolas.ferre@microchip.com>, <claudiu.beznea@tuxon.dev>,
	<pvalerio@redhat.com>, <nb@tipi-net.de>,
	<vladimir.kondratiev@mobileye.com>, <gregory.clement@bootlin.com>,
	<benoit.monin@bootlin.com>, <tawfik.bayouk@mobileye.com>,
	<thomas.petazzoni@bootlin.com>, <maxime.chevallier@bootlin.com>
Subject: Re: [PATCH net-next v3 07/15] net: macb: introduce macb_context struct for buffer management
Date: Mon, 13 Jul 2026 14:53:55 +0200	[thread overview]
Message-ID: <DJXGIM9EGPT8.4UHNYP2Y0GOP@bootlin.com> (raw)
In-Reply-To: <20260708102716.169767-1-pabeni@redhat.com>

Hello Paolo's LLM,

On Wed Jul 8, 2026 at 12:27 PM CEST, Paolo Abeni wrote:
> From: AI Reviewer <ai@example.com>
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at: https://netdev-ai.bots.linux.dev/sashiko/
> ---
> net: macb: introduce macb_context struct for buffer management
>
> This patch moves per-queue ring buffers and ring-size parameters out of
> struct macb / struct macb_queue into a new struct macb_context that is
> allocated on open and freed on close, so future patches can swap in a
> new context while the interface is running.
>
>> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
>> index 951a7f080225..dfb1d49d841c 100644
>> --- a/drivers/net/ethernet/cadence/macb_main.c
>> +++ b/drivers/net/ethernet/cadence/macb_main.c
>
> [ ... ]
>
>> @@ -1257,6 +1288,7 @@ static void macb_tx_error_task(struct work_struct *work)
>>  	struct macb_queue *queue = container_of(work, struct macb_queue,
>>  						tx_error_task);
>>  	unsigned int q = queue - queue->bp->queues;
>> +	struct macb_txq *txq = macb_txq(queue);
>>  	struct macb *bp = queue->bp;
>
> [High]
> Can macb_tx_error_task() dereference a freed context?
>
> macb_tx_error_task is scheduled from macb_interrupt():
>
>     schedule_work(&queue->tx_error_task);
>
> After this patch, the very first thing the worker does is:
>
>     struct macb_txq *txq = macb_txq(queue);
>
> which expands to &bp->ctx->txq[q] and dereferences bp->ctx.
>
> Looking at macb_close():
>
>     macb_reset_hw(bp);
>     ...
>     macb_free(bp);
>     kfree(bp->ctx);
>     bp->ctx = NULL;
>
> There is no cancel_work_sync(&queue->tx_error_task), and macb_reset_hw()
> does not drain the workqueue. If an interrupt scheduled the work just
> before close, or the work was already pending, the worker can run after
> kfree(bp->ctx) and hit a NULL dereference (and a use-after-free if
> macb_open() re-allocates ctx concurrently via ethtool ring reconfig).
>
> The same reasoning applies to bp->hresp_err_bh_work, which is queued
> from macb_interrupt() and whose handler calls
> mog_init_rings()/macb_init_buffers() that read bp->ctx->tx_ring_size and
> bp->ctx->{tx,rx}q[q]. cancel_work_sync(&bp->hresp_err_bh_work) is only
> called from macb_remove(), not macb_close().

All of this is a valid concern.

> Pre-patch these fields lived inside the embedded struct macb_queue so a
> late worker would touch stale-but-addressable memory; post-patch the
> first indirection through bp->ctx faults.

This pre-series analysis is wrong however. Current upstream would crash:
macb_tx_error_task() restarts the HW and it even assigns
queue->tx_ring_dma which still contains the freed DMA address
(macb_free()/macb_close() don't reset that value).

Summary: this patch turns potential memory corruption into a NULL
pointer dereference.

> Would adding cancel_work_sync(&queue->tx_error_task) per queue and
> cancel_work_sync(&bp->hresp_err_bh_work) before kfree(bp->ctx) in
> macb_close() close this window?

Yes that is the way forward. It will probably be separate and target
net/main. Not specifically because I want it backported (it'd be nice
but issue is super unlikely and no one reported it) but mostly because
this series is already 15 patches long.

>> @@ -3690,8 +3778,8 @@ static int macb_set_ringparam(struct net_device *netdev,
>>  		macb_close(bp->netdev);
>>  	}
>>  
>> -	bp->rx_ring_size = new_rx_size;
>> -	bp->tx_ring_size = new_tx_size;
>> +	bp->configured_rx_ring_size = new_rx_size;
>> +	bp->configured_tx_ring_size = new_tx_size;
>>  
>>  	if (reset)
>>  		macb_open(bp->netdev);
>
> [Medium]
> Should the return value of macb_open() be checked here?
>
> This patch adds a new failure point inside macb_open():
>
>     bp->ctx = kzalloc_obj(*bp->ctx);
>     if (!bp->ctx) {
>         err = -ENOMEM;
>         goto pm_exit;
>     }
>
> On failure, bp->ctx remains NULL and the interface stays down, but
> macb_set_ringparam() ignores the return value and reports success to
> userspace. The commit message says the motivation is to improve
> reliability under memory pressure, but this caller silently swallows the
> new allocation failure.

No need, this series ends with context swapping and the
macb_context_swap_end() operation, which replaces the macb_open()
highlighted here, cannot fail.

>> @@ -5039,6 +5125,12 @@ static int at91ether_open(struct net_device *netdev)
>>  	if (ret < 0)
>>  		return ret;
>>  
>> +	bp->ctx = kzalloc_obj(*bp->ctx);
>> +	if (!bp->ctx) {
>> +		ret = -ENOMEM;
>> +		goto pm_exit;
>> +	}
>> +
>>  	/* Clear internal statistics */
>>  	ctl = macb_readl(bp, NCR);
>>  	macb_writel(bp, NCR, ctl | MACB_BIT(CLRSTAT));
>
> [Low]
> Should bp->ctx->rx_ring_size, tx_ring_size and rx_buffer_size be
> initialized on this path?
>
> macb_open() sets them from configured_{rx,tx}_ring_size and calls
> macb_init_rx_buffer_size(), but at91ether_open() leaves them at zero
> after kzalloc_obj().
>
> Helpers such as macb_rx_ring_wrap() compute:
>
>     return index & (bp->ctx->rx_ring_size - 1);
>
> which becomes index & 0xFFFFFFFF when rx_ring_size is 0. It happens to
> be harmless today because the at91ether path constrains indices to
> [0, AT91ETHER_MAX_RX_DESCR-1] independently and macb_get_regs() reports
> zeroed head/tail for the tx-less at91ether, but pre-patch macb_init_dflt()
> unconditionally set bp->rx_ring_size = DEFAULT_RX_RING_SIZE.
>
> Any future shared helper that used tx_ring_size as a stride or divisor
> would misbehave on at91ether.

Yes. Null impact (but it would be better in theory).

>> @@ -5076,6 +5171,9 @@ static int at91ether_close(struct net_device *netdev)
>>  
>>  	at91ether_stop(bp);
>>  
>> +	kfree(bp->ctx);
>> +	bp->ctx = NULL;
>> +
>>  	pm_runtime_put(&bp->pdev->dev);
>>  
>>  	return 0;
>
> [High]
> Is there IRQ synchronization missing before freeing bp->ctx on this
> path?
>
> at91ether_stop() disables MAC RX/TX and writes IDR to mask further
> interrupts, but does not synchronize with a handler already running or
> already dispatched on another CPU. at91ether_interrupt() calls
> at91ether_rx(), which after this patch does:
>
>     struct macb_rxq *rxq = &bp->ctx->rxq[0];
>     ...
>     desc = macb_rx_desc(queue, rxq->tail);
>     ...
>     p_recv = rxq->buffers + rxq->tail * AT91ETHER_MAX_RBUFF_SZ;
>
> If the handler is in flight when kfree(bp->ctx); bp->ctx = NULL runs,
> the next access through bp->ctx faults. The macb_open()/macb_close()
> path is somewhat protected by napi_disable() before macb_free(), but
> at91ether does not use NAPI and has no equivalent barrier.
>
> Would a synchronize_irq(bp->netdev->irq) between at91ether_stop() and
> kfree(bp->ctx) close this?

Ah at91ether_interrupt() doesn't grab bp->lock as macb_interrupt() does.
Indeed synchronize_irq() would solve this.

Thanks,

--
Théo Lebrun, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


  reply	other threads:[~2026-07-13 12:54 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-01 15:59 [PATCH net-next v3 00/15] net: macb: implement context swapping Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 01/15] net: macb: drop "consistent" from alloc/free function names Théo Lebrun
2026-07-02 10:41   ` Nicolai Buchwitz
2026-07-03 11:28   ` Conor Dooley
2026-07-03 16:32     ` Théo Lebrun
2026-07-03 16:34       ` Conor Dooley
2026-07-01 15:59 ` [PATCH net-next v3 02/15] net: macb: unify device pointer naming convention Théo Lebrun
2026-07-03 11:29   ` Conor Dooley
2026-07-01 15:59 ` [PATCH net-next v3 03/15] net: macb: unify variable naming convention in at91ether functions Théo Lebrun
2026-07-02 10:42   ` Nicolai Buchwitz
2026-07-03 11:30   ` Conor Dooley
2026-07-01 15:59 ` [PATCH net-next v3 04/15] net: macb: unify queue index variable naming convention and types Théo Lebrun
2026-07-02 10:43   ` Nicolai Buchwitz
2026-07-03 11:34   ` Conor Dooley
2026-07-03 17:10     ` Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 05/15] net: macb: enforce reverse christmas tree (RCT) convention Théo Lebrun
2026-07-02 10:48   ` Nicolai Buchwitz
2026-07-03 11:35   ` Conor Dooley
2026-07-01 15:59 ` [PATCH net-next v3 06/15] net: macb: allocate tieoff descriptor once across device lifetime Théo Lebrun
2026-07-02 10:54   ` Nicolai Buchwitz
2026-07-13 12:00     ` Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 07/15] net: macb: introduce macb_context struct for buffer management Théo Lebrun
2026-07-03 11:39   ` Conor Dooley
2026-07-08 10:27   ` Paolo Abeni
2026-07-13 12:53     ` Théo Lebrun [this message]
2026-07-01 15:59 ` [PATCH net-next v3 08/15] net: macb: avoid macb_init_rx_buffer_size() modifying state Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 09/15] net: macb: make `struct macb` subset reachable from macb_context struct Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 10/15] net: macb: change caps helpers signatures Théo Lebrun
2026-07-03 11:43   ` Conor Dooley
2026-07-01 15:59 ` [PATCH net-next v3 11/15] net: macb: change function signatures to take contexts Théo Lebrun
2026-07-03 11:45   ` Conor Dooley
2026-07-01 15:59 ` [PATCH net-next v3 12/15] net: macb: introduce macb_context_alloc() helper Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 13/15] net: macb: re-read ISR inside IRQ handler locked section Théo Lebrun
2026-07-03 12:09   ` Conor Dooley
2026-07-13 15:04     ` Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 14/15] net: macb: use context swapping in .set_ringparam() Théo Lebrun
2026-07-02 10:37   ` Nicolai Buchwitz
2026-07-13 16:41     ` Théo Lebrun
2026-07-01 15:59 ` [PATCH net-next v3 15/15] net: macb: use context swapping in .ndo_change_mtu() Théo Lebrun

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=DJXGIM9EGPT8.4UHNYP2Y0GOP@bootlin.com \
    --to=theo.lebrun@bootlin.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=benoit.monin@bootlin.com \
    --cc=claudiu.beznea@tuxon.dev \
    --cc=conor.dooley@microchip.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=gregory.clement@bootlin.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=maxime.chevallier@bootlin.com \
    --cc=nb@tipi-net.de \
    --cc=netdev@vger.kernel.org \
    --cc=nicolas.ferre@microchip.com \
    --cc=pabeni@redhat.com \
    --cc=pvalerio@redhat.com \
    --cc=richardcochran@gmail.com \
    --cc=tawfik.bayouk@mobileye.com \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=vladimir.kondratiev@mobileye.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.