Skip to content

Commit 4fd5106

Browse files
edumazetKernel Patches Daemon
authored andcommitted
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 ec624fe ("net/sched: Extend qdisc control block with tc control block"), which added a wrong interaction with db58ba4 ("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: ec624fe ("net/sched: Extend qdisc control block with tc control block") Reported-by: syzbot <[email protected]> Closes: https://lore.kernel.org/netdev/[email protected]/ Signed-off-by: Eric Dumazet <[email protected]> Cc: Paul Blakey <[email protected]> Reviewed-by: Victor Nogueira <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]>
1 parent 4752827 commit 4fd5106

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

include/linux/filter.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,26 @@ static inline void bpf_compute_data_pointers(struct sk_buff *skb)
901901
cb->data_end = skb->data + skb_headlen(skb);
902902
}
903903

904+
static inline int bpf_prog_run_data_pointers(
905+
const struct bpf_prog *prog,
906+
struct sk_buff *skb)
907+
{
908+
struct bpf_skb_data_end *cb = (struct bpf_skb_data_end *)skb->cb;
909+
void *save_data_meta, *save_data_end;
910+
int res;
911+
912+
save_data_meta = cb->data_meta;
913+
save_data_end = cb->data_end;
914+
915+
bpf_compute_data_pointers(skb);
916+
res = bpf_prog_run(prog, skb);
917+
918+
cb->data_meta = save_data_meta;
919+
cb->data_end = save_data_end;
920+
921+
return res;
922+
}
923+
904924
/* Similar to bpf_compute_data_pointers(), except that save orginal
905925
* data in cb->data and cb->meta_data for restore.
906926
*/

net/sched/act_bpf.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,12 @@ TC_INDIRECT_SCOPE int tcf_bpf_act(struct sk_buff *skb,
4747
filter = rcu_dereference(prog->filter);
4848
if (at_ingress) {
4949
__skb_push(skb, skb->mac_len);
50-
bpf_compute_data_pointers(skb);
51-
filter_res = bpf_prog_run(filter, skb);
50+
filter_res = bpf_prog_run_data_pointers(filter, skb);
5251
__skb_pull(skb, skb->mac_len);
5352
} else {
54-
bpf_compute_data_pointers(skb);
55-
filter_res = bpf_prog_run(filter, skb);
53+
filter_res = bpf_prog_run_data_pointers(filter, skb);
5654
}
55+
5756
if (unlikely(!skb->tstamp && skb->tstamp_type))
5857
skb->tstamp_type = SKB_CLOCK_REALTIME;
5958
if (skb_sk_is_prefetched(skb) && filter_res != TC_ACT_OK)

net/sched/cls_bpf.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,10 @@ TC_INDIRECT_SCOPE int cls_bpf_classify(struct sk_buff *skb,
9797
} else if (at_ingress) {
9898
/* It is safe to push/pull even if skb_shared() */
9999
__skb_push(skb, skb->mac_len);
100-
bpf_compute_data_pointers(skb);
101-
filter_res = bpf_prog_run(prog->filter, skb);
100+
filter_res = bpf_prog_run_data_pointers(prog->filter, skb);
102101
__skb_pull(skb, skb->mac_len);
103102
} else {
104-
bpf_compute_data_pointers(skb);
105-
filter_res = bpf_prog_run(prog->filter, skb);
103+
filter_res = bpf_prog_run_data_pointers(prog->filter, skb);
106104
}
107105
if (unlikely(!skb->tstamp && skb->tstamp_type))
108106
skb->tstamp_type = SKB_CLOCK_REALTIME;

0 commit comments

Comments
 (0)