aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2016-11-13 08:44:37 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-14 16:22:33 -0500
commit5bf35ddfee052d44f39ebaa395d87101c8918405 (patch)
tree0482e404f2e9307e27224e6ffc660c59d34325b9
parent193f5122878c5d4d30dbfc9128affe58bdd18206 (diff)
sctp: change sk state only when it has assocs in sctp_shutdown
Now when users shutdown a sock with SEND_SHUTDOWN in sctp, even if this sock has no connection (assoc), sk state would be changed to SCTP_SS_CLOSING, which is not as we expect. Besides, after that if users try to listen on this sock, kernel could even panic when it dereference sctp_sk(sk)->bind_hash in sctp_inet_listen, as bind_hash is null when sock has no assoc. This patch is to move sk state change after checking sk assocs is not empty, and also merge these two if() conditions and reduce indent level. Fixes: d46e416c11c8 ("sctp: sctp should change socket state when shutdown is received") Reported-by: Andrey Konovalov <andreyknvl@google.com> Tested-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sctp/socket.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index faa48ff5cf4b..f23ad913dc7a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4285,19 +4285,18 @@ static void sctp_shutdown(struct sock *sk, int how)
4285{ 4285{
4286 struct net *net = sock_net(sk); 4286 struct net *net = sock_net(sk);
4287 struct sctp_endpoint *ep; 4287 struct sctp_endpoint *ep;
4288 struct sctp_association *asoc;
4289 4288
4290 if (!sctp_style(sk, TCP)) 4289 if (!sctp_style(sk, TCP))
4291 return; 4290 return;
4292 4291
4293 if (how & SEND_SHUTDOWN) { 4292 ep = sctp_sk(sk)->ep;
4293 if (how & SEND_SHUTDOWN && !list_empty(&ep->asocs)) {
4294 struct sctp_association *asoc;
4295
4294 sk->sk_state = SCTP_SS_CLOSING; 4296 sk->sk_state = SCTP_SS_CLOSING;
4295 ep = sctp_sk(sk)->ep; 4297 asoc = list_entry(ep->asocs.next,
4296 if (!list_empty(&ep->asocs)) { 4298 struct sctp_association, asocs);
4297 asoc = list_entry(ep->asocs.next, 4299 sctp_primitive_SHUTDOWN(net, asoc, NULL);
4298 struct sctp_association, asocs);
4299 sctp_primitive_SHUTDOWN(net, asoc, NULL);
4300 }
4301 } 4300 }
4302} 4301}
4303 4302