Commit e5b13f34 authored by Marcelo Ricardo Leitner's avatar Marcelo Ricardo Leitner Committed by David S. Miller

sctp: recvmsg should be able to run even if sock is in closing state

Commit d46e416c missed to update some other places which checked for
the socket being TCP-style AND Established state, as Closing state has
some overlapping with the previous understanding of Established.

Without this fix, one of the effects is that some already queued rx
messages may not be readable anymore depending on how the association
teared down, and sending may also not be possible if peer initiated the
shutdown.

Also merge two if() blocks into one condition on sctp_sendmsg().

Cc: Xin Long <lucien.xin@gmail.com>
Fixes: d46e416c ("sctp: sctp should change socket state when shutdown is received")
Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b3f2cf8f
...@@ -202,7 +202,7 @@ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id) ...@@ -202,7 +202,7 @@ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
* could be a TCP-style listening socket or a socket which * could be a TCP-style listening socket or a socket which
* hasn't yet called connect() to establish an association. * hasn't yet called connect() to establish an association.
*/ */
if (!sctp_sstate(sk, ESTABLISHED)) if (!sctp_sstate(sk, ESTABLISHED) && !sctp_sstate(sk, CLOSING))
return NULL; return NULL;
/* Get the first and the only association from the list. */ /* Get the first and the only association from the list. */
...@@ -1068,7 +1068,7 @@ static int __sctp_connect(struct sock *sk, ...@@ -1068,7 +1068,7 @@ static int __sctp_connect(struct sock *sk,
* is already connected. * is already connected.
* It cannot be done even on a TCP-style listening socket. * It cannot be done even on a TCP-style listening socket.
*/ */
if (sctp_sstate(sk, ESTABLISHED) || if (sctp_sstate(sk, ESTABLISHED) || sctp_sstate(sk, CLOSING) ||
(sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
err = -EISCONN; err = -EISCONN;
goto out_free; goto out_free;
...@@ -1705,18 +1705,19 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) ...@@ -1705,18 +1705,19 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
if (msg_name) { if (msg_name) {
/* Look for a matching association on the endpoint. */ /* Look for a matching association on the endpoint. */
asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
if (!asoc) {
/* If we could not find a matching association on the /* If we could not find a matching association on the
* endpoint, make sure that it is not a TCP-style * endpoint, make sure that it is not a TCP-style
* socket that already has an association or there is * socket that already has an association or there is
* no peeled-off association on another socket. * no peeled-off association on another socket.
*/ */
if ((sctp_style(sk, TCP) && if (!asoc &&
sctp_sstate(sk, ESTABLISHED)) || ((sctp_style(sk, TCP) &&
sctp_endpoint_is_peeled_off(ep, &to)) { (sctp_sstate(sk, ESTABLISHED) ||
err = -EADDRNOTAVAIL; sctp_sstate(sk, CLOSING))) ||
goto out_unlock; sctp_endpoint_is_peeled_off(ep, &to))) {
} err = -EADDRNOTAVAIL;
goto out_unlock;
} }
} else { } else {
asoc = sctp_id2assoc(sk, associd); asoc = sctp_id2assoc(sk, associd);
...@@ -2077,7 +2078,8 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, ...@@ -2077,7 +2078,8 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
lock_sock(sk); lock_sock(sk);
if (sctp_style(sk, TCP) && !sctp_sstate(sk, ESTABLISHED)) { if (sctp_style(sk, TCP) && !sctp_sstate(sk, ESTABLISHED) &&
!sctp_sstate(sk, CLOSING)) {
err = -ENOTCONN; err = -ENOTCONN;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment