Message ID | 20240612001654.923887-1-ziweixiao@google.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 6f4d93b78ade0a4c2cafd587f7b429ce95abb02e |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net] gve: Clear napi->skb before dev_kfree_skb_any() | expand |
On Wed, 12 Jun 2024 00:16:54 +0000 Ziwei Xiao wrote: > + if (rx->ctx.skb_head == napi->skb) > + napi->skb = NULL; There doesn't seem to be much precedent for directly poking at this field in drivers but I don't have any better ideas..
Hello: This patch was applied to netdev/net.git (main) by Jakub Kicinski <kuba@kernel.org>: On Wed, 12 Jun 2024 00:16:54 +0000 you wrote: > 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: 9b8dd5e5ea48 ("gve: DQO: Add RX path") > Cc: stable@vger.kernel.org > Reported-by: Shailend Chand <shailend@google.com> > Signed-off-by: Ziwei Xiao <ziweixiao@google.com> > Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com> > Reviewed-by: Shailend Chand <shailend@google.com> > Reviewed-by: Praveen Kaligineedi <pkaligineedi@google.com> > > [...] Here is the summary with links: - [net] gve: Clear napi->skb before dev_kfree_skb_any() https://git.kernel.org/netdev/net/c/6f4d93b78ade You are awesome, thank you!
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c index c1c912de59c7..1154c1d8f66f 100644 --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c @@ -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); } -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) return; + if (rx->ctx.skb_head == napi->skb) + napi->skb = NULL; dev_kfree_skb_any(rx->ctx.skb_head); rx->ctx.skb_head = NULL; rx->ctx.skb_tail = NULL; @@ -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); if (err < 0) { - gve_rx_free_skb(rx); + gve_rx_free_skb(napi, rx); u64_stats_update_begin(&rx->statss); if (err == -ENOMEM) rx->rx_skb_alloc_fail++; @@ -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 */ 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); rx->rx_desc_err_dropped_pkt++; u64_stats_update_end(&rx->statss);