]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Reject fragmented frames in devmap
authorZhao Zhang <zzhan461@ucr.edu>
Tue, 2 Jun 2026 08:43:33 +0000 (16:43 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 5 Jun 2026 15:20:12 +0000 (08:20 -0700)
Devmap broadcast redirects clone the packet for all but the last
destination.

For native XDP, that clone path copies only the linear xdp_frame data,
while fragmented frames keep skb_shared_info in tailroom outside the
linear area. Cloning such a frame leaves XDP_FLAGS_HAS_FRAGS set but
without valid frag metadata, and the later free path can interpret
uninitialized tail data as skb_shared_info, leading to an out-of-bounds
access during frame return.

Reject fragmented native XDP frames in dev_map_enqueue_clone().

Add the same restriction to the generic XDP clone path in
dev_map_redirect_clone(). Generic XDP represents fragmented packets as
nonlinear skbs, and rejecting them here keeps clone-based broadcast
support aligned between native and generic XDP.

Fixes: e624d4ed4aa8 ("xdp: Extend xdp_redirect_map with broadcast support")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Zhao Zhang <zzhan461@ucr.edu>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/r/21c2d153dd25603d359069a02bf06779b51f6423.1780385378.git.zzhan461@ucr.edu
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/devmap.c

index cc0a43ebab6b994feb412b2c9915610c1eeb2957..5b9eac5342a90d348c568db6803313288fe748b4 100644 (file)
@@ -581,6 +581,10 @@ static int dev_map_enqueue_clone(struct bpf_dtab_netdev *obj,
 {
        struct xdp_frame *nxdpf;
 
+       /* Frags live outside the linear frame and cannot be cloned safely. */
+       if (unlikely(xdp_frame_has_frags(xdpf)))
+               return -EOPNOTSUPP;
+
        nxdpf = xdpf_clone(xdpf);
        if (!nxdpf)
                return -ENOMEM;
@@ -726,6 +730,9 @@ static int dev_map_redirect_clone(struct bpf_dtab_netdev *dst,
        struct sk_buff *nskb;
        int err;
 
+       if (unlikely(skb_is_nonlinear(skb)))
+               return -EOPNOTSUPP;
+
        nskb = skb_clone(skb, GFP_ATOMIC);
        if (!nskb)
                return -ENOMEM;