All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Lukasz Majewski" <lukasz.majewski@mailbox.org>
Cc: Frank.Li@kernel.org, imx@lists.linux.dev
Subject: Re: [net-next v24 4/7] net: mtip: Add net_device_ops functions to the L2 switch driver
Date: Tue, 02 Jun 2026 11:32:55 +0000	[thread overview]
Message-ID: <20260602113255.765061F0089A@smtp.kernel.org> (raw)
In-Reply-To: <20260601112437.2216043-5-lukasz.majewski@mailbox.org>

Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] Unchecked memcpy into a fixed-size bounce buffer causes a heap buffer overflow if the SKB exceeds the buffer size.
- [High] Accessing an SKB after handing it to the hardware transmission ring causes a use-after-free.
- [High] The watchdog timeout work logic evaluates to true when the device is closed, leading to hardware access crashes.
- [High] Missing hardware lock during `mtip_switch_restart()` causes a data race with concurrent transmissions.
- [High] Mapping a fixed maximum size instead of the actual SKB length causes DMA out-of-bounds reads.
- [High] Incorrect teardown ordering in `mtip_ndev_cleanup` causes a Use-After-Free race with the TX timeout work.
- [Medium] The TX path maps buffers for DMA but does not unmap them during a timeout restart, causing a DMA mapping leak.
--

commit 472dd23af31f2a6b37da050f58cdf8ed66693ebc
Author: Lukasz Majewski <lukasz.majewski@mailbox.org>

net: mtip: Add net_device_ops functions to the L2 switch driver

This patch provides callbacks for struct net_device_ops for MTIP
L2 switch.

> diff --git a/drivers/net/ethernet/freescale/mtipsw/mtipl2sw.c b/drivers/net/ethernet/freescale/mtipsw/mtipl2sw.c
> index 5b5229ee411df..7dfeda230e3fb 100644
> --- a/drivers/net/ethernet/freescale/mtipsw/mtipl2sw.c
> +++ b/drivers/net/ethernet/freescale/mtipsw/mtipl2sw.c
[ ... ]
> @@ -463,6 +472,120 @@ static void mtip_config_switch(struct switch_enet_private *fep)
[ ... ]
> +	/* On some FEC implementations data must be aligned on
> +	 * 4-byte boundaries. Use bounce buffers to copy data
> +	 * and get it aligned.
> +	 */
> +	if ((unsigned long)bufaddr & MTIP_ALIGNMENT ||
> +	    fep->quirks & FEC_QUIRK_SWAP_FRAME) {
> +		memcpy(fep->tx_bounce[index], skb->data, skb->len);

[Severity: Critical]
Does this code overflow the bounce buffer? The bounce buffer has a fixed size,
but there appears to be no bounds check to ensure the skb length actually
fits. A maliciously constructed oversized packet could cause a heap buffer
overflow.

> +		bufaddr = fep->tx_bounce[index];
> +
> +		if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
> +			swap_buffer(bufaddr, skb->len);
> +	}
> +
> +	/* Push the data cache so the CPM does not get stale memory
> +	 * data.
> +	 */
> +	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
> +					  MTIP_SWITCH_TX_FRSIZE,
> +					  DMA_TO_DEVICE);

[Severity: High]
Is it safe to map a fixed maximum size instead of the actual packet length?
Since the underlying memory allocated for the packet may be smaller than
MTIP_SWITCH_TX_FRSIZE, this can force the DMA API to flush memory beyond the
bounds of the allocation, potentially triggering an out-of-bounds read or
IOMMU faults.

> +	if (unlikely(dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr))) {
[ ... ]
> +	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
> +	 * it's the last BD of the frame, and to put the CRC on the end.
> +	 */
> +
> +	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST |
> +		   BD_ENET_TX_TC);
> +
> +	/* Synchronize all descriptor writes */
> +	wmb();
> +	bdp->cbd_sc = status;
> +
> +	skb_tx_timestamp(skb);
> +
> +	dev->stats.tx_bytes += skb->len;

[Severity: High]
Can this sequence cause a use-after-free? Once the descriptor status is
updated and the memory barrier is issued, ownership of the buffer is
transferred to the hardware. The transmission completion interrupt could free
the packet before the timestamp and length are accessed here.

[ ... ]
> +static void mtip_timeout_work(struct work_struct *work)
> +{
> +	struct mtip_ndev_priv *priv =
> +		container_of(work, struct mtip_ndev_priv, tx_timeout_work);
> +	struct switch_enet_private *fep = priv->fep;
> +	struct net_device *dev = priv->dev;
> +
> +	rtnl_lock();
> +	if (netif_device_present(dev) || netif_running(dev)) {

[Severity: High]
Is this logical condition correct? The netif_device_present check evaluates to
true as long as the device is registered, even if it is administratively down.
Writing to the hardware registers via mtip_switch_restart while the device is
closed and the IPG clock is disabled could trigger an imprecise external abort
and crash the system.

> +		napi_disable(&fep->napi);
> +		netif_tx_lock_bh(dev);
> +		mtip_switch_restart(dev, fep->full_duplex[0],
> +				    fep->full_duplex[1]);

[Severity: High]
Does this restart logic cause a data race with concurrent transmissions on the
other port? The driver manages two network ports sharing a single hardware
ring. mtip_switch_restart resets the shared transmission ring state, but only
the tx lock for the specific port that timed out is acquired here, rather than
the shared hardware lock.

[Severity: Medium]
Does mtip_switch_restart leak DMA mappings during a timeout recovery? The
transmission path maps buffers for DMA, but the restart routine appears to
simply free the transmit socket buffers without calling the corresponding unmap
function, potentially leaking IOVA space or bounce buffers on every timeout.

> +		netif_tx_wake_all_queues(dev);
> +		netif_tx_unlock_bh(dev);
> +		napi_enable(&fep->napi);
> +	}
> +	rtnl_unlock();
> +}
[ ... ]
> @@ -1158,10 +1448,14 @@ static int mtip_switch_dma_init(struct switch_enet_private *fep)
>  
>  static void mtip_ndev_cleanup(struct switch_enet_private *fep)
>  {
> +	struct mtip_ndev_priv *priv;
>  	int i;
>  
>  	for (i = 0; i < SWITCH_EPORT_NUMBER; i++) {
>  		if (fep->ndev[i]) {
> +			priv = netdev_priv(fep->ndev[i]);
> +			cancel_work_sync(&priv->tx_timeout_work);
> +
>  			unregister_netdev(fep->ndev[i]);

[Severity: High]
Can this result in a use-after-free race with the timeout work? Calling
unregister_netdev after cancel_work_sync means the networking watchdog is
still active and could fire immediately after cancel_work_sync returns. If the
watchdog queues the work item again, the work could execute after the device
structures have been freed.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260601112437.2216043-1-lukasz.majewski@mailbox.org?part=4

  reply	other threads:[~2026-06-02 11:32 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-01 11:24 [net-next v24 0/7] net: mtip: Add support for MTIP imx287 L2 switch driver Lukasz Majewski
2026-06-01 11:24 ` [net-next v24 1/7] dt-bindings: net: Add MTIP L2 switch description Lukasz Majewski
2026-06-02 11:32   ` sashiko-bot
2026-06-01 11:24 ` [net-next v24 2/7] net: mtip: The L2 switch driver for imx287 Lukasz Majewski
2026-06-02 11:32   ` sashiko-bot
2026-06-05  2:18   ` Jakub Kicinski
2026-06-01 11:24 ` [net-next v24 3/7] net: mtip: Add buffers management functions to the L2 switch driver Lukasz Majewski
2026-06-02 11:32   ` sashiko-bot
2026-06-05  2:18   ` Jakub Kicinski
2026-06-09  8:37     ` Łukasz Majewski
2026-06-01 11:24 ` [net-next v24 4/7] net: mtip: Add net_device_ops " Lukasz Majewski
2026-06-02 11:32   ` sashiko-bot [this message]
2026-06-05  2:18   ` Jakub Kicinski
2026-06-01 11:24 ` [net-next v24 5/7] net: mtip: Add mtip_switch_{rx|tx} " Lukasz Majewski
2026-06-02 11:32   ` sashiko-bot
2026-06-05  2:18   ` Jakub Kicinski
2026-06-01 11:24 ` [net-next v24 6/7] net: mtip: Extend the L2 switch driver with management operations Lukasz Majewski
2026-06-02 11:32   ` sashiko-bot
2026-06-05  2:18   ` Jakub Kicinski
2026-06-01 11:24 ` [net-next v24 7/7] net: mtip: Extend the L2 switch driver for imx287 with bridge operations Lukasz Majewski
2026-06-02 11:32   ` 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=20260602113255.765061F0089A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=lukasz.majewski@mailbox.org \
    --cc=sashiko-reviews@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 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.