2023-12-02 04:47:27

by Jakub Kicinski

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

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 protected]>

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