On Thu, Jun 27, 2019 at 07:48:10PM -0300, Marcelo Ricardo Leitner wrote:
> 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+c1a380d42b190ad1e...@syzkaller.appspotmail.com
> Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
> Tested-by: Xin Long <lucien....@gmail.com>
> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leit...@gmail.com>
> ---
>  net/sctp/stream.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
> index 
> 93ed07877337eace4ef7f4775dda5868359ada37..25946604af85c09917e63e5c4a8d7d6fa2caebc4
>  100644
> --- a/net/sctp/stream.c
> +++ b/net/sctp/stream.c
> @@ -153,13 +153,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)
> -- 
> 2.21.0
> 
> 
Acked-by: Neil Horman <nhor...@redhat.com>

Reply via email to