Skip to contentSkip to conversation

Patch "sctp: do not free asoc when it is already dead in sctp_sendmsg" has been added to the 4.9-stable tree

PATCH [email protected] 1 participant 1 message Dec 12, 2017

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

sctp: do not free asoc when it is already dead in sctp_sendmsg

to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
sctp-do-not-free-asoc-when-it-is-already-dead-in-sctp_sendmsg.patch
and it can be found in the queue-4.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From foo@baz Tue Dec 12 13:26:17 CET 2017

From: Xin Long <[email protected]>
Date: Wed, 15 Nov 2017 16:55:54 +0800
Subject: sctp: do not free asoc when it is already dead in sctp_sendmsg

From: Xin Long <[email protected]>

[ Upstream commit ca3af4dd28cff4e7216e213ba3b671fbf9f84758 ]

Now in sctp_sendmsg sctp_wait_for_sndbuf could schedule out without holding sock sk. It means the current asoc can be freed elsewhere, like when receiving an abort packet.

If the asoc is just created in sctp_sendmsg and sctp_wait_for_sndbuf returns err, the asoc will be freed again due to new_asoc is not nil. An use-after-free issue would be triggered by this.

This patch is to fix it by setting new_asoc with nil if the asoc is already dead when cpu schedules back, so that it will not be freed again in sctp_sendmsg.

v1->v2:
set new_asoc as nil in sctp_sendmsg instead of sctp_wait_for_sndbuf.

---
 net/sctp/socket.c |   17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)
net/sctp/socket.c +14 -3
@@ -1958,8 +1958,14 @@ static int sctp_sendmsg(struct sock *sk,
 	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
 	if (!sctp_wspace(asoc)) {
 		err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
-		if (err)
+		if (err) {
+			if (err == -ESRCH) {
+				/* asoc is already dead. */
+				new_asoc = NULL;
+				err = -EPIPE;
+			}
 			goto out_free;
+		}
 	}
 
 	/* If an address is passed with the sendto/sendmsg call, it is used
@@ -7457,10 +7463,11 @@ static int sctp_wait_for_sndbuf(struct s
 	for (;;) {
 		prepare_to_wait_exclusive(&asoc->wait, &wait,
 					  TASK_INTERRUPTIBLE);
+		if (asoc->base.dead)
+			goto do_dead;
 		if (!*timeo_p)
 			goto do_nonblock;
-		if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
-		    asoc->base.dead)
+		if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING)
 			goto do_error;
 		if (signal_pending(current))
 			goto do_interrupted;
@@ -7485,6 +7492,10 @@ out:
 
 	return err;
 
+do_dead:
+	err = -ESRCH;
+	goto out;
+
 do_error:
 	err = -EPIPE;
 	goto out;

Patches currently in stable-queue which might be from [email protected] are

queue-4.9/route-update-fnhe_expires-for-redirect-when-the-fnhe-exists.patch queue-4.9/route-also-update-fnhe_genid-when-updating-a-route-cache.patch queue-4.9/sctp-use-the-right-sk-after-waking-up-from-wait_buf-sleep.patch queue-4.9/sctp-do-not-free-asoc-when-it-is-already-dead-in-sctp_sendmsg.patch