aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/stream.c
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2017-11-15 04:00:11 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-15 20:49:00 -0500
commit423852f89034492cc40920c00908f6de7d2dbe4f (patch)
tree85760f49fd0d9e0965e4c41b8159bc25c20a9f63 /net/sctp/stream.c
parentcea0cc80a6777beb6eb643d4ad53690e1ad1d4ff (diff)
sctp: check stream reset info len before making reconf chunk
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 EINVAL if the len exceeds chunk's capacity. Thanks Marcelo and Neil for making this clear. v1->v2: - move the check into sctp_send_reset_streams instead. Fixes: cc16f00f6529 ("sctp: add support for generating stream reconf ssn reset request chunk") Reported-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/stream.c')
-rw-r--r--net/sctp/stream.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index b8c8cabb1a58..a11db21dc8a0 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -282,15 +282,31 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
282 282
283 str_nums = params->srs_number_streams; 283 str_nums = params->srs_number_streams;
284 str_list = params->srs_stream_list; 284 str_list = params->srs_stream_list;
285 if (out && str_nums) 285 if (str_nums) {
286 for (i = 0; i < str_nums; i++) 286 int param_len = 0;
287 if (str_list[i] >= stream->outcnt)
288 goto out;
289 287
290 if (in && str_nums) 288 if (out) {
291 for (i = 0; i < str_nums; i++) 289 for (i = 0; i < str_nums; i++)
292 if (str_list[i] >= stream->incnt) 290 if (str_list[i] >= stream->outcnt)
293 goto out; 291 goto out;
292
293 param_len = str_nums * sizeof(__u16) +
294 sizeof(struct sctp_strreset_outreq);
295 }
296
297 if (in) {
298 for (i = 0; i < str_nums; i++)
299 if (str_list[i] >= stream->incnt)
300 goto out;
301
302 param_len += str_nums * sizeof(__u16) +
303 sizeof(struct sctp_strreset_inreq);
304 }
305
306 if (param_len > SCTP_MAX_CHUNK_LEN -
307 sizeof(struct sctp_reconf_chunk))
308 goto out;
309 }
294 310
295 nstr_list = kcalloc(str_nums, sizeof(__be16), GFP_KERNEL); 311 nstr_list = kcalloc(str_nums, sizeof(__be16), GFP_KERNEL);
296 if (!nstr_list) { 312 if (!nstr_list) {