doc/website/static/security/patches/SA-20:25/sctp.11.4.patch
Sergio Carlavilla Delgado 989d921f5d Migrate doc to Hugo/AsciiDoctor
I'm very pleased to announce the release of
our new website and documentation using
the new toolchain with Hugo and AsciiDoctor.

To get more information about the new toolchain
please read the FreeBSD Documentation Project Primer[1],
Hugo docs[2] and AsciiDoctor docs[3].

Acknowledgment:
Benedict Reuschling <bcr@>
Glen Barber <gjb@>
Hiroki Sato <hrs@>
Li-Wen Hsu <lwhsu@>
Sean Chittenden <seanc@>
The FreeBSD Foundation

[1] https://docs.FreeBSD.org/en/books/fdp-primer/
[2] https://gohugo.io/documentation/
[3] https://docs.asciidoctor.org/home/

Approved by:    doceng, core
2021-01-26 00:31:29 +01:00

305 lines
10 KiB
Diff

--- sys/netinet/sctp_input.c
+++ sys/netinet/sctp_input.c
@@ -846,7 +846,6 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
- SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -1995,7 +1994,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* send up all the data */
SCTP_TCB_SEND_LOCK(stcb);
- sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
+ sctp_report_all_outbound(stcb, 0, SCTP_SO_LOCKED);
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
stcb->asoc.strmout[i].chunks_on_queues = 0;
#if defined(SCTP_DETAILED_STR_STATS)
--- sys/netinet/sctp_output.c
+++ sys/netinet/sctp_output.c
@@ -13202,11 +13202,10 @@ sctp_lower_sosend(struct socket *so,
error = EINVAL;
goto out;
}
- SCTP_TCB_SEND_UNLOCK(stcb);
-
strm = &stcb->asoc.strmout[srcv->sinfo_stream];
if (strm->last_msg_incomplete == 0) {
do_a_copy_in:
+ SCTP_TCB_SEND_UNLOCK(stcb);
sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error);
if (error) {
goto out;
@@ -13232,13 +13231,11 @@ sctp_lower_sosend(struct socket *so,
if (sinfo_flags & SCTP_UNORDERED) {
SCTP_STAT_INCR(sctps_sends_with_unord);
}
+ sp->processing = 1;
TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp, 1);
- SCTP_TCB_SEND_UNLOCK(stcb);
} else {
- SCTP_TCB_SEND_LOCK(stcb);
sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead);
- SCTP_TCB_SEND_UNLOCK(stcb);
if (sp == NULL) {
/* ???? Huh ??? last msg is gone */
#ifdef INVARIANTS
@@ -13250,7 +13247,16 @@ sctp_lower_sosend(struct socket *so,
goto do_a_copy_in;
}
+ if (sp->processing) {
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+ error = EINVAL;
+ goto out;
+ } else {
+ sp->processing = 1;
+ }
}
+ SCTP_TCB_SEND_UNLOCK(stcb);
while (uio->uio_resid > 0) {
/* How much room do we have? */
struct mbuf *new_tail, *mm;
@@ -13275,20 +13281,29 @@ sctp_lower_sosend(struct socket *so,
if (mm) {
sctp_m_freem(mm);
}
+ SCTP_TCB_SEND_LOCK(stcb);
+ if (sp != NULL) {
+ sp->processing = 0;
+ }
+ SCTP_TCB_SEND_UNLOCK(stcb);
goto out;
}
/* Update the mbuf and count */
SCTP_TCB_SEND_LOCK(stcb);
- if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+ (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
/*
* we need to get out. Peer probably
* aborted.
*/
sctp_m_freem(mm);
- if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED) {
+ if (stcb->asoc.state & SCTP_STATE_WAS_ABORTED) {
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
error = ECONNRESET;
}
+ if (sp != NULL) {
+ sp->processing = 0;
+ }
SCTP_TCB_SEND_UNLOCK(stcb);
goto out;
}
@@ -13348,6 +13363,11 @@ sctp_lower_sosend(struct socket *so,
/* wait for space now */
if (non_blocking) {
/* Non-blocking io in place out */
+ SCTP_TCB_SEND_LOCK(stcb);
+ if (sp != NULL) {
+ sp->processing = 0;
+ }
+ SCTP_TCB_SEND_UNLOCK(stcb);
goto skip_out_eof;
}
/* What about the INIT, send it maybe */
@@ -13471,6 +13491,11 @@ sctp_lower_sosend(struct socket *so,
}
}
SOCKBUF_UNLOCK(&so->so_snd);
+ SCTP_TCB_SEND_LOCK(stcb);
+ if (sp != NULL) {
+ sp->processing = 0;
+ }
+ SCTP_TCB_SEND_UNLOCK(stcb);
goto out_unlocked;
}
@@ -13480,12 +13505,19 @@ sctp_lower_sosend(struct socket *so,
}
}
SOCKBUF_UNLOCK(&so->so_snd);
+ SCTP_TCB_SEND_LOCK(stcb);
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ if (sp != NULL) {
+ sp->processing = 0;
+ }
+ SCTP_TCB_SEND_UNLOCK(stcb);
goto out_unlocked;
}
+ SCTP_TCB_SEND_UNLOCK(stcb);
}
SCTP_TCB_SEND_LOCK(stcb);
- if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
+ (stcb->asoc.state & SCTP_STATE_WAS_ABORTED)) {
SCTP_TCB_SEND_UNLOCK(stcb);
goto out_unlocked;
}
@@ -13501,6 +13533,7 @@ sctp_lower_sosend(struct socket *so,
strm->last_msg_incomplete = 0;
asoc->stream_locked = 0;
}
+ sp->processing = 0;
} else {
SCTP_PRINTF("Huh no sp TSNH?\n");
strm->last_msg_incomplete = 0;
--- sys/netinet/sctp_pcb.c
+++ sys/netinet/sctp_pcb.c
@@ -4725,6 +4725,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* there is no asoc, really TSNH :-0 */
return (1);
}
+ SCTP_TCB_SEND_LOCK(stcb);
if (stcb->asoc.alternate) {
sctp_free_remote_addr(stcb->asoc.alternate);
stcb->asoc.alternate = NULL;
@@ -4759,6 +4760,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* nope, reader or writer in the way */
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
/* no asoc destroyed */
+ SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 8);
@@ -4827,6 +4829,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
}
+ SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))
@@ -4860,10 +4863,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
if (from_inpcbfree == SCTP_NORMAL_PROC) {
atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_INFO_WLOCK();
SCTP_INP_WLOCK(inp);
SCTP_TCB_LOCK(stcb);
+ SCTP_TCB_SEND_LOCK(stcb);
}
/* Double check the GONE flag */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
@@ -4911,6 +4916,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_INP_INFO_WUNLOCK();
SCTP_INP_WUNLOCK(inp);
}
+ SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
return (0);
}
@@ -4942,7 +4948,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
* in case.
*/
/* anything on the wheel needs to be removed */
- SCTP_TCB_SEND_LOCK(stcb);
for (i = 0; i < asoc->streamoutcnt; i++) {
struct sctp_stream_out *outs;
@@ -4973,7 +4978,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED);
}
}
- SCTP_TCB_SEND_UNLOCK(stcb);
/* sa_ignore FREED_MEMORY */
TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
@@ -5175,6 +5179,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* Insert new items here :> */
/* Get rid of LOCK */
+ SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
--- sys/netinet/sctp_structs.h
+++ sys/netinet/sctp_structs.h
@@ -535,6 +535,7 @@ struct sctp_stream_queue_pending {
uint8_t sender_all_done;
uint8_t put_last_out;
uint8_t discard_rest;
+ uint8_t processing;
};
/*
--- sys/netinet/sctputil.c
+++ sys/netinet/sctputil.c
@@ -3921,7 +3921,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
}
void
-sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
+sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
@@ -3947,9 +3947,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock,
return;
}
/* now through all the gunk freeing chunks */
- if (holds_lock == 0) {
- SCTP_TCB_SEND_LOCK(stcb);
- }
/* sent queue SHOULD be empty */
TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
@@ -4026,10 +4023,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock,
/* sa_ignore FREED_MEMORY */
}
}
-
- if (holds_lock == 0) {
- SCTP_TCB_SEND_UNLOCK(stcb);
- }
}
void
@@ -4053,8 +4046,11 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
return;
}
+ SCTP_TCB_SEND_LOCK(stcb);
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
/* Tell them we lost the asoc */
- sctp_report_all_outbound(stcb, error, 0, so_locked);
+ sctp_report_all_outbound(stcb, error, so_locked);
+ SCTP_TCB_SEND_UNLOCK(stcb);
if (from_peer) {
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
} else {
@@ -4086,7 +4082,6 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (stcb != NULL) {
/* We have a TCB to abort, send notification too */
sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
- SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
/* Ok, now lets free it */
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
@@ -4196,8 +4191,6 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
}
return;
- } else {
- SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
}
/* notify the peer */
sctp_send_abort_tcb(stcb, op_err, so_locked);
--- sys/netinet/sctputil.h
+++ sys/netinet/sctputil.h
@@ -166,7 +166,7 @@ void sctp_stop_timers_for_shutdown(struct sctp_tcb *);
void sctp_stop_association_timers(struct sctp_tcb *, bool);
void
-sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int
+sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif