[net] udp: exclude UDP_ENCAP_RXRPC packets from early demux

Vadim Fedorenko vfedorenko at novek.ru
Fri Jan 29 09:25:03 EST 2021


While adding the early demux for udp sockets rxrpc were not
changed to deal with sk_rx_dst cache. That leads to leaking early
demux cache dst reference. But adding dst_release to destructor of
rxrpc doesn't help in situation of destroying namespace. This is
because rxrpc does not register any netdevices per namespace.
Assigned sk->sk_rx_dst holds the reference to netdevice preventing
successful freeing of netdevices in namespace and moving forward to
subsystem freeing. This is dead lock situation.

Removing rxrpc sockets from early demux util the solution in rxrpc
subsystem is made.

Fixes: 421b3885bf6d (udp: ipv4: Add udp early demux)
Reported-by: syzbot+90a3766590adf905974e at syzkaller.appspotmail.com
Signed-off-by: Vadim Fedorenko <vfedorenko at novek.ru>
---
 net/ipv4/udp.c | 6 +++++-
 net/ipv6/udp.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 69ea765..a218edc 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2486,8 +2486,12 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
 
 	udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
 		if (INET_MATCH(sk, net, acookie, rmt_addr,
-			       loc_addr, ports, dif, sdif))
+			       loc_addr, ports, dif, sdif)) {
+			if (unlikely(udp_sk(sk)->encap_type == UDP_ENCAP_RXRPC))
+				continue;
+
 			return sk;
+		}
 		/* Only check first socket in chain */
 		break;
 	}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b9f3dfd..2e9b114 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1020,8 +1020,12 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
 
 	udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
 		if (sk->sk_state == TCP_ESTABLISHED &&
-		    INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif))
+		    INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif)) {
+			if (unlikely(udp_sk(sk)->encap_type == UDP_ENCAP_RXRPC))
+				continue;
+
 			return sk;
+		}
 		/* Only check first socket in chain */
 		break;
 	}
-- 
1.8.3.1




More information about the linux-afs mailing list