Subject: Re: [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes

From: Jakub Kicinski <[email-masked]>
Date: Fri, 1 Dec 2023 20:47:14 -0800

On Wed, 29 Nov 2023 10:52:39 +0100 Stefan Wahren wrote:
> The qca_spi driver stop and restart the SPI kernel thread
> (via ndo_stop & ndo_open) in case of TX ring changes. This is
> a big issue because it allows userspace to prevent restart of
> the SPI kernel thread (via signals). A subsequent change of
> TX ring wrongly assume a valid spi_thread pointer which result
> in a crash.
> 
> So prevent this by stopping the network queue and temporary park
> the SPI thread. Because this could happen during transmission
> we also need to call qcaspi_flush_tx_ring().
> 
> Fixes: 291ab06ecf67 ("net: qualcomm: new Ethernet over SPI driver for QCA7000")
> Signed-off-by: Stefan Wahren <[email-masked]>

Still looks a bit racy.

> diff --git a/drivers/net/ethernet/qualcomm/qca_debug.c b/drivers/net/ethernet/qualcomm/qca_debug.c
> index 6f2fa2a42770..9777dbb17ac2 100644
> --- a/drivers/net/ethernet/qualcomm/qca_debug.c
> +++ b/drivers/net/ethernet/qualcomm/qca_debug.c
> @@ -263,22 +263,29 @@ qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
>  		     struct kernel_ethtool_ringparam *kernel_ring,
>  		     struct netlink_ext_ack *extack)
>  {
> -	const struct net_device_ops *ops = dev->netdev_ops;
>  	struct qcaspi *qca = netdev_priv(dev);
> +	bool queue_active = !netif_queue_stopped(dev);

nothing prevents stopped -> running or running -> stopped
transitions at this point, so this check can be meaningful

>  	if ((ring->rx_pending) ||
>  	    (ring->rx_mini_pending) ||
>  	    (ring->rx_jumbo_pending))
>  		return -EINVAL;
> 
> -	if (netif_running(dev))
> -		ops->ndo_stop(dev);
> +	if (queue_active)
> +		netif_stop_queue(dev);

This doesn't wait for xmit to finish, it just sets a bit.
You probably want something like netif_tx_disable().

Also - the thread may still be running and wake the queue up right after
we stop it.
-- 
pw-bot: cr