Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rxrpc: Fix deadlock around release of dst cached on udp tunnel

AF_RXRPC sockets use UDP ports in encap mode. This causes socket and dst
from an incoming packet to get stolen and attached to the UDP socket from
whence it is leaked when that socket is closed.

When a network namespace is removed, the wait for dst records to be cleaned
up happens before the cleanup of the rxrpc and UDP socket, meaning that the
wait never finishes.

Fix this by moving the rxrpc (and, by dependence, the afs) private
per-network namespace registrations to the device group rather than subsys
group. This allows cached rxrpc local endpoints to be cleared and their
UDP sockets closed before we try waiting for the dst records.

The symptom is that lines looking like the following:

unregister_netdevice: waiting for lo to become free

get emitted at regular intervals after running something like the
referenced syzbot test.

Thanks to Vadim for tracking this down and work out the fix.

Reported-by: syzbot+df400f2f24a1677cd7e0@syzkaller.appspotmail.com
Reported-by: Vadim Fedorenko <vfedorenko@novek.ru>
Fixes: 5271953cad31 ("rxrpc: Use the UDP encap_rcv hook")
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vadim Fedorenko <vfedorenko@novek.ru>
Link: https://lore.kernel.org/r/161196443016.3868642.5577440140646403533.stgit@warthog.procyon.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

David Howells and committed by
Jakub Kicinski
5399d522 8d520b4d

+6 -6
+3 -3
fs/afs/main.c
··· 193 193 goto error_cache; 194 194 #endif 195 195 196 - ret = register_pernet_subsys(&afs_net_ops); 196 + ret = register_pernet_device(&afs_net_ops); 197 197 if (ret < 0) 198 198 goto error_net; 199 199 ··· 213 213 error_proc: 214 214 afs_fs_exit(); 215 215 error_fs: 216 - unregister_pernet_subsys(&afs_net_ops); 216 + unregister_pernet_device(&afs_net_ops); 217 217 error_net: 218 218 #ifdef CONFIG_AFS_FSCACHE 219 219 fscache_unregister_netfs(&afs_cache_netfs); ··· 244 244 245 245 proc_remove(afs_proc_symlink); 246 246 afs_fs_exit(); 247 - unregister_pernet_subsys(&afs_net_ops); 247 + unregister_pernet_device(&afs_net_ops); 248 248 #ifdef CONFIG_AFS_FSCACHE 249 249 fscache_unregister_netfs(&afs_cache_netfs); 250 250 #endif
+3 -3
net/rxrpc/af_rxrpc.c
··· 990 990 goto error_security; 991 991 } 992 992 993 - ret = register_pernet_subsys(&rxrpc_net_ops); 993 + ret = register_pernet_device(&rxrpc_net_ops); 994 994 if (ret) 995 995 goto error_pernet; 996 996 ··· 1035 1035 error_sock: 1036 1036 proto_unregister(&rxrpc_proto); 1037 1037 error_proto: 1038 - unregister_pernet_subsys(&rxrpc_net_ops); 1038 + unregister_pernet_device(&rxrpc_net_ops); 1039 1039 error_pernet: 1040 1040 rxrpc_exit_security(); 1041 1041 error_security: ··· 1057 1057 unregister_key_type(&key_type_rxrpc); 1058 1058 sock_unregister(PF_RXRPC); 1059 1059 proto_unregister(&rxrpc_proto); 1060 - unregister_pernet_subsys(&rxrpc_net_ops); 1060 + unregister_pernet_device(&rxrpc_net_ops); 1061 1061 ASSERTCMP(atomic_read(&rxrpc_n_tx_skbs), ==, 0); 1062 1062 ASSERTCMP(atomic_read(&rxrpc_n_rx_skbs), ==, 0); 1063 1063