Commit 4ef92743 authored by Eric Dumazet's avatar Eric Dumazet Committed by Martin KaFai Lau
Browse files

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 commit ec624fe7 ("net/sched:
Extend qdisc control block with tc control block"), which added a wrong
interaction with db58ba45 ("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: ec624fe7 ("net/sched: Extend qdisc control block with tc control block")
Reported-by: default avatarsyzbot <syzkaller@googlegroups.com>
Closes: https://lore.kernel.org/netdev/6913437c.a70a0220.22f260.013b.GAE@google.com/


Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
Reviewed-by: default avatarVictor Nogueira <victor@mojatatu.com>
Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20251112125516.1563021-1-edumazet@google.com
parent 91a78ce9
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -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.
 */
+2 −4
Original line number Diff line number Diff line
@@ -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;
+2 −4
Original line number Diff line number Diff line
@@ -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;