New: Remote/local Denial of Service vulnerability in SCTP packet/chunk handling
Subsystems (3)
(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).
Quoted 96 lines · On Wed, 15 Sep 2010 12:17:21 GMT [email protected] wrote:
https://bugzilla.kernel.org/show_bug.cgi?id592
Summary: Remote/local Denial of Service vulnerability in SCTP packet/chunk handling Product: Networking Version: 2.5 Kernel Version: 2.6.36-rc4 Platform: All OS/Version: Linux Tree: Mainline Status: NEW Severity: blocking Priority: P1 Component: Other AssignedTo: [email protected] ReportedBy: [email protected] Regression: NoCreated an attachment (id0132)
--> (https://bugzilla.kernel.org/attachment.cgi?id0132)
Patch to fix the problem
sctp_outq_flush()innet/sctp/outqueue.cmay callsctp_packet_reset()on a packet structure which has already been filled with chunks.sctp_packet_reset()will not take care of the chunks in its list and only reset the packet length. After that, the SCTP code assumes the packet to be re-initialized and adds further chunks to the structure. The length will be wrong. When actually trying to transmit the packet, the packetsk_buffstructure may be exceeded withinsctp_packet_transmit(), resulting inskb_over_panic()=> denial of service.Such a DoS can be triggered by a malicious remote SCTP instance, as follows:
- The remote endpoint has to use two paths (i.e. 2 IP addresses); easy to achieve using an IPv4 address and an IPv6 address -> path A and B.
- The remote user has to trigger the transmission of aHEARTBEAT_ACKon path A. This is trivial, by sending a HEARTBEAT chunk.sctp_outq_flush()will callsctp_packet_config()for the packet on path A. TheHEARTBEAT_ACKwill be added to this packet.
- The remote user has to trigger a DATA chunk retransmission on path B. This is trivial, since it only has to send appropriate SACK chunks.sctp_outq_flush()notices that the retransmission is on a different path and callssctp_packet_config()for the packet on path B. The DATA chunk to be retransmitted is added to this packet.
- The local instance has to send another DATA chunk on path A. This depends on the application, but should be easy to trigger from a remote instance.sctp_outq_flush()notices that the path has changed again, and callssctp_packet_config()for the packet on path A. This resets the size of theHEARTBEAT_ACKchunk, but the chunk remains in the packet. Ifsize(HEARTBEAT_ACK)+ size(DATA) > MTU - overhead, the next call tosctp_packet_transmit()causes the kernel panic => DoS.PID: 13309 TASK:
f6636600CPU: 1 COMMAND: "scriptingclient"
#0 [e4d91968]crash_kexecatc0189fea
#1 [e4d919b4]do_invalid_opatc0104a46
#2 [e4d91a50]error_code(viainvalid_op) atc058d1a1EAX: 0000008b EBX: f89e168d ECX: ffffff78 EDX: 00000000 EBP: e4d91ab8 DS: 007b ESI: f601e000 ES: 007b EDI: e44570e8 GS: 00e0 CS: 0060 EIP: c04b9d7c ERR: ffffffff EFLAGS: 00010286#3 [
e4d91a84]skb_over_panicatc04b9d7c
#4 [e4d91a94]sctp_packet_transmitatf89e1688#5 [e4d91ac8]sctp_packet_transmitatf89e1688#6 [e4d91b14]sctp_packet_transmit_chunkatf89e1d23#7 [e4d91b2c]sctp_outq_flushatf89d78f9
#8 [e4d91ba8]sctp_outq_uncorkatf89d7994#9 [e4d91bb0]sctp_cmd_interpreteratf89cce71
#10 [e4d91c00]sctp_side_effectsatf89cdbff#11 [e4d91c30]sctp_do_smatf89cdd3d
#12 [e4d91cdc]sctp_assoc_bh_rcvatf89d1279#13 [e4d91d0c]sctp_inq_pushatf89d6773
#14 [e4d91d14]sctp_rcvatf89e2e5d
#15 [e4d91d8c]ip_local_deliver_finishatc04ec6e5#16 [e4d91db0]ip_local_deliveratc04ec93a#17 [e4d91dcc]ip_rcv_finishatc04ebf98
#18 [e4d91df4]ip_rcvatc04ec449
#19 [e4d91e1c]netif_receive_skbatc04c37a4#20 [e4d91e58]e1000_receive_skbatf80a45bb#21 [e4d91e68]e1000_clean_rx_irqatf80a88b6#22 [e4d91edc]e1000_cleanatf80a799d
#23 [e4d91efc]net_rx_actionatc04c410a
#24 [e4d91f28]__do_softirqatc0153132
#25 [e4d91f70]do_softirqatc0153290
#26 [e4d91f7c]irq_exitatc01533e0
#27 [e4d91f84]do_IRQatc0591240
#28 [e4d91fb0]common_interruptatc0103a2bEAX: 9af6e0c6 EBX: b0dad373 ECX: 00000005 EDX: 4d995cbc DS: 007b ESI: 598130cd ES: 007b EDI: 00b5dfc0 SS: 007b ESP: bfca6d80 EBP: bfca6df8 GS: 0033 CS: 0073 EIP: 0804b816 ERR: ffffff55 EFLAGS: 00000a86In a similar way, the problem can also be triggered by a local user, having only the permission to establish SCTP associations. Of course, the problem can also occur during normal network operation, just by a retransmission at the wrong time.
Quoted 5 lines
The attached patch against 2.6.36-rc4 (git repository) fixes
sctp_outq_flush()by ensuring that the packet on each path is initialized only once. Furthermore, aBUG_ON()statement ensures that further problems by callingsctp_packet_reset()on packets with chunks are detected directly.
Thanks, but please send patches via email, not via bugzilla. Documentation/SubmittingPatches has some tips. Suitable recipients for this patch are, from the MAINTAINERS file:
M: Vlad Yasevich <[email protected]> M: Sridhar Samudrala <[email protected]> L: [email protected]
but please just send it as a reply-to-all to this email so that everyone knows wht's happening.
I'd suggest that you also add the line
to the end of the changelog so that we don't forget to consider the patch for backporting.
net/sctp/output.c +1 -0
@@ -72,6 +72,7 @@ static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet,static void sctp_packet_reset (struct sctp_packet *packet) { +BUG_ON (!list_empty (&packet->chunk_list)); packet->size = packet->overhead; packet->has_cookie_echo =0 ; packet->has_sack =0 ;
net/sctp/outqueue.c +14 -15
@@ -799,13 +799,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)*/ if (new_transport != transport) { transport = new_transport; + packet = &transport->packet;if (list_empty (&transport->send_ready)) {list_add_tail (&transport->send_ready, &transport_list); +sctp_packet_config (packet, vtag, + asoc->peer.ecn_capable); } - packet = &transport->packet; -sctp_packet_config (packet, vtag, - asoc->peer.ecn_capable); }switch (chunk->chunk_hdr->type) {
@@ -900,15 +900,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)/* Switch transports & prepare the packet. */ transport = asoc->peer.retran_path; + packet = &transport->packet;if (list_empty (&transport->send_ready)) {list_add_tail (&transport->send_ready, &transport_list); +sctp_packet_config (packet, vtag, + asoc->peer.ecn_capable); } - - packet = &transport->packet; -sctp_packet_config (packet, vtag, - asoc->peer.ecn_capable); retran: error =sctp_outq_flush_rtx (q, packet, rtx_timeout, &start_timer);
@@ -970,6 +969,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)/* Change packets if necessary. */ if (new_transport != transport) { transport = new_transport; + packet = &transport->packet;/* Schedule to have this transport's * packet flushed.
@@ -977,15 +977,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)if (list_empty (&transport->send_ready)) {list_add_tail (&transport->send_ready, &transport_list); - } +sctp_packet_config (packet, vtag, + asoc->peer.ecn_capable); - packet = &transport->packet; -sctp_packet_config (packet, vtag, - asoc->peer.ecn_capable); -/* We've switched transports, so apply the -* Burst limit to the new transport. -*/ -sctp_transport_burst_limited (transport); +/* We've switched transports, so apply the +* Burst limit to the new transport. +*/ +sctp_transport_burst_limited (transport); + } } SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ",
Quoted 13 lines · Andrew Morton
Thanks, but please send patches via email, not via bugzilla.
Documentation/SubmittingPatcheshas some tips. Suitable recipients for this patch are, from theMAINTAINERSfile:M: Vlad Yasevich <[email protected]> M: Sridhar Samudrala <[email protected]> L: [email protected]but please just send it as a reply-to-all to this email so that everyone knows wht's happening.
Quoted 8 lines
I'd suggest that you also add the line
Cc <[email protected]>to the end of the changelog so that we don't forget to consider the patch for backporting.
Hi Andrew
There is a much simpler solution to this problem that I posted to netdev today.
-vlad.
Quoted 90 lines
net/sctp/output.c +1
-0@@ -72,6 +72,7 @@ static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet,static void sctp_packet_reset (struct sctp_packet *packet) { +BUG_ON (!list_empty (&packet->chunk_list)); packet->size = packet->overhead; packet->has_cookie_echo =0 ; packet->has_sack =0 ;net/sctp/outqueue.c +14
-16@@ -799,13 +799,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)*/ if (new_transport != transport) { transport = new_transport; + packet = &transport->packet;if (list_empty (&transport->send_ready)) {list_add_tail (&transport->send_ready, &transport_list); +sctp_packet_config (packet, vtag, + asoc->peer.ecn_capable); } - packet = &transport->packet; -sctp_packet_config (packet, vtag, - asoc->peer.ecn_capable); }switch (chunk->chunk_hdr->type) {@@ -900,15 +900,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)/* Switch transports & prepare the packet. */ transport = asoc->peer.retran_path; + packet = &transport->packet;if (list_empty (&transport->send_ready)) {list_add_tail (&transport->send_ready, &transport_list); +sctp_packet_config (packet, vtag, + asoc->peer.ecn_capable); } - - packet = &transport->packet; -sctp_packet_config (packet, vtag, - asoc->peer.ecn_capable); retran: error =sctp_outq_flush_rtx (q, packet, rtx_timeout, &start_timer);@@ -970,6 +969,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)/* Change packets if necessary. */ if (new_transport != transport) { transport = new_transport; + packet = &transport->packet;/* Schedule to have this transport's * packet flushed. @@ -977,15 +977,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)if (list_empty (&transport->send_ready)) {list_add_tail (&transport->send_ready, &transport_list); - } +sctp_packet_config (packet, vtag, + asoc->peer.ecn_capable); - packet = &transport->packet; -sctp_packet_config (packet, vtag, - asoc->peer.ecn_capable); -/* We've switched transports, so apply the -* Burst limit to the new transport. -*/ -sctp_transport_burst_limited (transport); +/* We've switched transports, so apply the +* Burst limit to the new transport. +*/ +sctp_transport_burst_limited (transport); + } } SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ", --To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 16 lines · Vlad Yasevich
Quoted 15 lines · Andrew Morton
Thanks, but please send patches via email, not via bugzilla.
Documentation/SubmittingPatcheshas some tips. Suitable recipients for this patch are, from theMAINTAINERSfile:M: Vlad Yasevich <[email protected]> M: Sridhar Samudrala <[email protected]> L: [email protected]but please just send it as a reply-to-all to this email so that everyone knows wht's happening.
I'd suggest that you also add the line
Cc <[email protected]>
Quoted 7 lines
Quoted 2 lines
to the end of the changelog so that we don't forget to consider the patch for backporting.
Hi Andrew
There is a much simpler solution to this problem that I posted to netdev today.
Dear all,
Vlad's patch solves the problem. I hope this patch can go into the mailine kernel soon, in order to get distribution kernels fixed as soon as possible. It is relatively easy to trigger the denial of service problem, making all systems providing SCTP-based services vulnerable to a remote DoS attack.
I have also been able to reproduce the problem with kernel 2.6.32, i.e. at least all kernels from 2.6.32 to 2.6.36 are affected.
Best regards
Signature · 9 lines
=================================== Dr. Thomas Dreibholz University of Duisburg-Essen, Room ES210 Inst. for Experimental Mathematics Ellernstraße 29 Computer Networking Technology Group D-45326 Essen/Germany ----------------------------------------------------------------------- E-Mail: [email protected] Homepage: http://www.iem.uni-due.de/~dreibh ===================================
Quoted 27 lines · Thomas Dreibholz
Quoted 16 lines · Vlad Yasevich
Quoted 15 lines · Andrew Morton
Thanks, but please send patches via email, not via bugzilla.
Documentation/SubmittingPatcheshas some tips. Suitable recipients for this patch are, from theMAINTAINERSfile:M: Vlad Yasevich <[email protected]> M: Sridhar Samudrala <[email protected]> L: [email protected]but please just send it as a reply-to-all to this email so that everyone knows wht's happening.
I'd suggest that you also add the line
Cc <[email protected]>Quoted 7 lines
Quoted 2 lines
to the end of the changelog so that we don't forget to consider the patch for backporting.
Hi Andrew
There is a much simpler solution to this problem that I posted to netdev today.
Dear all,
Quoted 7 lines
Vlad's patch solves the problem. I hope this patch can go into the mailine kernel soon, in order to get distribution kernels fixed as soon as possible. It is relatively easy to trigger the denial of service problem, making all systems providing SCTP-based services vulnerable to a remote DoS attack.
I have also been able to reproduce the problem with kernel 2.6.32, i.e. at least all kernels from 2.6.32 to 2.6.36 are affected.
Is this in Linus's tree now? If so, does anyone have the git commit id?
thanks,
greg k-h
David Miller
maintainerFrom: Greg KH <[email protected]>
Date: Thu, 23 Sep 2010 11:05:15 -0700
Quoted 10 lines · Thomas Dreibholz
Quoted 7 lines
Vlad's patch solves the problem. I hope this patch can go into the mailine kernel soon, in order to get distribution kernels fixed as soon as possible. It is relatively easy to trigger the denial of service problem, making all systems providing SCTP-based services vulnerable to a remote DoS attack.
I have also been able to reproduce the problem with kernel 2.6.32, i.e. at least all kernels from 2.6.32 to 2.6.36 are affected.
Is this in Linus's tree now? If so, does anyone have the git commit id?
Should be: 4bdab43323b459900578b200a4b8cf9713ac8fab
Quoted 9 lines · David Miller
From: Greg KH <[email protected]>
Date: Thu, 23 Sep 2010 11:05:15 -0700Quoted 6 lines · Thomas Dreibholz
Quoted 5 lines
Vlad's patch solves the problem. I hope this patch can go into the mailine kernel soon, in order to get distribution kernels fixed as soon as possible. It is relatively easy to trigger the denial of service problem, making all systems providing SCTP-based services vulnerable to a remote DoS attack.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
I have also been able to reproduce the problem with kernel 2.6.32, i.e. at least all kernels from 2.6.32 to 2.6.36 are affected.
Is this in Linus's tree now? If so, does anyone have the git commit id?
Should be:
4bdab43323b459900578b200a4b8cf9713ac8fab
Wonderful, now queued up.
thanks,
greg k-h