Now when resetting stream, if both in and out flags are set, the info len can reach: sizeof(struct sctp_strreset_outreq) + SCTP_MAX_STREAM(65535) + sizeof(struct sctp_strreset_inreq) + SCTP_MAX_STREAM(65535) even without duplicated stream no, this value is far greater than the chunk's max size. _sctp_make_chunk doesn't do any check for this, which would cause the skb it allocs is huge, syzbot even reported a crash due to this. This patch is to check stream reset info len before making reconf chunk and return NULL if the len exceeds chunk's capacity. Fixes: cc16f00f6529 ("sctp: add support for generating stream reconf ssn reset request chunk") Reported-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx> Signed-off-by: Xin Long <lucien.xin@xxxxxxxxx> --- net/sctp/sm_make_chunk.c | 7 +++++-- net/sctp/stream.c | 8 +++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 514465b..a21328a 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3598,14 +3598,17 @@ struct sctp_chunk *sctp_make_strreset_req( __u16 stream_len = stream_num * 2; struct sctp_strreset_inreq inreq; struct sctp_chunk *retval; - __u16 outlen, inlen; + int outlen, inlen; outlen = (sizeof(outreq) + stream_len) * out; inlen = (sizeof(inreq) + stream_len) * in; + if (outlen + inlen > SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_chunkhdr)) + return ERR_PTR(-EINVAL); + retval = sctp_make_reconf(asoc, outlen + inlen); if (!retval) - return NULL; + return ERR_PTR(-ENOMEM); if (outlen) { outreq.param_hdr.type = SCTP_PARAM_RESET_OUT_REQUEST; diff --git a/net/sctp/stream.c b/net/sctp/stream.c index fa8371f..51a25bf 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -162,8 +162,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, kfree(nstr_list); - if (!chunk) { - retval = -ENOMEM; + if (IS_ERR(chunk)) { + retval = PTR_ERR(chunk); goto out; } @@ -482,8 +482,10 @@ struct sctp_chunk *sctp_process_strreset_inreq( } chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); - if (!chunk) + if (IS_ERR(chunk)) { + chunk = NULL; goto out; + } if (nums) for (i = 0; i < nums; i++) -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html