]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/file.data: fix mixing transforms (file api)
authorVictor Julien <victor@inliniac.net>
Thu, 25 Feb 2021 19:07:41 +0000 (20:07 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 26 Feb 2021 09:42:50 +0000 (10:42 +0100)
Fix handling of file progress tracking for regular file.data along
with transform combinations for the part of the implementation that
uses the File API.

This is done by implementing the 'base id' logic.

Related tickets: #4361 #4199 #3616

(cherry picked from commit 54ad7de9cea22b9a3c3e7cc64145155126f4dada)

src/detect-file-data.c

index 08ca66547a62f3529dbb22a8c8933ccb58537e0a..47eb57943a391b7dadec03ef14f71b01351ca128 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2020 Open Information Security Foundation
+/* Copyright (C) 2007-2021 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -413,19 +413,50 @@ static InspectionBuffer *HttpServerBodyGetDataCallback(DetectEngineThreadCtx *de
 
 /* file API based inspection */
 
+static inline InspectionBuffer *FiledataWithXformsGetDataCallback(DetectEngineThreadCtx *det_ctx,
+        const DetectEngineTransforms *transforms, const int list_id, int local_file_id,
+        InspectionBuffer *base_buffer, const bool first)
+{
+    InspectionBufferMultipleForList *fb = InspectionBufferGetMulti(det_ctx, list_id);
+    InspectionBuffer *buffer = InspectionBufferMultipleForListGet(fb, local_file_id);
+    if (buffer == NULL) {
+        SCLogDebug("list_id: %d: no buffer", list_id);
+        return NULL;
+    }
+    if (!first && buffer->inspect != NULL) {
+        SCLogDebug("list_id: %d: returning %p", list_id, buffer);
+        return buffer;
+    }
+
+    InspectionBufferSetup(det_ctx, list_id, buffer, base_buffer->inspect, base_buffer->inspect_len);
+    buffer->inspect_offset = base_buffer->inspect_offset;
+    InspectionBufferApplyTransforms(buffer, transforms);
+    SCLogDebug("xformed buffer %p size %u", buffer, buffer->inspect_len);
+    SCReturnPtr(buffer, "InspectionBuffer");
+}
+
 static InspectionBuffer *FiledataGetDataCallback(DetectEngineThreadCtx *det_ctx,
-        const DetectEngineTransforms *transforms,
-        Flow *f, uint8_t flow_flags, File *cur_file,
-        int list_id, int local_file_id, bool first)
+        const DetectEngineTransforms *transforms, Flow *f, uint8_t flow_flags, File *cur_file,
+        const int list_id, const int base_id, int local_file_id, bool first)
 {
     SCEnter();
+    SCLogDebug(
+            "starting: list_id %d base_id %d first %s", list_id, base_id, first ? "true" : "false");
 
-    InspectionBufferMultipleForList *fb = InspectionBufferGetMulti(det_ctx, list_id);
+    InspectionBufferMultipleForList *fb = InspectionBufferGetMulti(det_ctx, base_id);
     InspectionBuffer *buffer = InspectionBufferMultipleForListGet(fb, local_file_id);
+    SCLogDebug("base: fb %p buffer %p", fb, buffer);
     if (buffer == NULL)
         return NULL;
-    if (!first && buffer->inspect != NULL)
+    if (base_id != list_id && buffer->inspect != NULL) {
+        SCLogDebug("handle xform %s", (list_id != base_id) ? "true" : "false");
+        return FiledataWithXformsGetDataCallback(
+                det_ctx, transforms, list_id, local_file_id, buffer, first);
+    }
+    if (!first && buffer->inspect != NULL) {
+        SCLogDebug("base_id: %d, not first: use %p", base_id, buffer);
         return buffer;
+    }
 
     const uint64_t file_size = FileDataSize(cur_file);
     const DetectEngineCtx *de_ctx = det_ctx->de_ctx;
@@ -471,16 +502,21 @@ static InspectionBuffer *FiledataGetDataCallback(DetectEngineThreadCtx *det_ctx,
                "; data_len %" PRIu32 "; file_size %" PRIu64,
             list_id, buffer->inspect_offset, buffer->inspect_len, data_len, file_size);
     buffer->inspect_offset = cur_file->content_inspected;
-    InspectionBufferApplyTransforms(buffer, transforms);
-    SCLogDebug("[list %d] [after] buffer offset %" PRIu64 "; buffer len %" PRIu32, list_id,
-            buffer->inspect_offset, buffer->inspect_len);
-
-    SCLogDebug("[list %d] content_inspected %" PRIu64, list_id, cur_file->content_inspected);
 
-    SCLogDebug("[list %d] file_data buffer %p, data %p len %u offset %" PRIu64, list_id, buffer,
-            buffer->inspect, buffer->inspect_len, buffer->inspect_offset);
+    /* update inspected tracker */
+    cur_file->content_inspected = buffer->inspect_len + buffer->inspect_offset;
+    SCLogDebug("content inspected: %" PRIu64, cur_file->content_inspected);
 
-    SCReturnPtr(buffer, "InspectionBuffer");
+    /* get buffer for the list id if it is different from the base id */
+    if (list_id != base_id) {
+        SCLogDebug("regular %d has been set up: now handle xforms id %d", base_id, list_id);
+        InspectionBuffer *tbuffer = FiledataWithXformsGetDataCallback(
+                det_ctx, transforms, list_id, local_file_id, buffer, first);
+        SCReturnPtr(tbuffer, "InspectionBuffer");
+    } else {
+        SCLogDebug("regular buffer %p size %u", buffer, buffer->inspect_len);
+        SCReturnPtr(buffer, "InspectionBuffer");
+    }
 }
 
 static int DetectEngineInspectFiledata(
@@ -508,8 +544,8 @@ static int DetectEngineInspectFiledata(
         if (file->txid != tx_id)
             continue;
 
-        InspectionBuffer *buffer = FiledataGetDataCallback(det_ctx,
-            transforms, f, flags, file, engine->sm_list, local_file_id, false);
+        InspectionBuffer *buffer = FiledataGetDataCallback(det_ctx, transforms, f, flags, file,
+                engine->sm_list, engine->sm_list_base, local_file_id, false);
         if (buffer == NULL)
             continue;
 
@@ -527,8 +563,6 @@ static int DetectEngineInspectFiledata(
                                               buffer->inspect_len,
                                               buffer->inspect_offset, ciflags,
                                               DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
-        /* update inspected tracker */
-        file->content_inspected = buffer->inspect_len + buffer->inspect_offset;
         if (match == 1) {
             r = 1;
             break;
@@ -544,6 +578,7 @@ static int DetectEngineInspectFiledata(
 
 typedef struct PrefilterMpmFiledata {
     int list_id;
+    int base_list_id;
     const MpmCtx *mpm_ctx;
     const DetectEngineTransforms *transforms;
 } PrefilterMpmFiledata;
@@ -577,8 +612,8 @@ static void PrefilterTxFiledata(DetectEngineThreadCtx *det_ctx,
             if (file->txid != idx)
                 continue;
 
-            InspectionBuffer *buffer = FiledataGetDataCallback(det_ctx,
-                    ctx->transforms, f, flags, file, list_id, local_file_id, true);
+            InspectionBuffer *buffer = FiledataGetDataCallback(det_ctx, ctx->transforms, f, flags,
+                    file, list_id, ctx->base_list_id, local_file_id, true);
             if (buffer == NULL)
                 continue;
 
@@ -605,6 +640,7 @@ int PrefilterMpmFiledataRegister(DetectEngineCtx *de_ctx,
     if (pectx == NULL)
         return -1;
     pectx->list_id = list_id;
+    pectx->base_list_id = mpm_reg->sm_list_base;
     pectx->mpm_ctx = mpm_ctx;
     pectx->transforms = &mpm_reg->transforms;