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.
#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>
@@ -1877,7 +1877,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
@@ -2030,7 +2032,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;
@@ -2347,7 +2351,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;
