-
Notifications
You must be signed in to change notification settings - Fork 15k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: cherry-pick 2c26785, b03de8b and a3c3ef6 from usrsctp. (#27491)
* chore: cherry-pick 2c26785, b03de8b and a3c3ef6 from usrsctp. * update patches Co-authored-by: Electron Bot <electron@github.com>
- Loading branch information
1 parent
47640ea
commit 70526f8
Showing
5 changed files
with
291 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
cherry_picking_improve_the_input_validation_and_processing_of.patch | ||
cherry_picking_clean_up_more_resources_of_an_existing_sctp.patch | ||
cherry_picking_harden_the_handling_of_outgoing_streams.patch |
104 changes: 104 additions & 0 deletions
104
patches/usrsctp/cherry_picking_clean_up_more_resources_of_an_existing_sctp.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: Michael Tuexen <tuexen@fh-muenster.de> | ||
Date: Sat, 12 Dec 2020 23:30:59 +0100 | ||
Subject: Cherry picking: Clean up more resouces of an existing SCTP | ||
association in case of a restart. | ||
|
||
This fixes a use-after-free scenario, which was reported by Felix | ||
Wilhelm from Google in case a peer is able to modify the cookie. | ||
However, this can also be triggered by an assciation restart under | ||
some specific conditions. | ||
|
||
diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c | ||
index e2f03c73165d8e1ecd08b9f103afe03a3d2adb7f..669b2b2131d6e1e844f98fc10547db1715e6a0bd 100755 | ||
--- a/usrsctplib/netinet/sctp_input.c | ||
+++ b/usrsctplib/netinet/sctp_input.c | ||
@@ -34,7 +34,7 @@ | ||
|
||
#if defined(__FreeBSD__) && !defined(__Userspace__) | ||
#include <sys/cdefs.h> | ||
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 366248 2020-09-29 09:36:06Z tuexen $"); | ||
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 368593 2020-12-12 22:23:45Z tuexen $"); | ||
#endif | ||
|
||
#include <netinet/sctp_os.h> | ||
@@ -1595,6 +1595,11 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, | ||
struct sctp_association *asoc; | ||
struct sctp_init_chunk *init_cp, init_buf; | ||
struct sctp_init_ack_chunk *initack_cp, initack_buf; | ||
+ struct sctp_asconf_addr *aparam, *naparam; | ||
+ struct sctp_asconf_ack *aack, *naack; | ||
+ struct sctp_tmit_chunk *chk, *nchk; | ||
+ struct sctp_stream_reset_list *strrst, *nstrrst; | ||
+ struct sctp_queued_to_read *sq, *nsq; | ||
struct sctp_nets *net; | ||
struct mbuf *op_err; | ||
struct timeval old; | ||
@@ -1891,8 +1896,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, | ||
* kick us so it COULD still take a timeout | ||
* to move these.. but it can't hurt to mark them. | ||
*/ | ||
- struct sctp_tmit_chunk *chk; | ||
- TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { | ||
+ TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { | ||
if (chk->sent < SCTP_DATAGRAM_RESEND) { | ||
chk->sent = SCTP_DATAGRAM_RESEND; | ||
sctp_flight_size_decrease(chk); | ||
@@ -2084,6 +2088,57 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, | ||
stcb->asoc.strmout[i].next_mid_unordered = 0; | ||
stcb->asoc.strmout[i].last_msg_incomplete = 0; | ||
} | ||
+ TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) { | ||
+ TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp); | ||
+ SCTP_FREE(strrst, SCTP_M_STRESET); | ||
+ } | ||
+ TAILQ_FOREACH_SAFE(sq, &asoc->pending_reply_queue, next, nsq) { | ||
+ TAILQ_REMOVE(&asoc->pending_reply_queue, sq, next); | ||
+ if (sq->data) { | ||
+ sctp_m_freem(sq->data); | ||
+ sq->data = NULL; | ||
+ } | ||
+ sctp_free_remote_addr(sq->whoFrom); | ||
+ sq->whoFrom = NULL; | ||
+ sq->stcb = NULL; | ||
+ sctp_free_a_readq(stcb, sq); | ||
+ } | ||
+ TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) { | ||
+ TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); | ||
+ if (chk->data) { | ||
+ sctp_m_freem(chk->data); | ||
+ chk->data = NULL; | ||
+ } | ||
+ if (chk->holds_key_ref) | ||
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); | ||
+ sctp_free_remote_addr(chk->whoTo); | ||
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); | ||
+ SCTP_DECR_CHK_COUNT(); | ||
+ } | ||
+ TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) { | ||
+ TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next); | ||
+ if (chk->data) { | ||
+ sctp_m_freem(chk->data); | ||
+ chk->data = NULL; | ||
+ } | ||
+ if (chk->holds_key_ref) | ||
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); | ||
+ sctp_free_remote_addr(chk->whoTo); | ||
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); | ||
+ SCTP_DECR_CHK_COUNT(); | ||
+ } | ||
+ TAILQ_FOREACH_SAFE(aparam, &asoc->asconf_queue, next, naparam) { | ||
+ TAILQ_REMOVE(&asoc->asconf_queue, aparam, next); | ||
+ SCTP_FREE(aparam,SCTP_M_ASC_ADDR); | ||
+ } | ||
+ TAILQ_FOREACH_SAFE(aack, &asoc->asconf_ack_sent, next, naack) { | ||
+ TAILQ_REMOVE(&asoc->asconf_ack_sent, aack, next); | ||
+ if (aack->data != NULL) { | ||
+ sctp_m_freem(aack->data); | ||
+ } | ||
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), aack); | ||
+ } | ||
+ | ||
/* process the INIT-ACK info (my info) */ | ||
asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); | ||
asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); |
54 changes: 54 additions & 0 deletions
54
patches/usrsctp/cherry_picking_harden_the_handling_of_outgoing_streams.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: Michael Tuexen <tuexen@fh-muenster.de> | ||
Date: Mon, 14 Dec 2020 00:57:51 +0100 | ||
Subject: Cherry picking: Harden the handling of outgoing streams in case of an | ||
restart or INIT collision. | ||
|
||
This avouds an out-of-bounce access in case the peer can | ||
break the cookie signature. Thanks to Felix Wilhelm from Google for | ||
reporting the issue. | ||
|
||
diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c | ||
index 669b2b2131d6e1e844f98fc10547db1715e6a0bd..6a5bdba4264b47e10766467255dd9ebd5d135556 100755 | ||
--- a/usrsctplib/netinet/sctp_input.c | ||
+++ b/usrsctplib/netinet/sctp_input.c | ||
@@ -34,7 +34,7 @@ | ||
|
||
#if defined(__FreeBSD__) && !defined(__Userspace__) | ||
#include <sys/cdefs.h> | ||
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 368593 2020-12-12 22:23:45Z tuexen $"); | ||
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 368622 2020-12-13 23:51:51Z tuexen $"); | ||
#endif | ||
|
||
#include <netinet/sctp_os.h> | ||
@@ -1886,7 +1886,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, | ||
NULL); | ||
} | ||
asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); | ||
- asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); | ||
+ if (asoc->pre_open_streams < asoc->streamoutcnt) { | ||
+ asoc->pre_open_streams = asoc->streamoutcnt; | ||
+ } | ||
|
||
if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { | ||
/* Ok the peer probably discarded our | ||
@@ -2040,8 +2042,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, | ||
/* move to OPEN state, if not in SHUTDOWN_SENT */ | ||
SCTP_SET_STATE(stcb, SCTP_STATE_OPEN); | ||
} | ||
- asoc->pre_open_streams = | ||
- ntohs(initack_cp->init.num_outbound_streams); | ||
+ if (asoc->pre_open_streams < asoc->streamoutcnt) { | ||
+ asoc->pre_open_streams = asoc->streamoutcnt; | ||
+ } | ||
asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); | ||
asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; | ||
asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; | ||
@@ -2361,7 +2364,6 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, | ||
/* process the INIT-ACK info (my info) */ | ||
asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); | ||
asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); | ||
- asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); | ||
asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); | ||
asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; | ||
asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; |
127 changes: 127 additions & 0 deletions
127
patches/usrsctp/cherry_picking_improve_the_input_validation_and_processing_of.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: Michael Tuexen <tuexen@fh-muenster.de> | ||
Date: Tue, 29 Sep 2020 11:38:11 +0200 | ||
Subject: Cherry picking: Improve the input validation and processing of | ||
cookies. | ||
|
||
This avoids setting the association in an inconsistent | ||
state, which could result in a use-after-free situation. | ||
The issue can be triggered by a malicious peer, if the peer | ||
can modify the cookie without the local endpoint recognizing it. | ||
|
||
Thanks to Ned Williamson for reporting the issue. | ||
|
||
diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c | ||
index 2555eacd68a9bf8c5a29ee190ee6fc03f5c7699c..e2f03c73165d8e1ecd08b9f103afe03a3d2adb7f 100755 | ||
--- a/usrsctplib/netinet/sctp_input.c | ||
+++ b/usrsctplib/netinet/sctp_input.c | ||
@@ -34,7 +34,7 @@ | ||
|
||
#if defined(__FreeBSD__) && !defined(__Userspace__) | ||
#include <sys/cdefs.h> | ||
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 364268 2020-08-16 11:50:37Z tuexen $"); | ||
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 366248 2020-09-29 09:36:06Z tuexen $"); | ||
#endif | ||
|
||
#include <netinet/sctp_os.h> | ||
@@ -2260,10 +2260,6 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, | ||
vrf_id, port); | ||
return (NULL); | ||
} | ||
- /* get the correct sctp_nets */ | ||
- if (netp) | ||
- *netp = sctp_findnet(stcb, init_src); | ||
- | ||
asoc = &stcb->asoc; | ||
/* get scope variables out of cookie */ | ||
asoc->scope.ipv4_local_scope = cookie->ipv4_scope; | ||
@@ -2320,10 +2316,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, | ||
asoc->advanced_peer_ack_point = asoc->last_acked_seq; | ||
|
||
/* process the INIT info (peer's info) */ | ||
- if (netp) | ||
- retval = sctp_process_init(init_cp, stcb); | ||
- else | ||
- retval = 0; | ||
+ retval = sctp_process_init(init_cp, stcb); | ||
if (retval < 0) { | ||
#if defined(__APPLE__) && !defined(__Userspace__) | ||
atomic_add_int(&stcb->asoc.refcnt, 1); | ||
@@ -2506,19 +2499,21 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, | ||
*/ | ||
; | ||
} | ||
- /* since we did not send a HB make sure we don't double things */ | ||
- if ((netp) && (*netp)) | ||
- (*netp)->hb_responded = 1; | ||
- | ||
if (stcb->asoc.sctp_autoclose_ticks && | ||
sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { | ||
sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); | ||
} | ||
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); | ||
- if ((netp != NULL) && (*netp != NULL)) { | ||
+ *netp = sctp_findnet(stcb, init_src); | ||
+ if (*netp != NULL) { | ||
struct timeval old; | ||
|
||
- /* calculate the RTT and set the encaps port */ | ||
+ /* | ||
+ * Since we did not send a HB, make sure we don't double | ||
+ * things. | ||
+ */ | ||
+ (*netp)->hb_responded = 1; | ||
+ /* Calculate the RTT. */ | ||
old.tv_sec = cookie->time_entered.tv_sec; | ||
old.tv_usec = cookie->time_entered.tv_usec; | ||
sctp_calculate_rto(stcb, asoc, *netp, &old, SCTP_RTT_FROM_NON_DATA); | ||
diff --git a/usrsctplib/netinet/sctp_pcb.c b/usrsctplib/netinet/sctp_pcb.c | ||
index 2bae796e5ad5c7cc490ceb4fa01c5cc448499232..f439c78eb45969f46cc47ca90cd710279b675071 100755 | ||
--- a/usrsctplib/netinet/sctp_pcb.c | ||
+++ b/usrsctplib/netinet/sctp_pcb.c | ||
@@ -34,7 +34,7 @@ | ||
|
||
#if defined(__FreeBSD__) && !defined(__Userspace__) | ||
#include <sys/cdefs.h> | ||
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 364268 2020-08-16 11:50:37Z tuexen $"); | ||
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 366248 2020-09-29 09:36:06Z tuexen $"); | ||
#endif | ||
|
||
#include <netinet/sctp_os.h> | ||
@@ -4997,7 +4997,15 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, | ||
if ((ntohs(sin->sin_port) == 0) || | ||
(sin->sin_addr.s_addr == INADDR_ANY) || | ||
(sin->sin_addr.s_addr == INADDR_BROADCAST) || | ||
- IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { | ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) || | ||
+#if defined(__Userspace__) | ||
+ (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) != 0) || | ||
+ (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) != 0) && | ||
+ (SCTP_IPV6_V6ONLY(inp) != 0)))) { | ||
+#else | ||
+ (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) != 0) && | ||
+ (SCTP_IPV6_V6ONLY(inp) != 0))) { | ||
+#endif | ||
/* Invalid address */ | ||
SCTP_INP_RUNLOCK(inp); | ||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); | ||
@@ -5016,7 +5024,8 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, | ||
sin6 = (struct sockaddr_in6 *)firstaddr; | ||
if ((ntohs(sin6->sin6_port) == 0) || | ||
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || | ||
- IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { | ||
+ IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) || | ||
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)) { | ||
/* Invalid address */ | ||
SCTP_INP_RUNLOCK(inp); | ||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); | ||
@@ -5034,7 +5043,8 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, | ||
|
||
sconn = (struct sockaddr_conn *)firstaddr; | ||
if ((ntohs(sconn->sconn_port) == 0) || | ||
- (sconn->sconn_addr == NULL)) { | ||
+ (sconn->sconn_addr == NULL) || | ||
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) == 0)) { | ||
/* Invalid address */ | ||
SCTP_INP_RUNLOCK(inp); | ||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); |