]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
stream: fix raw reassembly flag issue
authorVictor Julien <victor@inliniac.net>
Fri, 11 Apr 2014 15:31:46 +0000 (17:31 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 22 Apr 2014 08:19:42 +0000 (10:19 +0200)
AppLayer reassembly correctly only flags a segment as done when it's
completely used in reassembly. Raw reassembly could flag a partially
used segment as complete as well. In this case the segment could be
discarded early. Further reassembly would miss data, leading to a
gap. Due to this, up to 'window size' bytes worth of segments could
remain in the session for a long time, leading to memory resource
pressure.

This patch sets the flag correctly.

src/stream-tcp-reassemble.c

index 105e5d042da81386eb8b4d8709424799e355d65f..5b34f8524e9e4ad429cdc496c813495c80767603 100644 (file)
@@ -3221,8 +3221,10 @@ int StreamTcpReassembleAppLayer (ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
         TcpSegment *next_seg = seg->next;
         next_seq = seg->seq + seg->payload_len;
         if (partial == FALSE) {
-            SCLogDebug("fully done with segment in app layer reassembly");
+            SCLogDebug("fully done with segment in app layer reassembly (seg %p seq %"PRIu32")",
+                    seg, seg->seq);
             seg->flags |= SEGMENTTCP_FLAG_APPLAYER_PROCESSED;
+            SCLogDebug("flags now %02x", seg->flags);
         } else {
             SCLogDebug("not yet fully done with segment in app layer reassembly");
         }
@@ -3300,9 +3302,9 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
     /* loop through the segments and fill one or more msgs */
     for (; seg != NULL && SEQ_LT(seg->seq, stream->last_ack);)
     {
-        SCLogDebug("seg %p, SEQ %"PRIu32", LEN %"PRIu16", SUM %"PRIu32,
+        SCLogDebug("seg %p, SEQ %"PRIu32", LEN %"PRIu16", SUM %"PRIu32", flags %02x",
                 seg, seg->seq, seg->payload_len,
-                (uint32_t)(seg->seq + seg->payload_len));
+                (uint32_t)(seg->seq + seg->payload_len), seg->flags);
 
         if ((p->flow->flags & FLOW_NO_APPLAYER_INSPECTION) ||
             (stream->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
@@ -3405,6 +3407,8 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
             }
         }
 
+        int partial = FALSE;
+
         /* if the segment ends beyond ra_base_seq we need to consider it */
         if (SEQ_GT((seg->seq + seg->payload_len), ra_base_seq+1)) {
             SCLogDebug("seg->seq %" PRIu32 ", seg->payload_len %" PRIu32 ", "
@@ -3422,6 +3426,7 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
                     } else {
                         payload_len = (stream->last_ack - seg->seq) - payload_offset;
                     }
+                    partial = TRUE;
                 } else {
                     payload_len = seg->payload_len - payload_offset;
                 }
@@ -3435,6 +3440,7 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
 
                 if (SEQ_LT(stream->last_ack, (seg->seq + seg->payload_len))) {
                     payload_len = stream->last_ack - seg->seq;
+                    partial = TRUE;
                 } else {
                     payload_len = seg->payload_len;
                 }
@@ -3564,8 +3570,15 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
 
         /* done with this segment, return it to the pool */
         TcpSegment *next_seg = seg->next;
-        seg->flags |= SEGMENTTCP_FLAG_RAW_PROCESSED;
         next_seq = seg->seq + seg->payload_len;
+        if (partial == FALSE) {
+            SCLogDebug("fully done with segment in raw reassembly (seg %p seq %"PRIu32")",
+                    seg, seg->seq);
+            seg->flags |= SEGMENTTCP_FLAG_RAW_PROCESSED;
+            SCLogDebug("flags now %02x", seg->flags);
+        } else {
+            SCLogDebug("not yet fully done with segment in raw reassembly");
+        }
         seg = next_seg;
     }