Message ID | 20211008204604.38014-1-xiyou.wangcong@gmail.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | BPF |
Headers | show |
Series | [bpf] udp: validate checksum in udp_read_sock() | expand |
Cong Wang wrote: > From: Cong Wang <cong.wang@bytedance.com> > > It turns out the skb's in sock receive queue could have > bad checksums, as both ->poll() and ->recvmsg() validate > checksums. We have to do the same for ->read_sock() path > too before they are redirected in sockmap. > > Fixes: d7f571188ecf ("udp: Implement ->read_sock() for sockmap") > Reported-by: Daniel Borkmann <daniel@iogearbox.net> > Reported-by: John Fastabend <john.fastabend@gmail.com> > Cc: Lorenz Bauer <lmb@cloudflare.com> > Cc: Jakub Sitnicki <jakub@cloudflare.com> > Signed-off-by: Cong Wang <cong.wang@bytedance.com> > --- > net/ipv4/udp.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c > index 8536b2a7210b..0ae8ab5e05b4 100644 > --- a/net/ipv4/udp.c > +++ b/net/ipv4/udp.c > @@ -1808,6 +1808,17 @@ int udp_read_sock(struct sock *sk, read_descriptor_t *desc, > skb = skb_recv_udp(sk, 0, 1, &err); > if (!skb) > return err; > + > + if (udp_lib_checksum_complete(skb)) { > + __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, > + IS_UDPLITE(sk)); > + __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, > + IS_UDPLITE(sk)); > + atomic_inc(&sk->sk_drops); > + kfree_skb(skb); We could use sock_drop() here? Otherwise looks good thanks. > + continue; > + } > + > used = recv_actor(desc, skb, 0, skb->len); > if (used <= 0) { > if (!copied) > -- > 2.30.2 >
On Mon, Oct 11, 2021 at 10:06 PM John Fastabend <john.fastabend@gmail.com> wrote: > > Cong Wang wrote: > > From: Cong Wang <cong.wang@bytedance.com> > > > > It turns out the skb's in sock receive queue could have > > bad checksums, as both ->poll() and ->recvmsg() validate > > checksums. We have to do the same for ->read_sock() path > > too before they are redirected in sockmap. > > > > Fixes: d7f571188ecf ("udp: Implement ->read_sock() for sockmap") > > Reported-by: Daniel Borkmann <daniel@iogearbox.net> > > Reported-by: John Fastabend <john.fastabend@gmail.com> > > Cc: Lorenz Bauer <lmb@cloudflare.com> > > Cc: Jakub Sitnicki <jakub@cloudflare.com> > > Signed-off-by: Cong Wang <cong.wang@bytedance.com> > > --- > > net/ipv4/udp.c | 11 +++++++++++ > > 1 file changed, 11 insertions(+) > > > > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c > > index 8536b2a7210b..0ae8ab5e05b4 100644 > > --- a/net/ipv4/udp.c > > +++ b/net/ipv4/udp.c > > @@ -1808,6 +1808,17 @@ int udp_read_sock(struct sock *sk, read_descriptor_t *desc, > > skb = skb_recv_udp(sk, 0, 1, &err); > > if (!skb) > > return err; > > + > > + if (udp_lib_checksum_complete(skb)) { > > + __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, > > + IS_UDPLITE(sk)); > > + __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, > > + IS_UDPLITE(sk)); > > + atomic_inc(&sk->sk_drops); > > + kfree_skb(skb); > > We could use sock_drop() here? Otherwise looks good thanks. sock_drop() is in include/linux/skmsg.h, I think we need to move it to sock.h before using it here in net/ipv4/udp.c, right? And there are other similar patterns which can be replaced with sock_drop(), so we can do the replacement for all in a separate patch. Thanks.
Cong Wang wrote: > On Mon, Oct 11, 2021 at 10:06 PM John Fastabend > <john.fastabend@gmail.com> wrote: > > > > Cong Wang wrote: > > > From: Cong Wang <cong.wang@bytedance.com> > > > > > > It turns out the skb's in sock receive queue could have > > > bad checksums, as both ->poll() and ->recvmsg() validate > > > checksums. We have to do the same for ->read_sock() path > > > too before they are redirected in sockmap. > > > > > > Fixes: d7f571188ecf ("udp: Implement ->read_sock() for sockmap") > > > Reported-by: Daniel Borkmann <daniel@iogearbox.net> > > > Reported-by: John Fastabend <john.fastabend@gmail.com> > > > Cc: Lorenz Bauer <lmb@cloudflare.com> > > > Cc: Jakub Sitnicki <jakub@cloudflare.com> > > > Signed-off-by: Cong Wang <cong.wang@bytedance.com> > > > --- > > > net/ipv4/udp.c | 11 +++++++++++ > > > 1 file changed, 11 insertions(+) > > > > > > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c > > > index 8536b2a7210b..0ae8ab5e05b4 100644 > > > --- a/net/ipv4/udp.c > > > +++ b/net/ipv4/udp.c > > > @@ -1808,6 +1808,17 @@ int udp_read_sock(struct sock *sk, read_descriptor_t *desc, > > > skb = skb_recv_udp(sk, 0, 1, &err); > > > if (!skb) > > > return err; > > > + > > > + if (udp_lib_checksum_complete(skb)) { > > > + __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, > > > + IS_UDPLITE(sk)); > > > + __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, > > > + IS_UDPLITE(sk)); > > > + atomic_inc(&sk->sk_drops); > > > + kfree_skb(skb); > > > > We could use sock_drop() here? Otherwise looks good thanks. > > sock_drop() is in include/linux/skmsg.h, I think we need to move it > to sock.h before using it here in net/ipv4/udp.c, right? Yes it would be necessary. Lets not do it here otherwise backports will be ugly. Acked-by: John Fastabend <john.fastabend@gmail.com> > > And there are other similar patterns which can be replaced with > sock_drop(), so we can do the replacement for all in a separate > patch. > > Thanks.
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 8536b2a7210b..0ae8ab5e05b4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1808,6 +1808,17 @@ int udp_read_sock(struct sock *sk, read_descriptor_t *desc, skb = skb_recv_udp(sk, 0, 1, &err); if (!skb) return err; + + if (udp_lib_checksum_complete(skb)) { + __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, + IS_UDPLITE(sk)); + __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, + IS_UDPLITE(sk)); + atomic_inc(&sk->sk_drops); + kfree_skb(skb); + continue; + } + used = recv_actor(desc, skb, 0, skb->len); if (used <= 0) { if (!copied)