Commit a6451192 authored by Song Yoong Siang's avatar Song Yoong Siang Committed by David S. Miller

net: stmmac: fix kernel panic due to NULL pointer dereference of xsk_pool

After free xsk_pool, there is possibility that napi polling is still
running in the middle, thus causes a kernel crash due to kernel NULL
pointer dereference of rx_q->xsk_pool and tx_q->xsk_pool.

Fix this by changing the XDP pool setup sequence to:
 1. disable napi before free xsk_pool
 2. enable napi after init xsk_pool

The following kernel panic is observed without this patch:

RIP: 0010:xsk_uses_need_wakeup+0x5/0x10
Call Trace:
stmmac_napi_poll_rxtx+0x3a9/0xae0 [stmmac]
__napi_poll+0x27/0x130
net_rx_action+0x233/0x280
__do_softirq+0xe2/0x2b6
run_ksoftirqd+0x1a/0x20
smpboot_thread_fn+0xac/0x140
? sort_range+0x20/0x20
kthread+0x124/0x150
? set_kthread_struct+0x40/0x40
ret_from_fork+0x1f/0x30
---[ end trace a77c8956b79ac107 ]---

Fixes: bba2556e ("net: stmmac: Enable RX via AF_XDP zero-copy")
Cc: <stable@vger.kernel.org> # 5.13.x
Signed-off-by: default avatarSong Yoong Siang <yoong.siang.song@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 85520079
...@@ -34,18 +34,18 @@ static int stmmac_xdp_enable_pool(struct stmmac_priv *priv, ...@@ -34,18 +34,18 @@ static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv); need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
if (need_update) { if (need_update) {
stmmac_disable_rx_queue(priv, queue);
stmmac_disable_tx_queue(priv, queue);
napi_disable(&ch->rx_napi); napi_disable(&ch->rx_napi);
napi_disable(&ch->tx_napi); napi_disable(&ch->tx_napi);
stmmac_disable_rx_queue(priv, queue);
stmmac_disable_tx_queue(priv, queue);
} }
set_bit(queue, priv->af_xdp_zc_qps); set_bit(queue, priv->af_xdp_zc_qps);
if (need_update) { if (need_update) {
napi_enable(&ch->rxtx_napi);
stmmac_enable_rx_queue(priv, queue); stmmac_enable_rx_queue(priv, queue);
stmmac_enable_tx_queue(priv, queue); stmmac_enable_tx_queue(priv, queue);
napi_enable(&ch->rxtx_napi);
err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX); err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX);
if (err) if (err)
...@@ -72,10 +72,10 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue) ...@@ -72,10 +72,10 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv); need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
if (need_update) { if (need_update) {
napi_disable(&ch->rxtx_napi);
stmmac_disable_rx_queue(priv, queue); stmmac_disable_rx_queue(priv, queue);
stmmac_disable_tx_queue(priv, queue); stmmac_disable_tx_queue(priv, queue);
synchronize_rcu(); synchronize_rcu();
napi_disable(&ch->rxtx_napi);
} }
xsk_pool_dma_unmap(pool, STMMAC_RX_DMA_ATTR); xsk_pool_dma_unmap(pool, STMMAC_RX_DMA_ATTR);
...@@ -83,10 +83,10 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue) ...@@ -83,10 +83,10 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
clear_bit(queue, priv->af_xdp_zc_qps); clear_bit(queue, priv->af_xdp_zc_qps);
if (need_update) { if (need_update) {
napi_enable(&ch->rx_napi);
napi_enable(&ch->tx_napi);
stmmac_enable_rx_queue(priv, queue); stmmac_enable_rx_queue(priv, queue);
stmmac_enable_tx_queue(priv, queue); stmmac_enable_tx_queue(priv, queue);
napi_enable(&ch->rx_napi);
napi_enable(&ch->tx_napi);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment