mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
bpf: Add bpf_prog_run_data_pointers()
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 commitec624fe740("net/sched: Extend qdisc control block with tc control block"), which added a wrong interaction withdb58ba4592("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:ec624fe740("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
This commit is contained in:
committed by
Martin KaFai Lau
parent
91a78ce994
commit
4ef9274362
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user