30ed1d1
From 07f2c7ab6f8d0a7e7c5764c4e6cc9c52951b9d9c Mon Sep 17 00:00:00 2001
30ed1d1
From: Alexey Kodanev <alexey.kodanev@oracle.com>
30ed1d1
Date: Fri, 9 Feb 2018 17:35:23 +0300
30ed1d1
Subject: [PATCH] sctp: verify size of a new chunk in _sctp_make_chunk()
30ed1d1
30ed1d1
When SCTP makes INIT or INIT_ACK packet the total chunk length
30ed1d1
can exceed SCTP_MAX_CHUNK_LEN which leads to kernel panic when
30ed1d1
transmitting these packets, e.g. the crash on sending INIT_ACK:
30ed1d1
30ed1d1
[  597.804948] skbuff: skb_over_panic: text:00000000ffae06e4 len:120168
30ed1d1
               put:120156 head:000000007aa47635 data:00000000d991c2de
30ed1d1
               tail:0x1d640 end:0xfec0 dev:<NULL>
30ed1d1
...
30ed1d1
[  597.976970] ------------[ cut here ]------------
30ed1d1
[  598.033408] kernel BUG at net/core/skbuff.c:104!
30ed1d1
[  600.314841] Call Trace:
30ed1d1
[  600.345829]  <IRQ>
30ed1d1
[  600.371639]  ? sctp_packet_transmit+0x2095/0x26d0 [sctp]
30ed1d1
[  600.436934]  skb_put+0x16c/0x200
30ed1d1
[  600.477295]  sctp_packet_transmit+0x2095/0x26d0 [sctp]
30ed1d1
[  600.540630]  ? sctp_packet_config+0x890/0x890 [sctp]
30ed1d1
[  600.601781]  ? __sctp_packet_append_chunk+0x3b4/0xd00 [sctp]
30ed1d1
[  600.671356]  ? sctp_cmp_addr_exact+0x3f/0x90 [sctp]
30ed1d1
[  600.731482]  sctp_outq_flush+0x663/0x30d0 [sctp]
30ed1d1
[  600.788565]  ? sctp_make_init+0xbf0/0xbf0 [sctp]
30ed1d1
[  600.845555]  ? sctp_check_transmitted+0x18f0/0x18f0 [sctp]
30ed1d1
[  600.912945]  ? sctp_outq_tail+0x631/0x9d0 [sctp]
30ed1d1
[  600.969936]  sctp_cmd_interpreter.isra.22+0x3be1/0x5cb0 [sctp]
30ed1d1
[  601.041593]  ? sctp_sf_do_5_1B_init+0x85f/0xc30 [sctp]
30ed1d1
[  601.104837]  ? sctp_generate_t1_cookie_event+0x20/0x20 [sctp]
30ed1d1
[  601.175436]  ? sctp_eat_data+0x1710/0x1710 [sctp]
30ed1d1
[  601.233575]  sctp_do_sm+0x182/0x560 [sctp]
30ed1d1
[  601.284328]  ? sctp_has_association+0x70/0x70 [sctp]
30ed1d1
[  601.345586]  ? sctp_rcv+0xef4/0x32f0 [sctp]
30ed1d1
[  601.397478]  ? sctp6_rcv+0xa/0x20 [sctp]
30ed1d1
...
30ed1d1
30ed1d1
Here the chunk size for INIT_ACK packet becomes too big, mostly
30ed1d1
because of the state cookie (INIT packet has large size with
30ed1d1
many address parameters), plus additional server parameters.
30ed1d1
30ed1d1
Later this chunk causes the panic in skb_put_data():
30ed1d1
30ed1d1
  skb_packet_transmit()
30ed1d1
      sctp_packet_pack()
30ed1d1
          skb_put_data(nskb, chunk->skb->data, chunk->skb->len);
30ed1d1
30ed1d1
'nskb' (head skb) was previously allocated with packet->size
30ed1d1
from u16 'chunk->chunk_hdr->length'.
30ed1d1
30ed1d1
As suggested by Marcelo we should check the chunk's length in
30ed1d1
_sctp_make_chunk() before trying to allocate skb for it and
30ed1d1
discard a chunk if its size bigger than SCTP_MAX_CHUNK_LEN.
30ed1d1
30ed1d1
Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
30ed1d1
Acked-by: Marcelo Ricardo Leitner <marcelo.leinter@gmail.com>
30ed1d1
Acked-by: Neil Horman <nhorman@tuxdriver.com>
30ed1d1
Signed-off-by: David S. Miller <davem@davemloft.net>
30ed1d1
---
30ed1d1
 net/sctp/sm_make_chunk.c | 7 ++++++-
30ed1d1
 1 file changed, 6 insertions(+), 1 deletion(-)
30ed1d1
30ed1d1
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
30ed1d1
index 793b05ec692b..d01475f5f710 100644
30ed1d1
--- a/net/sctp/sm_make_chunk.c
30ed1d1
+++ b/net/sctp/sm_make_chunk.c
30ed1d1
@@ -1380,9 +1380,14 @@ static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc,
30ed1d1
 	struct sctp_chunk *retval;
30ed1d1
 	struct sk_buff *skb;
30ed1d1
 	struct sock *sk;
30ed1d1
+	int chunklen;
30ed1d1
+
30ed1d1
+	chunklen = SCTP_PAD4(sizeof(*chunk_hdr) + paylen);
30ed1d1
+	if (chunklen > SCTP_MAX_CHUNK_LEN)
30ed1d1
+		goto nodata;
30ed1d1
30ed1d1
 	/* No need to allocate LL here, as this is only a chunk. */
30ed1d1
-	skb = alloc_skb(SCTP_PAD4(sizeof(*chunk_hdr) + paylen), gfp);
30ed1d1
+	skb = alloc_skb(chunklen, gfp);
30ed1d1
 	if (!skb)
30ed1d1
 		goto nodata;
30ed1d1
30ed1d1
-- 
30ed1d1
2.14.3
30ed1d1