On Wed, Jun 26, 2019 at 04:31:39PM +0800, Xin Long wrote:
> 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+079bf326b38072f84...@syzkaller.appspotmail.com
> Signed-off-by: Xin Long <lucien....@gmail.com>

Acked-by: Marcelo Ricardo Leitner <marcelo.leit...@gmail.com>

> ---
>  net/sctp/socket.c | 24 +++---------------------
>  1 file changed, 3 insertions(+), 21 deletions(-)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 39ea0a3..f33aa9e 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -4816,35 +4816,17 @@ static int sctp_setsockopt(struct sock *sk, int 
> level, int optname,
>  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 = addr_len < offsetofend(struct sockaddr, sa_family) ? NULL :
> -             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.
> -              */
> +     af = sctp_get_af_specific(addr->sa_family);
> +     if (af && addr_len >= af->sockaddr_len)
>               err = __sctp_connect(sk, addr, af->sockaddr_len, flags, NULL);
> -     }
>  
>       release_sock(sk);
>       return err;
> -- 
> 2.1.0
> 

Reply via email to