Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions net/core/skmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1146,14 +1146,30 @@ static int sk_psock_strp_parse(struct strparser *strp, struct sk_buff *skb)
struct bpf_prog *prog;
int ret = skb->len;

rcu_read_lock();
guard(rcu)();
prog = READ_ONCE(psock->progs.stream_parser);
if (likely(prog)) {
skb->sk = psock->sk;
ret = bpf_prog_run_pin_on_cpu(prog, skb);
skb->sk = NULL;
struct sk_buff *parse_skb = skb;

/*
* strparser chains the message skbs through skb->frag_list and
* keeps a pointer into that list in strp->skb_nextp. The parser
* program may call bpf_skb_change_tail() and friends, which go
* through __pskb_pull_tail() and free the frag_list skbs that
* strparser still tracks. Run the program on a clone when a
* frag_list is present so it cannot drop frags strparser owns.
*/
if (skb_has_frag_list(skb)) {
parse_skb = skb_clone(skb, GFP_ATOMIC);
if (!parse_skb)
return -ENOMEM;
}
parse_skb->sk = psock->sk;
ret = bpf_prog_run_pin_on_cpu(prog, parse_skb);
parse_skb->sk = NULL;
if (parse_skb != skb)
kfree_skb(parse_skb);
}
rcu_read_unlock();
return ret;
}

Expand Down
Loading