summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>2019-06-27 19:48:10 -0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-07-28 08:28:31 +0200
commit2a8e1d0c9646f78fdd0f00e2eadf8210bbf810a7 (patch)
tree1cd31a26b71e808ee8d68a303f267a3f1ef40352
parent36febc9885c7cda0fcafadb6fc7f77deb1811902 (diff)
downloadlinux-stable-2a8e1d0c9646f78fdd0f00e2eadf8210bbf810a7.tar.gz
linux-stable-2a8e1d0c9646f78fdd0f00e2eadf8210bbf810a7.tar.bz2
linux-stable-2a8e1d0c9646f78fdd0f00e2eadf8210bbf810a7.zip
sctp: fix error handling on stream scheduler initialization
[ Upstream commit 4d1415811e492d9a8238f8a92dd0d51612c788e9 ] It allocates the extended area for outbound streams only on sendmsg calls, if they are not yet allocated. When using the priority stream scheduler, this initialization may imply into a subsequent allocation, which may fail. In this case, it was aborting the stream scheduler initialization but leaving the ->ext pointer (allocated) in there, thus in a partially initialized state. On a subsequent call to sendmsg, it would notice the ->ext pointer in there, and trip on uninitialized stuff when trying to schedule the data chunk. The fix is undo the ->ext initialization if the stream scheduler initialization fails and avoid the partially initialized state. Although syzkaller bisected this to commit 4ff40b86262b ("sctp: set chunk transport correctly when it's a new asoc"), this bug was actually introduced on the commit I marked below. Reported-by: syzbot+c1a380d42b190ad1e559@syzkaller.appspotmail.com Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations") Tested-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Acked-by: Neil Horman <nhorman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/sctp/stream.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index b6bb68adac6e..f72dfda4025d 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -168,13 +168,20 @@ out:
int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid)
{
struct sctp_stream_out_ext *soute;
+ int ret;
soute = kzalloc(sizeof(*soute), GFP_KERNEL);
if (!soute)
return -ENOMEM;
SCTP_SO(stream, sid)->ext = soute;
- return sctp_sched_init_sid(stream, sid, GFP_KERNEL);
+ ret = sctp_sched_init_sid(stream, sid, GFP_KERNEL);
+ if (ret) {
+ kfree(SCTP_SO(stream, sid)->ext);
+ SCTP_SO(stream, sid)->ext = NULL;
+ }
+
+ return ret;
}
void sctp_stream_free(struct sctp_stream *stream)