aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorGravatar Cong Wang <cong.wang@bytedance.com> 2022-06-15 09:20:13 -0700
committerGravatar Daniel Borkmann <daniel@iogearbox.net> 2022-06-20 14:05:52 +0200
commit57452d767feaeab405de3bff0d240c3ac84bfe0d (patch)
tree3462cefaa340f3d51248adfee7feb7bedf879b19 /net
parentnet: Introduce a new proto_ops ->read_skb() (diff)
downloadlinux-57452d767feaeab405de3bff0d240c3ac84bfe0d.tar.gz
linux-57452d767feaeab405de3bff0d240c3ac84bfe0d.tar.bz2
linux-57452d767feaeab405de3bff0d240c3ac84bfe0d.zip
skmsg: Get rid of skb_clone()
With ->read_skb() now we have an entire skb dequeued from receive queue, now we just need to grab an addtional refcnt before passing its ownership to recv actors. And we should not touch them any more, particularly for skb->sk. Fortunately, skb->sk is already set for most of the protocols except UDP where skb->sk has been stolen, so we have to fix it up for UDP case. Signed-off-by: Cong Wang <cong.wang@bytedance.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20220615162014.89193-4-xiyou.wangcong@gmail.com
Diffstat (limited to 'net')
-rw-r--r--net/core/skmsg.c7
-rw-r--r--net/ipv4/udp.c1
2 files changed, 2 insertions, 6 deletions
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index f7f63b7d990c..8b248d289c11 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -1167,10 +1167,7 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)
int ret = __SK_DROP;
int len = skb->len;
- /* clone here so sk_eat_skb() in tcp_read_sock does not drop our data */
- skb = skb_clone(skb, GFP_ATOMIC);
- if (!skb)
- return 0;
+ skb_get(skb);
rcu_read_lock();
psock = sk_psock(sk);
@@ -1183,12 +1180,10 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)
if (!prog)
prog = READ_ONCE(psock->progs.skb_verdict);
if (likely(prog)) {
- skb->sk = sk;
skb_dst_drop(skb);
skb_bpf_redirect_clear(skb);
ret = bpf_prog_run_pin_on_cpu(prog, skb);
ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb));
- skb->sk = NULL;
}
if (sk_psock_verdict_apply(psock, skb, ret) < 0)
len = 0;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index c660b0bc4d14..2516078aa03e 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1819,6 +1819,7 @@ int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
continue;
}
+ WARN_ON(!skb_set_owner_sk_safe(skb, sk));
used = recv_actor(sk, skb);
if (used <= 0) {
if (!copied)