The branch main has been updated by tuexen:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=101a0f09e8baf8293e1eeb591de18caf15e49e00

commit 101a0f09e8baf8293e1eeb591de18caf15e49e00
Author:     Michael Tuexen <[email protected]>
AuthorDate: 2024-08-03 11:27:18 +0000
Commit:     Michael Tuexen <[email protected]>
CommitDate: 2024-08-03 11:27:18 +0000

    sctp: improve input validation for data chunks
    
    fsn_included should only be considered, if first_frag_seen is true.
    Also, fix the resetting of the control structure, if stream queues
    are flushed.
    This fixes a bug where a legitimate message sequence was incorrectly
    classified as illegitimate.
    Thanks to Victor Boivie for reporting the issue on the userland
    stack.
    
    MFC after:              3 days
---
 sys/netinet/sctp_indata.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 4c40e0de4326..693de313b970 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -746,21 +746,6 @@ sctp_build_readq_entry_from_ctl(struct sctp_queued_to_read 
*nc, struct sctp_queu
        nc->do_not_ref_stcb = control->do_not_ref_stcb;
 }
 
-static void
-sctp_reset_a_control(struct sctp_queued_to_read *control,
-    struct sctp_inpcb *inp, uint32_t tsn)
-{
-       control->fsn_included = tsn;
-       if (control->on_read_q) {
-               /*
-                * We have to purge it from there, hopefully this will work
-                * :-)
-                */
-               TAILQ_REMOVE(&inp->read_queue, control, next);
-               control->on_read_q = 0;
-       }
-}
-
 static int
 sctp_handle_old_unordered_data(struct sctp_tcb *stcb,
     struct sctp_association *asoc,
@@ -1922,7 +1907,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct 
sctp_association *asoc,
                                SCTP_SNPRINTF(msg, sizeof(msg), "Duplicate 
MID=%8.8x detected.", mid);
                                goto err_out;
                        } else {
-                               if ((tsn == control->fsn_included + 1) &&
+                               if ((control->first_frag_seen) &&
+                                   (tsn == control->fsn_included + 1) &&
                                    (control->end_added == 0)) {
                                        SCTP_SNPRINTF(msg, sizeof(msg),
                                            "Illegal message sequence, missing 
end for MID: %8.8x",
@@ -5430,12 +5416,25 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
                sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
        }
        if (!TAILQ_EMPTY(&control->reasm)) {
-               /* This has to be old data, unordered */
+               KASSERT(!asoc->idata_supported,
+                   ("Reassembly queue not empty for I-DATA"));
+               KASSERT(!ordered,
+                   ("Reassembly queue not empty for ordered data"));
                if (control->data) {
                        sctp_m_freem(control->data);
                        control->data = NULL;
                }
-               sctp_reset_a_control(control, stcb->sctp_ep, cumtsn);
+               control->fsn_included = 0xffffffff;
+               control->first_frag_seen = 0;
+               control->last_frag_seen = 0;
+               if (control->on_read_q) {
+                       /*
+                        * We have to purge it from there, hopefully this
+                        * will work :-)
+                        */
+                       TAILQ_REMOVE(&stcb->sctp_ep->read_queue, control, next);
+                       control->on_read_q = 0;
+               }
                chk = TAILQ_FIRST(&control->reasm);
                if (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
                        TAILQ_REMOVE(&control->reasm, chk, sctp_next);

Reply via email to