aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>2016-11-03 17:03:41 -0200
committerWilly Tarreau <w@1wt.eu>2017-02-10 11:03:55 +0100
commit5b97e5f348cf50af84ca008f930d0e4259026bbc (patch)
tree6e9bd5d3647893d526587245273d697673b137de
parent261def571d19d3b4e2228643c5c0ac89f5e10d15 (diff)
downloadedison-v3.10-5b97e5f348cf50af84ca008f930d0e4259026bbc.tar.gz
sctp: assign assoc_id earlier in __sctp_connect
commit 7233bc84a3aeda835d334499dc00448373caf5c0 upstream. sctp_wait_for_connect() currently already holds the asoc to keep it alive during the sleep, in case another thread release it. But Andrey Konovalov and Dmitry Vyukov reported an use-after-free in such situation. Problem is that __sctp_connect() doesn't get a ref on the asoc and will do a read on the asoc after calling sctp_wait_for_connect(), but by then another thread may have closed it and the _put on sctp_wait_for_connect will actually release it, causing the use-after-free. Fix is, instead of doing the read after waiting for the connect, do it before so, and avoid this issue as the socket is still locked by then. There should be no issue on returning the asoc id in case of failure as the application shouldn't trust on that number in such situations anyway. This issue doesn't exist in sctp_sendmsg() path. Reported-by: Dmitry Vyukov <dvyukov@google.com> Reported-by: Andrey Konovalov <andreyknvl@google.com> Tested-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Reviewed-by: Xin Long <lucien.xin@gmail.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Willy Tarreau <w@1wt.eu>
-rw-r--r--net/sctp/socket.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 86e7352422b..ede7c540ea2 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1231,9 +1231,12 @@ static int __sctp_connect(struct sock* sk,
timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
- err = sctp_wait_for_connect(asoc, &timeo);
- if ((err == 0 || err == -EINPROGRESS) && assoc_id)
+ if (assoc_id)
*assoc_id = asoc->assoc_id;
+ err = sctp_wait_for_connect(asoc, &timeo);
+ /* Note: the asoc may be freed after the return of
+ * sctp_wait_for_connect.
+ */
/* Don't free association on exit. */
asoc = NULL;