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+079bf326b38072f849d9@xxxxxxxxxxxxxxxxxxxxxxxxx > Signed-off-by: Xin Long <lucien.xin@xxxxxxxxx> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@xxxxxxxxx> > --- > 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 >