Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sctp: ensure sk_state is set to CLOSED if hashing fails in sctp_listen_start

If hashing fails in sctp_listen_start(), the socket remains in the
LISTENING state, even though it was not added to the hash table.
This can lead to a scenario where a socket appears to be listening
without actually being accessible.

This patch ensures that if the hashing operation fails, the sk_state
is set back to CLOSED before returning an error.

Note that there is no need to undo the autobind operation if hashing
fails, as the bind port can still be used for next listen() call on
the same socket.

Fixes: 76c6d988aeb3 ("sctp: add sock_reuseport for the sock in __sctp_hash_endpoint")
Reported-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.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>

authored by

Xin Long and committed by
David S. Miller
4d5c70e6 82c5b531

+13 -5
+13 -5
net/sctp/socket.c
··· 8531 8531 struct sctp_endpoint *ep = sp->ep; 8532 8532 struct crypto_shash *tfm = NULL; 8533 8533 char alg[32]; 8534 + int err; 8534 8535 8535 8536 /* Allocate HMAC for generating cookie. */ 8536 8537 if (!sp->hmac && sp->sctp_hmac_alg) { ··· 8559 8558 inet_sk_set_state(sk, SCTP_SS_LISTENING); 8560 8559 if (!ep->base.bind_addr.port) { 8561 8560 if (sctp_autobind(sk)) { 8562 - inet_sk_set_state(sk, SCTP_SS_CLOSED); 8563 - return -EAGAIN; 8561 + err = -EAGAIN; 8562 + goto err; 8564 8563 } 8565 8564 } else { 8566 8565 if (sctp_get_port(sk, inet_sk(sk)->inet_num)) { 8567 - inet_sk_set_state(sk, SCTP_SS_CLOSED); 8568 - return -EADDRINUSE; 8566 + err = -EADDRINUSE; 8567 + goto err; 8569 8568 } 8570 8569 } 8571 8570 8572 8571 WRITE_ONCE(sk->sk_max_ack_backlog, backlog); 8573 - return sctp_hash_endpoint(ep); 8572 + err = sctp_hash_endpoint(ep); 8573 + if (err) 8574 + goto err; 8575 + 8576 + return 0; 8577 + err: 8578 + inet_sk_set_state(sk, SCTP_SS_CLOSED); 8579 + return err; 8574 8580 } 8575 8581 8576 8582 /*