Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9ee5afd authored by Marcelo Ricardo Leitner's avatar Marcelo Ricardo Leitner Committed by Greg Kroah-Hartman
Browse files

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: default avatar <syzbot+c1a380d42b190ad1e559@syzkaller.appspotmail.com>
Fixes: 5bbbbe32 ("sctp: introduce stream scheduler foundations")
Tested-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: default avatarNeil Horman <nhorman@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bfa79135
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -253,13 +253,20 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
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)