| From foo@baz Thu Dec 8 07:19:12 CET 2016 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Tue, 22 Nov 2016 09:06:45 -0800 |
| Subject: udplite: call proper backlog handlers |
| |
| From: Eric Dumazet <edumazet@google.com> |
| |
| |
| [ Upstream commit 30c7be26fd3587abcb69587f781098e3ca2d565b ] |
| |
| In commits 93821778def10 ("udp: Fix rcv socket locking") and |
| f7ad74fef3af ("net/ipv6/udp: UDP encapsulation: break backlog_rcv into |
| __udpv6_queue_rcv_skb") UDP backlog handlers were renamed, but UDPlite |
| was forgotten. |
| |
| This leads to crashes if UDPlite header is pulled twice, which happens |
| starting from commit e6afc8ace6dd ("udp: remove headers from UDP packets |
| before queueing") |
| |
| Bug found by syzkaller team, thanks a lot guys ! |
| |
| Note that backlog use in UDP/UDPlite is scheduled to be removed starting |
| from linux-4.10, so this patch is only needed up to linux-4.9 |
| |
| Fixes: 93821778def1 ("udp: Fix rcv socket locking") |
| Fixes: f7ad74fef3af ("net/ipv6/udp: UDP encapsulation: break backlog_rcv into __udpv6_queue_rcv_skb") |
| Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Reported-by: Andrey Konovalov <andreyknvl@google.com> |
| Cc: Benjamin LaHaise <bcrl@kvack.org> |
| Cc: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv4/udp.c | 2 +- |
| net/ipv4/udp_impl.h | 2 +- |
| net/ipv4/udplite.c | 2 +- |
| net/ipv6/udp.c | 2 +- |
| net/ipv6/udp_impl.h | 2 +- |
| net/ipv6/udplite.c | 2 +- |
| 6 files changed, 6 insertions(+), 6 deletions(-) |
| |
| --- a/net/ipv4/udp.c |
| +++ b/net/ipv4/udp.c |
| @@ -1451,7 +1451,7 @@ static void udp_v4_rehash(struct sock *s |
| udp_lib_rehash(sk, new_hash); |
| } |
| |
| -static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| +int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| { |
| int rc; |
| |
| --- a/net/ipv4/udp_impl.h |
| +++ b/net/ipv4/udp_impl.h |
| @@ -25,7 +25,7 @@ int udp_recvmsg(struct sock *sk, struct |
| int flags, int *addr_len); |
| int udp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, |
| int flags); |
| -int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); |
| +int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); |
| void udp_destroy_sock(struct sock *sk); |
| |
| #ifdef CONFIG_PROC_FS |
| --- a/net/ipv4/udplite.c |
| +++ b/net/ipv4/udplite.c |
| @@ -50,7 +50,7 @@ struct proto udplite_prot = { |
| .sendmsg = udp_sendmsg, |
| .recvmsg = udp_recvmsg, |
| .sendpage = udp_sendpage, |
| - .backlog_rcv = udp_queue_rcv_skb, |
| + .backlog_rcv = __udp_queue_rcv_skb, |
| .hash = udp_lib_hash, |
| .unhash = udp_lib_unhash, |
| .get_port = udp_v4_get_port, |
| --- a/net/ipv6/udp.c |
| +++ b/net/ipv6/udp.c |
| @@ -514,7 +514,7 @@ out: |
| return; |
| } |
| |
| -static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| +int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| { |
| int rc; |
| |
| --- a/net/ipv6/udp_impl.h |
| +++ b/net/ipv6/udp_impl.h |
| @@ -26,7 +26,7 @@ int compat_udpv6_getsockopt(struct sock |
| int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len); |
| int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, |
| int flags, int *addr_len); |
| -int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); |
| +int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); |
| void udpv6_destroy_sock(struct sock *sk); |
| |
| void udp_v6_clear_sk(struct sock *sk, int size); |
| --- a/net/ipv6/udplite.c |
| +++ b/net/ipv6/udplite.c |
| @@ -45,7 +45,7 @@ struct proto udplitev6_prot = { |
| .getsockopt = udpv6_getsockopt, |
| .sendmsg = udpv6_sendmsg, |
| .recvmsg = udpv6_recvmsg, |
| - .backlog_rcv = udpv6_queue_rcv_skb, |
| + .backlog_rcv = __udpv6_queue_rcv_skb, |
| .hash = udp_lib_hash, |
| .unhash = udp_lib_unhash, |
| .get_port = udp_v6_get_port, |