mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-23 02:41:58 +01:00
Detect and handle an invalid reassembly constellation, which results in
a memory leak. Thanks to Felix Weinrank for finding this issue using fuzz testing the userland stack. MFC after: 1 week
This commit is contained in:
parent
e9b21d432b
commit
91e04f9e7a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=363440
@ -795,6 +795,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define SCTP_LOC_34 0x00000022
|
||||
#define SCTP_LOC_35 0x00000023
|
||||
#define SCTP_LOC_36 0x00000024
|
||||
#define SCTP_LOC_37 0x00000025
|
||||
|
||||
/* Free assoc codes */
|
||||
#define SCTP_NORMAL_PROC 0
|
||||
|
@ -1567,6 +1567,15 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
chk->rec.data.fsn);
|
||||
TAILQ_FOREACH(at, &control->reasm, sctp_next) {
|
||||
if (SCTP_TSN_GT(at->rec.data.fsn, chk->rec.data.fsn)) {
|
||||
if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
|
||||
/* Last not at the end? huh? */
|
||||
SCTPDBG(SCTP_DEBUG_XXX,
|
||||
"Last fragment not last in list: -- abort\n");
|
||||
sctp_abort_in_reasm(stcb, control,
|
||||
chk, abort_flag,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_14);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* This one in queue is bigger than the new
|
||||
* one, insert the new one before at.
|
||||
@ -1597,7 +1606,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
at->rec.data.fsn);
|
||||
sctp_abort_in_reasm(stcb, control,
|
||||
chk, abort_flag,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_14);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_15);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1751,7 +1760,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
* Need to send an abort since we had a empty data chunk.
|
||||
*/
|
||||
op_err = sctp_generate_no_user_data_cause(tsn);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
*abort_flag = 1;
|
||||
return (0);
|
||||
@ -1888,7 +1897,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
SCTP_SNPRINTF(msg, sizeof(msg), "Reassembly problem (MID=%8.8x)", mid);
|
||||
err_out:
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
*abort_flag = 1;
|
||||
return (0);
|
||||
@ -2023,7 +2032,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
(uint16_t)mid);
|
||||
}
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_18;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
*abort_flag = 1;
|
||||
return (0);
|
||||
@ -2597,7 +2606,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap)
|
||||
if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
|
||||
stcb->sctp_ep, stcb, NULL,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_18);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_19);
|
||||
}
|
||||
sctp_send_shutdown(stcb,
|
||||
((stcb->asoc.alternate) ? stcb->asoc.alternate : stcb->asoc.primary_destination));
|
||||
@ -2648,7 +2657,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap)
|
||||
* there are gaps or duplicates.
|
||||
*/
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_19);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
|
||||
sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
|
||||
}
|
||||
} else {
|
||||
@ -2750,7 +2759,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
|
||||
|
||||
SCTP_SNPRINTF(msg, sizeof(msg), "%s", "DATA chunk received when I-DATA was negotiated");
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_20;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_21;
|
||||
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return (2);
|
||||
}
|
||||
@ -2761,7 +2770,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
|
||||
|
||||
SCTP_SNPRINTF(msg, sizeof(msg), "%s", "I-DATA chunk received when DATA was negotiated");
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_21;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_22;
|
||||
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return (2);
|
||||
}
|
||||
@ -2786,7 +2795,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
|
||||
ch->chunk_type == SCTP_DATA ? "DATA" : "I-DATA",
|
||||
chk_length);
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_22;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_23;
|
||||
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return (2);
|
||||
}
|
||||
@ -2874,7 +2883,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
|
||||
|
||||
SCTP_SNPRINTF(msg, sizeof(msg), "Chunk of length %u", chk_length);
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_23;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
|
||||
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return (2);
|
||||
}
|
||||
@ -4025,7 +4034,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
"Cum ack %8.8x greater or equal than TSN %8.8x",
|
||||
cumack, send_s);
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return;
|
||||
}
|
||||
@ -4201,7 +4210,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
net->dest_state &= ~SCTP_ADDR_PF;
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
|
||||
stcb->sctp_ep, stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_25);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
|
||||
asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
|
||||
/* Done with this net */
|
||||
@ -4279,7 +4288,7 @@ again:
|
||||
} else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
|
||||
stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_27);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4332,7 +4341,7 @@ again:
|
||||
*abort_now = 1;
|
||||
/* XXX */
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_27;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_28;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return;
|
||||
}
|
||||
@ -4548,7 +4557,7 @@ hopeless_peer:
|
||||
"Cum ack %8.8x greater or equal than TSN %8.8x",
|
||||
cum_ack, send_s);
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_28;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_29;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return;
|
||||
}
|
||||
@ -4580,7 +4589,7 @@ hopeless_peer:
|
||||
/* stop any timers */
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
|
||||
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_29);
|
||||
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30);
|
||||
net->partial_bytes_acked = 0;
|
||||
net->flight_size = 0;
|
||||
}
|
||||
@ -4780,14 +4789,14 @@ hopeless_peer:
|
||||
if (net->new_pseudo_cumack)
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
|
||||
stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_30);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_31);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (accum_moved) {
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
|
||||
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_31);
|
||||
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4950,7 +4959,7 @@ hopeless_peer:
|
||||
net->dest_state &= ~SCTP_ADDR_PF;
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
|
||||
stcb->sctp_ep, stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_33);
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
|
||||
asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
|
||||
/* Done with this net */
|
||||
@ -4975,7 +4984,7 @@ hopeless_peer:
|
||||
/* stop all timers */
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
|
||||
stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_33);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_34);
|
||||
net->flight_size = 0;
|
||||
net->partial_bytes_acked = 0;
|
||||
}
|
||||
@ -5013,7 +5022,7 @@ hopeless_peer:
|
||||
*abort_now = 1;
|
||||
/* XXX */
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_34;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_35;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return;
|
||||
}
|
||||
@ -5162,7 +5171,7 @@ again:
|
||||
} else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
|
||||
stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_35);
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_36);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5565,7 +5574,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
|
||||
"New cum ack %8.8x too high, highest TSN %8.8x",
|
||||
new_cum_tsn, asoc->highest_tsn_inside_map);
|
||||
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_36;
|
||||
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_37;
|
||||
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user