Skip to content

Commit

Permalink
chore: cherry-pick 2c26785, b03de8b and a3c3ef6 from usrsctp. (#27491)
Browse files Browse the repository at this point in the history
* chore: cherry-pick 2c26785, b03de8b and a3c3ef6 from usrsctp.

* update patches

Co-authored-by: Electron Bot <electron@github.com>
  • Loading branch information
ppontes and electron-bot committed Jan 26, 2021
1 parent 47640ea commit 70526f8
Show file tree
Hide file tree
Showing 5 changed files with 291 additions and 1 deletion.
4 changes: 3 additions & 1 deletion patches/config.json
Expand Up @@ -15,5 +15,7 @@

"src/electron/patches/sqlite": "src/third_party/sqlite/src",

"src/electron/patches/icu": "src/third_party/icu"
"src/electron/patches/icu": "src/third_party/icu",

"src/electron/patches/usrsctp": "src/third_party/usrsctp/usrsctplib"
}
3 changes: 3 additions & 0 deletions patches/usrsctp/.patches
@@ -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
@@ -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);
@@ -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;
@@ -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);

0 comments on commit 70526f8

Please sign in to comment.