* [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() @ 2025-07-23 0:32 Chenyuan Yang 2025-07-24 9:57 ` Paolo Abeni 0 siblings, 1 reply; 8+ messages in thread From: Chenyuan Yang @ 2025-07-23 0:32 UTC (permalink / raw) To: ecree.xilinx, andrew+netdev, davem, edumazet, kuba, pabeni, ast, daniel, hawk, john.fastabend, sdf, lorenzo Cc: netdev, linux-net-drivers, bpf, zzjas98, Chenyuan Yang The xdp_convert_buff_to_frame() function can return NULL when there is insufficient headroom in the buffer to store the xdp_frame structure or when the driver didn't reserve enough tailroom for skb_shared_info. Currently, the sfc driver does not check for this NULL return value in the XDP_TX case within efx_do_xdp(). While the efx_xdp_tx_buffers() function has some defensive checks, passing a NULL xdpf can still lead to undefined behavior when the function tries to access xdpf->len and xdpf->data. Fix by adding a proper NULL check in the XDP_TX case. If conversion fails, free the RX buffer and increment the bad drops counter, following the same pattern used for other XDP error conditions in this driver. Signed-off-by: Chenyuan Yang <chenyuan0y@gmail.com> Fixes: 1b698fa5d8ef ("xdp: Rename convert_to_xdp_frame in xdp_convert_buff_to_frame") --- drivers/net/ethernet/sfc/rx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index ffca82207e47..6321ccd8c8fa 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -308,6 +308,12 @@ static bool efx_do_xdp(struct efx_nic *efx, struct efx_channel *channel, case XDP_TX: /* Buffer ownership passes to tx on success. */ xdpf = xdp_convert_buff_to_frame(&xdp); + if (unlikely(!xdpf)) { + efx_free_rx_buffers(rx_queue, rx_buf, 1); + channel->n_rx_xdp_bad_drops++; + break; + } + err = efx_xdp_tx_buffers(efx, 1, &xdpf, true); if (unlikely(err != 1)) { efx_free_rx_buffers(rx_queue, rx_buf, 1); -- 2.34.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() 2025-07-23 0:32 [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() Chenyuan Yang @ 2025-07-24 9:57 ` Paolo Abeni 2025-07-25 10:11 ` Edward Cree 0 siblings, 1 reply; 8+ messages in thread From: Paolo Abeni @ 2025-07-24 9:57 UTC (permalink / raw) To: Chenyuan Yang, ecree.xilinx, andrew+netdev, davem, edumazet, kuba, ast, daniel, hawk, john.fastabend, sdf, lorenzo Cc: netdev, linux-net-drivers, bpf, zzjas98 On 7/23/25 2:32 AM, Chenyuan Yang wrote: > The xdp_convert_buff_to_frame() function can return NULL when there is > insufficient headroom in the buffer to store the xdp_frame structure > or when the driver didn't reserve enough tailroom for skb_shared_info. AFAIC the sfc driver reserves both enough headroom and tailroom, but this is after ebpf run, which in turn could consume enough headroom to cause a failure, so I think this makes sense. @Eduard: could you please have a look? Thanks, Paolo ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() 2025-07-24 9:57 ` Paolo Abeni @ 2025-07-25 10:11 ` Edward Cree 2025-07-25 12:38 ` Kunwu Chan 2025-07-31 9:14 ` Jesper Dangaard Brouer 0 siblings, 2 replies; 8+ messages in thread From: Edward Cree @ 2025-07-25 10:11 UTC (permalink / raw) To: Paolo Abeni, Chenyuan Yang, ecree.xilinx, andrew+netdev, davem, edumazet, kuba, ast, daniel, hawk, john.fastabend, sdf, lorenzo Cc: netdev, linux-net-drivers, bpf, zzjas98 On 7/24/25 10:57, Paolo Abeni wrote: > On 7/23/25 2:32 AM, Chenyuan Yang wrote: >> The xdp_convert_buff_to_frame() function can return NULL when there is >> insufficient headroom in the buffer to store the xdp_frame structure >> or when the driver didn't reserve enough tailroom for skb_shared_info. > > AFAIC the sfc driver reserves both enough headroom and tailroom, but > this is after ebpf run, which in turn could consume enough headroom to > cause a failure, so I think this makes sense. Your reasoning seems plausible to me. However, I think the error path ought to more closely follow the existing error cases in logging a ratelimited message and calling the tracepoint. I think the cleanest way to do this would be: if (unlikely(!xdpf)) err = -ENOBUFS; else err = efx_xdp_tx_buffers(efx, 1, &xdpf, true); so that it can make use of the existing failure path. Adding the check to efx_xdp_tx_buffers() is also an option. -ed ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() 2025-07-25 10:11 ` Edward Cree @ 2025-07-25 12:38 ` Kunwu Chan 2025-07-26 19:56 ` Chenyuan Yang 2025-07-28 14:28 ` Edward Cree 2025-07-31 9:14 ` Jesper Dangaard Brouer 1 sibling, 2 replies; 8+ messages in thread From: Kunwu Chan @ 2025-07-25 12:38 UTC (permalink / raw) To: Edward Cree, Paolo Abeni, Chenyuan Yang, ecree.xilinx, andrew+netdev, davem, edumazet, kuba, ast, daniel, hawk, john.fastabend, sdf, lorenzo Cc: netdev, linux-net-drivers, bpf, zzjas98 On 2025/7/25 18:11, Edward Cree wrote: > On 7/24/25 10:57, Paolo Abeni wrote: >> On 7/23/25 2:32 AM, Chenyuan Yang wrote: >>> The xdp_convert_buff_to_frame() function can return NULL when there is >>> insufficient headroom in the buffer to store the xdp_frame structure >>> or when the driver didn't reserve enough tailroom for skb_shared_info. >> AFAIC the sfc driver reserves both enough headroom and tailroom, but >> this is after ebpf run, which in turn could consume enough headroom to >> cause a failure, so I think this makes sense. > Your reasoning seems plausible to me. > However, I think the error path ought to more closely follow the existing > error cases in logging a ratelimited message and calling the tracepoint. > I think the cleanest way to do this would be: > if (unlikely(!xdpf)) > err = -ENOBUFS; > else > err = efx_xdp_tx_buffers(efx, 1, &xdpf, true); > so that it can make use of the existing failure path. > Adding the check to efx_xdp_tx_buffers() is also an option. > > -ed > Hi Chenyuan, THX for addressing this edge case. I concur with Edward's suggestion to integrate this with the existing error handling flow. This will ensure: Consistent observability (ratelimited logs + tracepoints) Centralized resource cleanup Clear error type differentiation via -ENOBUFS Proposed refinement: diff case XDP_TX: /* Buffer ownership passes to tx on success. */ xdpf = xdp_convert_buff_to_frame(&xdp); + if (unlikely(!xdpf)) { + err = -ENOBUFS; + } else { + err = efx_siena_xdp_tx_buffers(efx, 1, &xdpf, true); + } - err = efx_siena_xdp_tx_buffers(efx, 1, &xdpf, true); if (unlikely(err != 1)) { efx_siena_free_rx_buffers(rx_queue, rx_buf, 1); if (net_ratelimit()) netif_err(efx, rx_err, efx->net_dev, - "XDP TX failed (%d)\n", err); + "XDP TX failed (%d)%s\n", err, + err == -ENOBUFS ? " [frame conversion]" : ""); channel->n_rx_xdp_bad_drops++; - trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); + if (err != -ENOBUFS) + trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); } else { channel->n_rx_xdp_tx++; } break; -- Thanks, TAO. --- “Life finds a way.” ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() 2025-07-25 12:38 ` Kunwu Chan @ 2025-07-26 19:56 ` Chenyuan Yang 2025-07-28 14:28 ` Edward Cree 1 sibling, 0 replies; 8+ messages in thread From: Chenyuan Yang @ 2025-07-26 19:56 UTC (permalink / raw) To: Kunwu Chan Cc: Edward Cree, Paolo Abeni, ecree.xilinx, andrew+netdev, davem, edumazet, kuba, ast, daniel, hawk, john.fastabend, sdf, lorenzo, netdev, linux-net-drivers, bpf, zzjas98 Thanks so much for your suggestion! I just submitted the v2 based on your comments for this issue :) On Fri, Jul 25, 2025 at 5:39 AM Kunwu Chan <kunwu.chan@linux.dev> wrote: > > On 2025/7/25 18:11, Edward Cree wrote: > > On 7/24/25 10:57, Paolo Abeni wrote: > >> On 7/23/25 2:32 AM, Chenyuan Yang wrote: > >>> The xdp_convert_buff_to_frame() function can return NULL when there is > >>> insufficient headroom in the buffer to store the xdp_frame structure > >>> or when the driver didn't reserve enough tailroom for skb_shared_info. > >> AFAIC the sfc driver reserves both enough headroom and tailroom, but > >> this is after ebpf run, which in turn could consume enough headroom to > >> cause a failure, so I think this makes sense. > > Your reasoning seems plausible to me. > > However, I think the error path ought to more closely follow the existing > > error cases in logging a ratelimited message and calling the tracepoint. > > I think the cleanest way to do this would be: > > if (unlikely(!xdpf)) > > err = -ENOBUFS; > > else > > err = efx_xdp_tx_buffers(efx, 1, &xdpf, true); > > so that it can make use of the existing failure path. > > Adding the check to efx_xdp_tx_buffers() is also an option. > > > > -ed > > > Hi Chenyuan, > > THX for addressing this edge case. I concur with Edward's suggestion to > integrate this with the existing error handling flow. This will ensure: > Consistent observability (ratelimited logs + tracepoints) > Centralized resource cleanup > Clear error type differentiation via -ENOBUFS > > Proposed refinement: > > diff > case XDP_TX: > /* Buffer ownership passes to tx on success. */ > xdpf = xdp_convert_buff_to_frame(&xdp); > + if (unlikely(!xdpf)) { > + err = -ENOBUFS; > + } else { > + err = efx_siena_xdp_tx_buffers(efx, 1, &xdpf, true); > + } > > - err = efx_siena_xdp_tx_buffers(efx, 1, &xdpf, true); > if (unlikely(err != 1)) { > efx_siena_free_rx_buffers(rx_queue, rx_buf, 1); > if (net_ratelimit()) > netif_err(efx, rx_err, efx->net_dev, > - "XDP TX failed (%d)\n", err); > + "XDP TX failed (%d)%s\n", err, > + err == -ENOBUFS ? " [frame conversion]" : ""); > channel->n_rx_xdp_bad_drops++; > - trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); > + if (err != -ENOBUFS) > + trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); > } else { > channel->n_rx_xdp_tx++; > } > break; > > > -- Thanks, TAO. --- “Life finds a way.” ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() 2025-07-25 12:38 ` Kunwu Chan 2025-07-26 19:56 ` Chenyuan Yang @ 2025-07-28 14:28 ` Edward Cree 2025-07-30 7:38 ` Kunwu Chan 1 sibling, 1 reply; 8+ messages in thread From: Edward Cree @ 2025-07-28 14:28 UTC (permalink / raw) To: Kunwu Chan, Edward Cree, Paolo Abeni, Chenyuan Yang, andrew+netdev, davem, edumazet, kuba, ast, daniel, hawk, john.fastabend, sdf, lorenzo Cc: netdev, linux-net-drivers, bpf, zzjas98 On 25/07/2025 13:38, Kunwu Chan wrote: > Proposed refinement: ... > if (net_ratelimit()) > netif_err(efx, rx_err, efx->net_dev, > - "XDP TX failed (%d)\n", err); > + "XDP TX failed (%d)%s\n", err, > + err == -ENOBUFS ? " [frame conversion]" : ""); Unnecessary, since efx_xdp_tx_buffers() never returns ENOBUFS. > channel->n_rx_xdp_bad_drops++; > - trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); > + if (err != -ENOBUFS) > + trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); Why prevent the tracepoint in this case?? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() 2025-07-28 14:28 ` Edward Cree @ 2025-07-30 7:38 ` Kunwu Chan 0 siblings, 0 replies; 8+ messages in thread From: Kunwu Chan @ 2025-07-30 7:38 UTC (permalink / raw) To: Edward Cree, Edward Cree, Paolo Abeni, Chenyuan Yang, andrew+netdev, davem, edumazet, kuba, ast, daniel, hawk, john.fastabend, sdf, lorenzo Cc: netdev, linux-net-drivers, bpf, zzjas98 On 2025/7/28 22:28, Edward Cree wrote: > On 25/07/2025 13:38, Kunwu Chan wrote: >> Proposed refinement: > ... >> if (net_ratelimit()) >> netif_err(efx, rx_err, efx->net_dev, >> - "XDP TX failed (%d)\n", err); >> + "XDP TX failed (%d)%s\n", err, >> + err == -ENOBUFS ? " [frame conversion]" : ""); > Unnecessary, since efx_xdp_tx_buffers() never returns ENOBUFS. You're correct that efx_siena_xdp_tx_buffers() never returns -ENOBUFS, and xdp_convert_buff_to_frame() returns NULL on failure. Whether we need a log to distinguish where the errors come from? + if (unlikely(!xdpf)) + err = -ENOBUFS; + else + err = efx_xdp_tx_buffers(efx, 1, &xdpf, true); - err = efx_siena_xdp_tx_buffers(efx, 1, &xdpf, true); if (unlikely(err != 1)) { efx_siena_free_rx_buffers(rx_queue, rx_buf, 1); if (net_ratelimit()) netif_err(efx, rx_err, efx->net_dev, - "XDP TX failed (%d)\n", err); + "XDP TX failed (%d)%s\n", err, + err == -ENOBUFS ? " [xdp_convert_buff_to_frame]" : "efx_siena_xdp_tx_buffers"); Just a personal thought. > >> channel->n_rx_xdp_bad_drops++; >> - trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); >> + if (err != -ENOBUFS) >> + trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); > Why prevent the tracepoint in this case?? You're correct, my mistake. -- Thanks, TAO. --- “Life finds a way.” ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() 2025-07-25 10:11 ` Edward Cree 2025-07-25 12:38 ` Kunwu Chan @ 2025-07-31 9:14 ` Jesper Dangaard Brouer 1 sibling, 0 replies; 8+ messages in thread From: Jesper Dangaard Brouer @ 2025-07-31 9:14 UTC (permalink / raw) To: Edward Cree, Paolo Abeni, Chenyuan Yang, ecree.xilinx, andrew+netdev, davem, edumazet, kuba, ast, daniel, john.fastabend, sdf, lorenzo Cc: netdev, linux-net-drivers, bpf, zzjas98 On 25/07/2025 12.11, Edward Cree wrote: > On 7/24/25 10:57, Paolo Abeni wrote: >> On 7/23/25 2:32 AM, Chenyuan Yang wrote: >>> The xdp_convert_buff_to_frame() function can return NULL when there is >>> insufficient headroom in the buffer to store the xdp_frame structure >>> or when the driver didn't reserve enough tailroom for skb_shared_info. >> >> AFAIC the sfc driver reserves both enough headroom and tailroom, but >> this is after ebpf run, which in turn could consume enough headroom to >> cause a failure, so I think this makes sense. > > Your reasoning seems plausible to me. Hmm... have you actually tested that XDP/BPF can adjust headroom so much that xdp_convert_buff_to_frame() function fails? I really doubt this possible for BPF-progs to violate this. The XDP BPF-prog can only adjust the headroom via the helpers bpf_xdp_adjust_head() and bpf_xdp_adjust_meta(). These helpers reserve room for sizeof(struct xdp_frame). The tailroom can be adjusted via helper bpf_xdp_adjust_tail() and it also reserve room for sizeof(struct skb_shared_info) such that BPF-progs cannot get access to this area. See define for xdp_data_hard_end. --Jesper ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-07-31 9:14 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-07-23 0:32 [PATCH] sfc: handle NULL returned by xdp_convert_buff_to_frame() Chenyuan Yang 2025-07-24 9:57 ` Paolo Abeni 2025-07-25 10:11 ` Edward Cree 2025-07-25 12:38 ` Kunwu Chan 2025-07-26 19:56 ` Chenyuan Yang 2025-07-28 14:28 ` Edward Cree 2025-07-30 7:38 ` Kunwu Chan 2025-07-31 9:14 ` Jesper Dangaard Brouer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).