[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20231201204714.21f7124c@kernel.org>
Date: Fri, 1 Dec 2023 20:47:14 -0800
From: Jakub Kicinski <kuba@...nel.org>
To: Stefan Wahren <wahrenst@....net>
Cc: "David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Paolo Abeni <pabeni@...hat.com>,
Lino Sanfilippo <LinoSanfilippo@....de>,
Florian Fainelli <f.fainelli@...il.com>,
netdev@...r.kernel.org, linux-kernel@...r.kernel.org
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 <wahrenst@....net>
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
Powered by blists - more mailing lists