Commit 6f4d93b7 authored by Ziwei Xiao's avatar Ziwei Xiao Committed by Jakub Kicinski

gve: Clear napi->skb before dev_kfree_skb_any()

gve_rx_free_skb incorrectly leaves napi->skb referencing an skb after it
is freed with dev_kfree_skb_any(). This can result in a subsequent call
to napi_get_frags returning a dangling pointer.

Fix this by clearing napi->skb before the skb is freed.

Fixes: 9b8dd5e5 ("gve: DQO: Add RX path")
Cc: stable@vger.kernel.org
Reported-by: default avatarShailend Chand <shailend@google.com>
Signed-off-by: default avatarZiwei Xiao <ziweixiao@google.com>
Reviewed-by: default avatarHarshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: default avatarShailend Chand <shailend@google.com>
Reviewed-by: default avatarPraveen Kaligineedi <pkaligineedi@google.com>
Link: https://lore.kernel.org/r/20240612001654.923887-1-ziweixiao@google.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 79f18a41
...@@ -647,11 +647,13 @@ static void gve_rx_skb_hash(struct sk_buff *skb, ...@@ -647,11 +647,13 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type); skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type);
} }
static void gve_rx_free_skb(struct gve_rx_ring *rx) static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
{ {
if (!rx->ctx.skb_head) if (!rx->ctx.skb_head)
return; return;
if (rx->ctx.skb_head == napi->skb)
napi->skb = NULL;
dev_kfree_skb_any(rx->ctx.skb_head); dev_kfree_skb_any(rx->ctx.skb_head);
rx->ctx.skb_head = NULL; rx->ctx.skb_head = NULL;
rx->ctx.skb_tail = NULL; rx->ctx.skb_tail = NULL;
...@@ -950,7 +952,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget) ...@@ -950,7 +952,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget)
err = gve_rx_dqo(napi, rx, compl_desc, complq->head, rx->q_num); err = gve_rx_dqo(napi, rx, compl_desc, complq->head, rx->q_num);
if (err < 0) { if (err < 0) {
gve_rx_free_skb(rx); gve_rx_free_skb(napi, rx);
u64_stats_update_begin(&rx->statss); u64_stats_update_begin(&rx->statss);
if (err == -ENOMEM) if (err == -ENOMEM)
rx->rx_skb_alloc_fail++; rx->rx_skb_alloc_fail++;
...@@ -993,7 +995,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget) ...@@ -993,7 +995,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget)
/* gve_rx_complete_skb() will consume skb if successful */ /* gve_rx_complete_skb() will consume skb if successful */
if (gve_rx_complete_skb(rx, napi, compl_desc, feat) != 0) { if (gve_rx_complete_skb(rx, napi, compl_desc, feat) != 0) {
gve_rx_free_skb(rx); gve_rx_free_skb(napi, rx);
u64_stats_update_begin(&rx->statss); u64_stats_update_begin(&rx->statss);
rx->rx_desc_err_dropped_pkt++; rx->rx_desc_err_dropped_pkt++;
u64_stats_update_end(&rx->statss); u64_stats_update_end(&rx->statss);
......
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