Re: [PATCH net 3/6] xsk: clear metadata pointer when no timestamp is requested
Stanislav Fomichev <[email protected]> Wed, 29 Jul 2026 09:03:51 -0700
| Newsgroups | dev.linux.lists.sashiko-reviews,org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
On 07/28, [email protected] wrote: > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > > Pre-existing issues: > - [High] Integer overflow in `xsk_skb_metadata` when calculating `skb->csum_start`, leading to a potential kernel warning and panic (DoS). > -- > > --- Patch [3]: [PATCH net 3/6] xsk: clear metadata pointer when no timestamp is requested --- > commit 814027e56069dbb5716ac5b9f7f38aebab332dd6 > Author: Stanislav Fomichev <[email protected]> > > xsk: clear metadata pointer when no timestamp is requested > > User space can change metadata flags after request processing. Rereading > them during completion can therefore make the kernel write a timestamp > that was not requested when the packet was submitted. Clear the metadata > pointer during request processing unless timestamp completion is requested. > > > diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c > > --- a/net/xdp/xsk.c > > +++ b/net/xdp/xsk.c > > [ ... ] > > > @@ -998,6 +998,8 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer, > > > > if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME) > > skb->skb_mstamp_ns = meta->request.launch_time; > > [Severity: High] > This is a pre-existing issue, but can the checksum offset calculation > earlier in this function cause an integer overflow? > > When handling XDP_TXMD_FLAGS_CHECKSUM, the code does: > > skb->csum_start = hr + csum_start; > > On architectures with 64KB pages, csum_start can be large enough that > adding hr wraps the u16 skb->csum_start. This would result in > skb->csum_start being smaller than the headroom. > > If pool->tx_sw_csum is true, this then calls skb_checksum_help(). Inside > skb_checksum_help(), the offset is calculated by subtracting headroom from > skb->csum_start, which yields a negative integer due to the wrap-around. > > When this negative offset is compared against skb_headlen() (which is > unsigned), it is implicitly cast to a huge unsigned value: > > net/core/dev.c:skb_checksum_help() { > ... > offset = skb_checksum_start_offset(skb); > ... > if (unlikely(offset >= skb_headlen(skb))) { > DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false); > WARN_ONCE(true, "offset (%d) >= skb_headlen() (%u)\n", ...); > ... > } > > Could this allow an unprivileged user to trigger a kernel warning and > potentially panic the system if panic_on_warn is set? I guess.. We can do a similar size check before calling skb_checksum_help to avoid WARN_ONCE.