On Mon, 25 Aug 2025 12:39:14 -0700 Amery Hung wrote: > +__bpf_kfunc int bpf_xdp_pull_data(struct xdp_md *x, u32 len, u64 flags) > +{ > + struct xdp_buff *xdp = (struct xdp_buff *)x; > + struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); > + void *data_end, *data_hard_end = xdp_data_hard_end(xdp); > + int i, delta, buff_len, n_frags_free = 0, len_free = 0; > + > + buff_len = xdp_get_buff_len(xdp); > + > + if (unlikely(len > buff_len)) > + return -EINVAL; > + > + if (!len) > + len = xdp_get_buff_len(xdp); > + > + data_end = xdp->data + len; > + delta = data_end - xdp->data_end; > + > + if (delta <= 0) > + return 0; > + > + if (unlikely(data_end > data_hard_end)) > + return -EINVAL; Is this safe against pointers wrapping on 32b systems? Maybe it's better to do: if (unlikely(data_hard_end - xdp->data_end < delta)) ? > + for (i = 0; i < sinfo->nr_frags && delta; i++) { > + skb_frag_t *frag = &sinfo->frags[i]; > + u32 shrink = min_t(u32, delta, skb_frag_size(frag)); > + > + memcpy(xdp->data_end + len_free, skb_frag_address(frag), shrink); > + > + len_free += shrink; > + delta -= shrink; > + if (bpf_xdp_shrink_data(xdp, frag, shrink, false)) > + n_frags_free++; possibly else break; and then you don't have to check delta in the for loop condition? > + } > + > + for (i = 0; i < sinfo->nr_frags - n_frags_free; i++) { > + memcpy(&sinfo->frags[i], &sinfo->frags[i + n_frags_free], > + sizeof(skb_frag_t)); This feels like it'd really want to be a memmove(), no? > + } > + > + sinfo->nr_frags -= n_frags_free; > + sinfo->xdp_frags_size -= len_free; > + xdp->data_end = data_end; > + > + if (unlikely(!sinfo->nr_frags)) > + xdp_buff_clear_frags_flag(xdp); > + > + return 0; > +}