| From 9b6c08878e23adb7cc84bdca94d8a944b03f099e Mon Sep 17 00:00:00 2001 |
| From: Xin Long <lucien.xin@gmail.com> |
| Date: Wed, 26 Jun 2019 16:31:39 +0800 |
| Subject: sctp: not bind the socket in sctp_connect |
| |
| From: Xin Long <lucien.xin@gmail.com> |
| |
| commit 9b6c08878e23adb7cc84bdca94d8a944b03f099e upstream. |
| |
| Now when sctp_connect() is called with a wrong sa_family, it binds |
| to a port but doesn't set bp->port, then sctp_get_af_specific will |
| return NULL and sctp_connect() returns -EINVAL. |
| |
| Then if sctp_bind() is called to bind to another port, the last |
| port it has bound will leak due to bp->port is NULL by then. |
| |
| sctp_connect() doesn't need to bind ports, as later __sctp_connect |
| will do it if bp->port is NULL. So remove it from sctp_connect(). |
| While at it, remove the unnecessary sockaddr.sa_family len check |
| as it's already done in sctp_inet_connect. |
| |
| Fixes: 644fbdeacf1d ("sctp: fix the issue that flags are ignored when using kernel_connect") |
| Reported-by: syzbot+079bf326b38072f849d9@syzkaller.appspotmail.com |
| Signed-off-by: Xin Long <lucien.xin@gmail.com> |
| Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| |
| --- |
| net/sctp/socket.c | 21 ++------------------- |
| 1 file changed, 2 insertions(+), 19 deletions(-) |
| |
| --- a/net/sctp/socket.c |
| +++ b/net/sctp/socket.c |
| @@ -4168,34 +4168,17 @@ out_nounlock: |
| static int sctp_connect(struct sock *sk, struct sockaddr *addr, |
| int addr_len, int flags) |
| { |
| - struct inet_sock *inet = inet_sk(sk); |
| struct sctp_af *af; |
| - int err = 0; |
| + int err = -EINVAL; |
| |
| lock_sock(sk); |
| - |
| pr_debug("%s: sk:%p, sockaddr:%p, addr_len:%d\n", __func__, sk, |
| addr, addr_len); |
| |
| - /* We may need to bind the socket. */ |
| - if (!inet->inet_num) { |
| - if (sk->sk_prot->get_port(sk, 0)) { |
| - release_sock(sk); |
| - return -EAGAIN; |
| - } |
| - inet->inet_sport = htons(inet->inet_num); |
| - } |
| - |
| /* Validate addr_len before calling common connect/connectx routine. */ |
| af = sctp_get_af_specific(addr->sa_family); |
| - if (!af || addr_len < af->sockaddr_len) { |
| - err = -EINVAL; |
| - } else { |
| - /* Pass correct addr len to common routine (so it knows there |
| - * is only one address being passed. |
| - */ |
| + if (af && addr_len >= af->sockaddr_len) |
| err = __sctp_connect(sk, addr, af->sockaddr_len, flags, NULL); |
| - } |
| |
| release_sock(sk); |
| return err; |