forked from mirrors/linux
		
	mptcp: provide subflow aware release function
mptcp re-used inet(6)_release, so the subflow sockets are ignored.
Need to invoke ip(v6)_mc_drop_socket function to ensure mcast join
resources get free'd.
Fixes: 717e79c867 ("mptcp: Add setsockopt()/getsockopt() socket operations")
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/110
Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									d87903b63e
								
							
						
					
					
						commit
						ad98dd3705
					
				
					 1 changed files with 53 additions and 2 deletions
				
			
		|  | @ -11,6 +11,7 @@ | |||
| #include <linux/netdevice.h> | ||||
| #include <linux/sched/signal.h> | ||||
| #include <linux/atomic.h> | ||||
| #include <linux/igmp.h> | ||||
| #include <net/sock.h> | ||||
| #include <net/inet_common.h> | ||||
| #include <net/inet_hashtables.h> | ||||
|  | @ -19,6 +20,7 @@ | |||
| #include <net/tcp_states.h> | ||||
| #if IS_ENABLED(CONFIG_MPTCP_IPV6) | ||||
| #include <net/transp_v6.h> | ||||
| #include <net/addrconf.h> | ||||
| #endif | ||||
| #include <net/mptcp.h> | ||||
| #include <net/xfrm.h> | ||||
|  | @ -3374,10 +3376,34 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock, | |||
| 	return mask; | ||||
| } | ||||
| 
 | ||||
| static int mptcp_release(struct socket *sock) | ||||
| { | ||||
| 	struct mptcp_subflow_context *subflow; | ||||
| 	struct sock *sk = sock->sk; | ||||
| 	struct mptcp_sock *msk; | ||||
| 
 | ||||
| 	if (!sk) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	lock_sock(sk); | ||||
| 
 | ||||
| 	msk = mptcp_sk(sk); | ||||
| 
 | ||||
| 	mptcp_for_each_subflow(msk, subflow) { | ||||
| 		struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | ||||
| 
 | ||||
| 		ip_mc_drop_socket(ssk); | ||||
| 	} | ||||
| 
 | ||||
| 	release_sock(sk); | ||||
| 
 | ||||
| 	return inet_release(sock); | ||||
| } | ||||
| 
 | ||||
| static const struct proto_ops mptcp_stream_ops = { | ||||
| 	.family		   = PF_INET, | ||||
| 	.owner		   = THIS_MODULE, | ||||
| 	.release	   = inet_release, | ||||
| 	.release	   = mptcp_release, | ||||
| 	.bind		   = mptcp_bind, | ||||
| 	.connect	   = mptcp_stream_connect, | ||||
| 	.socketpair	   = sock_no_socketpair, | ||||
|  | @ -3469,10 +3495,35 @@ void __init mptcp_proto_init(void) | |||
| } | ||||
| 
 | ||||
| #if IS_ENABLED(CONFIG_MPTCP_IPV6) | ||||
| static int mptcp6_release(struct socket *sock) | ||||
| { | ||||
| 	struct mptcp_subflow_context *subflow; | ||||
| 	struct mptcp_sock *msk; | ||||
| 	struct sock *sk = sock->sk; | ||||
| 
 | ||||
| 	if (!sk) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	lock_sock(sk); | ||||
| 
 | ||||
| 	msk = mptcp_sk(sk); | ||||
| 
 | ||||
| 	mptcp_for_each_subflow(msk, subflow) { | ||||
| 		struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | ||||
| 
 | ||||
| 		ip_mc_drop_socket(ssk); | ||||
| 		ipv6_sock_mc_close(ssk); | ||||
| 		ipv6_sock_ac_close(ssk); | ||||
| 	} | ||||
| 
 | ||||
| 	release_sock(sk); | ||||
| 	return inet6_release(sock); | ||||
| } | ||||
| 
 | ||||
| static const struct proto_ops mptcp_v6_stream_ops = { | ||||
| 	.family		   = PF_INET6, | ||||
| 	.owner		   = THIS_MODULE, | ||||
| 	.release	   = inet6_release, | ||||
| 	.release	   = mptcp6_release, | ||||
| 	.bind		   = mptcp_bind, | ||||
| 	.connect	   = mptcp_stream_connect, | ||||
| 	.socketpair	   = sock_no_socketpair, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Florian Westphal
						Florian Westphal