]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Add bpf_prog_run_data_pointers()
authorEric Dumazet <edumazet@google.com>
Wed, 12 Nov 2025 12:55:16 +0000 (12:55 +0000)
committerMartin KaFai Lau <martin.lau@kernel.org>
Fri, 14 Nov 2025 16:56:49 +0000 (08:56 -0800)
syzbot found that cls_bpf_classify() is able to change
tc_skb_cb(skb)->drop_reason triggering a warning in sk_skb_reason_drop().

WARNING: CPU: 0 PID: 5965 at net/core/skbuff.c:1192 __sk_skb_reason_drop net/core/skbuff.c:1189 [inline]
WARNING: CPU: 0 PID: 5965 at net/core/skbuff.c:1192 sk_skb_reason_drop+0x76/0x170 net/core/skbuff.c:1214

struct tc_skb_cb has been added in commit ec624fe740b4 ("net/sched:
Extend qdisc control block with tc control block"), which added a wrong
interaction with db58ba459202 ("bpf: wire in data and data_end for
cls_act_bpf").

drop_reason was added later.

Add bpf_prog_run_data_pointers() helper to save/restore the net_sched
storage colliding with BPF data_meta/data_end.

Fixes: ec624fe740b4 ("net/sched: Extend qdisc control block with tc control block")
Reported-by: syzbot <syzkaller@googlegroups.com>
Closes: https://lore.kernel.org/netdev/6913437c.a70a0220.22f260.013b.GAE@google.com/
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Reviewed-by: Victor Nogueira <victor@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20251112125516.1563021-1-edumazet@google.com
include/linux/filter.h
net/sched/act_bpf.c
net/sched/cls_bpf.c

index f5c859b8131a3e5fa5111b60cc291cedd44f096d..973233b82dc1fd422f26ac221eeb46c66c47767a 100644 (file)
@@ -901,6 +901,26 @@ static inline void bpf_compute_data_pointers(struct sk_buff *skb)
        cb->data_end  = skb->data + skb_headlen(skb);
 }
 
+static inline int bpf_prog_run_data_pointers(
+       const struct bpf_prog *prog,
+       struct sk_buff *skb)
+{
+       struct bpf_skb_data_end *cb = (struct bpf_skb_data_end *)skb->cb;
+       void *save_data_meta, *save_data_end;
+       int res;
+
+       save_data_meta = cb->data_meta;
+       save_data_end = cb->data_end;
+
+       bpf_compute_data_pointers(skb);
+       res = bpf_prog_run(prog, skb);
+
+       cb->data_meta = save_data_meta;
+       cb->data_end = save_data_end;
+
+       return res;
+}
+
 /* Similar to bpf_compute_data_pointers(), except that save orginal
  * data in cb->data and cb->meta_data for restore.
  */
index 396b576390d00aad56bca6a18b7796e5324c0aef..c2b5bc19e09118857d1ef3c4aed566b8225f2e9a 100644 (file)
@@ -47,12 +47,10 @@ TC_INDIRECT_SCOPE int tcf_bpf_act(struct sk_buff *skb,
        filter = rcu_dereference(prog->filter);
        if (at_ingress) {
                __skb_push(skb, skb->mac_len);
-               bpf_compute_data_pointers(skb);
-               filter_res = bpf_prog_run(filter, skb);
+               filter_res = bpf_prog_run_data_pointers(filter, skb);
                __skb_pull(skb, skb->mac_len);
        } else {
-               bpf_compute_data_pointers(skb);
-               filter_res = bpf_prog_run(filter, skb);
+               filter_res = bpf_prog_run_data_pointers(filter, skb);
        }
        if (unlikely(!skb->tstamp && skb->tstamp_type))
                skb->tstamp_type = SKB_CLOCK_REALTIME;
index 7fbe42f0e5c2b7aca0a28c34cd801c3a767c804e..a32754a2658bb7d21e8ceb62c67d6684ed4f9fcc 100644 (file)
@@ -97,12 +97,10 @@ TC_INDIRECT_SCOPE int cls_bpf_classify(struct sk_buff *skb,
                } else if (at_ingress) {
                        /* It is safe to push/pull even if skb_shared() */
                        __skb_push(skb, skb->mac_len);
-                       bpf_compute_data_pointers(skb);
-                       filter_res = bpf_prog_run(prog->filter, skb);
+                       filter_res = bpf_prog_run_data_pointers(prog->filter, skb);
                        __skb_pull(skb, skb->mac_len);
                } else {
-                       bpf_compute_data_pointers(skb);
-                       filter_res = bpf_prog_run(prog->filter, skb);
+                       filter_res = bpf_prog_run_data_pointers(prog->filter, skb);
                }
                if (unlikely(!skb->tstamp && skb->tstamp_type))
                        skb->tstamp_type = SKB_CLOCK_REALTIME;