Jiri Slaby ef65b8
From: Xin Long <lucien.xin@gmail.com>
Jiri Slaby ef65b8
Subject: sctp: change sctp_prot .no_autobind with true
Michal Kubecek 12c818
Patch-mainline: v5.4-rc4
Jiri Slaby ef65b8
Git-commit: 63dfb7938b13fa2c2fbcb45f34d065769eb09414
Michal Kubecek 12c818
References: networking-stable-19_10_24 bsc#1158082
Jiri Slaby ef65b8
Jiri Slaby ef65b8
syzbot reported a memory leak:
Jiri Slaby ef65b8
Jiri Slaby ef65b8
  BUG: memory leak, unreferenced object 0xffff888120b3d380 (size 64):
Jiri Slaby ef65b8
  backtrace:
Jiri Slaby ef65b8
Jiri Slaby ef65b8
    [...] slab_alloc mm/slab.c:3319 [inline]
Jiri Slaby ef65b8
    [...] kmem_cache_alloc+0x13f/0x2c0 mm/slab.c:3483
Jiri Slaby ef65b8
    [...] sctp_bucket_create net/sctp/socket.c:8523 [inline]
Jiri Slaby ef65b8
    [...] sctp_get_port_local+0x189/0x5a0 net/sctp/socket.c:8270
Jiri Slaby ef65b8
    [...] sctp_do_bind+0xcc/0x200 net/sctp/socket.c:402
Jiri Slaby ef65b8
    [...] sctp_bindx_add+0x4b/0xd0 net/sctp/socket.c:497
Jiri Slaby ef65b8
    [...] sctp_setsockopt_bindx+0x156/0x1b0 net/sctp/socket.c:1022
Jiri Slaby ef65b8
    [...] sctp_setsockopt net/sctp/socket.c:4641 [inline]
Jiri Slaby ef65b8
    [...] sctp_setsockopt+0xaea/0x2dc0 net/sctp/socket.c:4611
Jiri Slaby ef65b8
    [...] sock_common_setsockopt+0x38/0x50 net/core/sock.c:3147
Jiri Slaby ef65b8
    [...] __sys_setsockopt+0x10f/0x220 net/socket.c:2084
Jiri Slaby ef65b8
    [...] __do_sys_setsockopt net/socket.c:2100 [inline]
Jiri Slaby ef65b8
Jiri Slaby ef65b8
It was caused by when sending msgs without binding a port, in the path:
Jiri Slaby ef65b8
inet_sendmsg() -> inet_send_prepare() -> inet_autobind() ->
Jiri Slaby ef65b8
.get_port/sctp_get_port(), sp->bind_hash will be set while bp->port is
Jiri Slaby ef65b8
not. Later when binding another port by sctp_setsockopt_bindx(), a new
Jiri Slaby ef65b8
bucket will be created as bp->port is not set.
Jiri Slaby ef65b8
Jiri Slaby ef65b8
sctp's autobind is supposed to call sctp_autobind() where it does all
Jiri Slaby ef65b8
things including setting bp->port. Since sctp_autobind() is called in
Jiri Slaby ef65b8
sctp_sendmsg() if the sk is not yet bound, it should have skipped the
Jiri Slaby ef65b8
auto bind.
Jiri Slaby ef65b8
Jiri Slaby ef65b8
THis patch is to avoid calling inet_autobind() in inet_send_prepare()
Jiri Slaby ef65b8
by changing sctp_prot .no_autobind with true, also remove the unused
Jiri Slaby ef65b8
.get_port.
Jiri Slaby ef65b8
Jiri Slaby ef65b8
Reported-by: syzbot+d44f7bbebdea49dbc84a@syzkaller.appspotmail.com
Jiri Slaby ef65b8
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Jiri Slaby ef65b8
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Jiri Slaby ef65b8
Signed-off-by: David S. Miller <davem@davemloft.net>
Jiri Slaby ef65b8
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Michal Kubecek 12c818
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Michal Kubecek 12c818
Michal Kubecek 12c818
SLE15: we need to check no_autobind socket flag in inet_dgram_connect() as,
Michal Kubecek 12c818
unlike in mainline, SCTP still uses this function.
Michal Kubecek 12c818
Jiri Slaby ef65b8
---
Michal Kubecek 12c818
 net/ipv4/af_inet.c | 3 ++-
Michal Kubecek 12c818
 net/sctp/socket.c  | 4 ++--
Michal Kubecek 12c818
 2 files changed, 4 insertions(+), 3 deletions(-)
Jiri Slaby ef65b8
Michal Kubecek 12c818
--- a/net/ipv4/af_inet.c
Michal Kubecek 12c818
+++ b/net/ipv4/af_inet.c
Michal Kubecek 12c818
@@ -535,7 +535,8 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
Michal Kubecek 12c818
 	if (uaddr->sa_family == AF_UNSPEC)
Michal Kubecek 12c818
 		return sk->sk_prot->disconnect(sk, flags);
Michal Kubecek 12c818
 
Michal Kubecek 12c818
-	if (!inet_sk(sk)->inet_num && inet_autobind(sk))
Michal Kubecek 12c818
+	if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind &&
Michal Kubecek 12c818
+	    inet_autobind(sk))
Michal Kubecek 12c818
 		return -EAGAIN;
Michal Kubecek 12c818
 	return sk->sk_prot->connect(sk, uaddr, addr_len);
Michal Kubecek 12c818
 }
Jiri Slaby ef65b8
--- a/net/sctp/socket.c
Jiri Slaby ef65b8
+++ b/net/sctp/socket.c
Jiri Slaby ef65b8
@@ -8240,7 +8240,7 @@ struct proto sctp_prot = {
Jiri Slaby ef65b8
 	.backlog_rcv =	sctp_backlog_rcv,
Jiri Slaby ef65b8
 	.hash        =	sctp_hash,
Jiri Slaby ef65b8
 	.unhash      =	sctp_unhash,
Jiri Slaby ef65b8
-	.get_port    =	sctp_get_port,
Jiri Slaby ef65b8
+	.no_autobind =	true,
Jiri Slaby ef65b8
 	.obj_size    =  sizeof(struct sctp_sock),
Jiri Slaby ef65b8
 	.sysctl_mem  =  sysctl_sctp_mem,
Jiri Slaby ef65b8
 	.sysctl_rmem =  sysctl_sctp_rmem,
Jiri Slaby ef65b8
@@ -8279,7 +8279,7 @@ struct proto sctpv6_prot = {
Jiri Slaby ef65b8
 	.backlog_rcv	= sctp_backlog_rcv,
Jiri Slaby ef65b8
 	.hash		= sctp_hash,
Jiri Slaby ef65b8
 	.unhash		= sctp_unhash,
Jiri Slaby ef65b8
-	.get_port	= sctp_get_port,
Jiri Slaby ef65b8
+	.no_autobind	= true,
Jiri Slaby ef65b8
 	.obj_size	= sizeof(struct sctp6_sock),
Jiri Slaby ef65b8
 	.sysctl_mem	= sysctl_sctp_mem,
Jiri Slaby ef65b8
 	.sysctl_rmem	= sysctl_sctp_rmem,