]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: optimize mpm-engine setup
authorVictor Julien <vjulien@oisf.net>
Fri, 1 Apr 2022 10:22:51 +0000 (12:22 +0200)
committerVictor Julien <vjulien@oisf.net>
Mon, 4 Apr 2022 15:15:42 +0000 (17:15 +0200)
Instead of a loop over the rules in a group *per engine* do a single
loop in which all the engines are prepared in parallel.

src/detect-engine-mpm.c

index 2af7df9439dffc295fa1b69e48102121ca641d46..c5cce5559d568af1ae3ae9f81ddb53d78bc876eb 100644 (file)
@@ -1694,69 +1694,47 @@ MpmStore *MpmStorePrepareBuffer(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
     }
 }
 
-static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx,
-        SigGroupHead *sgh, const DetectBufferMpmRegistery *am)
-{
-    const Signature *s = NULL;
-    uint32_t sig;
-    uint32_t cnt = 0;
-    uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
-    uint8_t sids_array[max_sid];
-    memset(sids_array, 0x00, max_sid);
+struct SidsArray {
+    uint8_t *sids_array;
+    uint32_t sids_array_size;
+    /* indicates this has an active engine */
+    bool active;
+
+    enum DetectBufferMpmType type;
+};
 
+static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
+        const DetectBufferMpmRegistery *am, const struct SidsArray *sa)
+{
     SCLogDebug("handling %s direction %s for list %d", am->name,
             am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
             am->sm_list);
 
-    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
-        s = sgh->init->match_array[sig];
-        if (s == NULL)
-            continue;
-
-        if (s->init_data->mpm_sm == NULL)
-            continue;
-
-        if ((s->flags & am->direction) == 0)
-            continue;
-
-        int list = s->init_data->mpm_sm_list;
-        if (list < 0)
-            continue;
-
-        if (list != am->sm_list)
-            continue;
-
-        sids_array[s->num / 8] |= 1 << (s->num % 8);
-        cnt++;
-    }
-
-    if (cnt == 0)
+    if (sa->active == false || sa->sids_array_size == 0 || sa->sids_array == NULL)
         return NULL;
 
-    MpmStore lookup = { sids_array, max_sid, am->direction,
-        MPMB_MAX, am->sm_list, 0, NULL};
+    MpmStore lookup = { sa->sids_array, sa->sids_array_size, am->direction, MPMB_MAX, am->sm_list,
+        0, NULL };
     SCLogDebug("am->direction %d am->sm_list %d",
             am->direction, am->sm_list);
 
     MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
     if (result == NULL) {
-        SCLogDebug("new unique mpm for %s %s: %u patterns",
-                am->name,
-                am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
-                cnt);
+        SCLogDebug("new unique mpm for %s %s", am->name,
+                am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient");
 
         MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
         if (copy == NULL)
             return NULL;
-        uint8_t *sids = SCCalloc(1, max_sid);
+        uint8_t *sids = SCCalloc(1, sa->sids_array_size);
         if (sids == NULL) {
             SCFree(copy);
             return NULL;
         }
 
-        memcpy(sids, sids_array, max_sid);
+        memcpy(sids, sa->sids_array, sa->sids_array_size);
         copy->sid_array = sids;
-        copy->sid_array_size = max_sid;
+        copy->sid_array_size = sa->sids_array_size;
         copy->buffer = MPMB_MAX;
         copy->direction = am->direction;
         copy->sm_list = am->sm_list;
@@ -1772,62 +1750,35 @@ static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx,
     return NULL;
 }
 
-static MpmStore *MpmStorePrepareBufferPkt(DetectEngineCtx *de_ctx,
-        SigGroupHead *sgh, const DetectBufferMpmRegistery *am)
+static MpmStore *MpmStorePrepareBufferPkt(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
+        const DetectBufferMpmRegistery *am, const struct SidsArray *sa)
 {
-    const Signature *s = NULL;
-    uint32_t sig;
-    uint32_t cnt = 0;
-    uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
-    uint8_t sids_array[max_sid];
-    memset(sids_array, 0x00, max_sid);
-
     SCLogDebug("handling %s for list %d", am->name,
             am->sm_list);
 
-    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
-        s = sgh->init->match_array[sig];
-        if (s == NULL)
-            continue;
-
-        if (s->init_data->mpm_sm == NULL)
-            continue;
-
-        int list = s->init_data->mpm_sm_list;
-        if (list < 0)
-            continue;
-
-        if (list != am->sm_list)
-            continue;
-
-        sids_array[s->num / 8] |= 1 << (s->num % 8);
-        cnt++;
-    }
-
-    if (cnt == 0)
+    if (sa->active == false || sa->sids_array_size == 0 || sa->sids_array == NULL)
         return NULL;
 
-    MpmStore lookup = { sids_array, max_sid, SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT,
-        MPMB_MAX, am->sm_list, 0, NULL};
+    MpmStore lookup = { sa->sids_array, sa->sids_array_size, SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT,
+        MPMB_MAX, am->sm_list, 0, NULL };
     SCLogDebug("am->sm_list %d", am->sm_list);
 
     MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
     if (result == NULL) {
-        SCLogDebug("new unique mpm for %s: %u patterns",
-                am->name, cnt);
+        SCLogDebug("new unique mpm for %s", am->name);
 
         MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
         if (copy == NULL)
             return NULL;
-        uint8_t *sids = SCCalloc(1, max_sid);
+        uint8_t *sids = SCCalloc(1, sa->sids_array_size);
         if (sids == NULL) {
             SCFree(copy);
             return NULL;
         }
 
-        memcpy(sids, sids_array, max_sid);
+        memcpy(sids, sa->sids_array, sa->sids_array_size);
         copy->sid_array = sids;
-        copy->sid_array_size = max_sid;
+        copy->sid_array_size = sa->sids_array_size;
         copy->buffer = MPMB_MAX;
         copy->direction = SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT;
         copy->sm_list = am->sm_list;
@@ -1843,62 +1794,34 @@ static MpmStore *MpmStorePrepareBufferPkt(DetectEngineCtx *de_ctx,
     return NULL;
 }
 
-static MpmStore *MpmStorePrepareBufferFrame(
-        DetectEngineCtx *de_ctx, SigGroupHead *sgh, const DetectBufferMpmRegistery *am)
+static MpmStore *MpmStorePrepareBufferFrame(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
+        const DetectBufferMpmRegistery *am, const struct SidsArray *sa)
 {
-    const Signature *s = NULL;
-    uint32_t sig;
-    uint32_t cnt = 0;
-    uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
-    uint8_t sids_array[max_sid];
-    memset(sids_array, 0x00, max_sid);
-
     SCLogDebug("handling %s for list %d", am->name, am->sm_list);
 
-    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
-        s = sgh->init->match_array[sig];
-        if (s == NULL)
-            continue;
-
-        if (s->init_data->mpm_sm == NULL)
-            continue;
-
-        if ((s->flags & am->direction) == 0)
-            continue;
-
-        int list = s->init_data->mpm_sm_list;
-        if (list < 0)
-            continue;
-
-        if (list != am->sm_list)
-            continue;
-
-        sids_array[s->num / 8] |= 1 << (s->num % 8);
-        cnt++;
-    }
-
-    if (cnt == 0)
+    if (sa->active == false || sa->sids_array_size == 0 || sa->sids_array == NULL)
         return NULL;
 
-    MpmStore lookup = { sids_array, max_sid, am->direction, MPMB_MAX, am->sm_list, 0, NULL };
+    MpmStore lookup = { sa->sids_array, sa->sids_array_size, am->direction, MPMB_MAX, am->sm_list,
+        0, NULL };
     SCLogDebug("am->sm_list %d", am->sm_list);
 
     MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
     if (result == NULL) {
-        SCLogDebug("new unique mpm for %s: %u patterns", am->name, cnt);
+        SCLogDebug("new unique mpm for %s", am->name);
 
         MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
         if (copy == NULL)
             return NULL;
-        uint8_t *sids = SCCalloc(1, max_sid);
+        uint8_t *sids = SCCalloc(1, sa->sids_array_size);
         if (sids == NULL) {
             SCFree(copy);
             return NULL;
         }
 
-        memcpy(sids, sids_array, max_sid);
+        memcpy(sids, sa->sids_array, sa->sids_array_size);
         copy->sid_array = sids;
-        copy->sid_array_size = max_sid;
+        copy->sid_array_size = sa->sids_array_size;
         copy->buffer = MPMB_MAX;
         copy->direction = am->direction;
         copy->sm_list = am->sm_list;
@@ -1933,52 +1856,113 @@ static void SetRawReassemblyFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
     SCLogDebug("rule group %p does NOT have SIG_GROUP_HEAD_HAVERAWSTREAM set", sgh);
 }
 
-static void PrepareAppMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
+static void PrepareMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
 {
-    if (de_ctx->app_mpms_list_cnt == 0)
-        return;
-
-    sh->init->app_mpms = SCCalloc(de_ctx->app_mpms_list_cnt, sizeof(MpmCtx *));
-    BUG_ON(sh->init->app_mpms == NULL);
-
-    DetectBufferMpmRegistery *a = de_ctx->app_mpms_list;
-    while (a != NULL) {
-        if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) ||
-            (a->direction == SIG_FLAG_TOCLIENT && SGH_DIRECTION_TC(sh)))
-        {
-            MpmStore *mpm_store = MpmStorePrepareBufferAppLayer(de_ctx, sh, a);
-            if (mpm_store != NULL) {
-                sh->init->app_mpms[a->id] = mpm_store->mpm_ctx;
+    const int max_buffer_id = de_ctx->buffer_type_id + 1;
+    struct SidsArray sids[max_buffer_id][2];
+    memset(sids, 0, sizeof(sids));
+    const uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
+
+    /* flag the list+directions we have engines for as active */
+    for (DetectBufferMpmRegistery *a = de_ctx->pkt_mpms_list; a != NULL; a = a->next) {
+        struct SidsArray *sa = &sids[a->sm_list][0];
+        sa->active = true;
+        sa->type = a->type;
+    }
+    for (DetectBufferMpmRegistery *a = de_ctx->frame_mpms_list; a != NULL; a = a->next) {
+        sids[a->sm_list][0].type = a->type;
+        if ((a->direction == SIG_FLAG_TOSERVER) && SGH_DIRECTION_TS(sh)) {
+            struct SidsArray *sa = &sids[a->sm_list][0];
+            sa->active = true;
+        }
+        if ((a->direction == SIG_FLAG_TOCLIENT) && SGH_DIRECTION_TC(sh)) {
+            struct SidsArray *sa = &sids[a->sm_list][1];
+            sa->active = true;
+        }
+    }
+    for (DetectBufferMpmRegistery *a = de_ctx->app_mpms_list; a != NULL; a = a->next) {
+        sids[a->sm_list][0].type = a->type;
+        if ((a->direction == SIG_FLAG_TOSERVER) && SGH_DIRECTION_TS(sh)) {
+            struct SidsArray *sa = &sids[a->sm_list][0];
+            sa->active = true;
+        }
+        if ((a->direction == SIG_FLAG_TOCLIENT) && SGH_DIRECTION_TC(sh)) {
+            struct SidsArray *sa = &sids[a->sm_list][1];
+            sa->active = true;
+        }
+    }
 
-                SCLogDebug("a %p a->name %s a->PrefilterRegisterWithListId %p "
-                        "mpm_store->mpm_ctx %p", a, a->name,
-                        a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
+    for (uint32_t sig = 0; sig < sh->init->sig_cnt; sig++) {
+        const Signature *s = sh->init->match_array[sig];
+        if (s == NULL)
+            continue;
+        if (s->init_data->mpm_sm == NULL)
+            continue;
+        const int list = s->init_data->mpm_sm_list;
+        if (list < 0)
+            continue;
+        if (list == DETECT_SM_LIST_PMATCH)
+            continue;
 
-                /* if we have just certain types of negated patterns,
-                 * mpm_ctx can be NULL */
-                if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
-                    BUG_ON(a->PrefilterRegisterWithListId(de_ctx,
-                                sh, mpm_store->mpm_ctx,
-                                a, a->sm_list) != 0);
-                    SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
+        switch (sids[list][0].type) {
+            /* app/frame engines are direction aware */
+            case DETECT_BUFFER_MPM_TYPE_FRAME:
+            case DETECT_BUFFER_MPM_TYPE_APP:
+                if (s->flags & SIG_FLAG_TOSERVER) {
+                    struct SidsArray *sa = &sids[list][0];
+                    if (sa->active) {
+                        if (sa->sids_array == NULL) {
+                            sa->sids_array = SCCalloc(1, max_sid);
+                            sa->sids_array_size = max_sid;
+                            BUG_ON(sa->sids_array == NULL); // TODO
+                        }
+                        sa->sids_array[s->num / 8] |= 1 << (s->num % 8);
+                    }
+                }
+                if (s->flags & SIG_FLAG_TOCLIENT) {
+                    struct SidsArray *sa = &sids[list][1];
+                    if (sa->active) {
+                        if (sa->sids_array == NULL) {
+                            sa->sids_array = SCCalloc(1, max_sid);
+                            sa->sids_array_size = max_sid;
+                            BUG_ON(sa->sids_array == NULL); // TODO
+                        }
+                        sa->sids_array[s->num / 8] |= 1 << (s->num % 8);
+                    }
+                }
+                break;
+            /* pkt engines are directionless, so only use index 0 */
+            case DETECT_BUFFER_MPM_TYPE_PKT: {
+                struct SidsArray *sa = &sids[list][0];
+                if (sa->active) {
+                    if (sa->sids_array == NULL) {
+                        sa->sids_array = SCCalloc(1, max_sid);
+                        sa->sids_array_size = max_sid;
+                        BUG_ON(sa->sids_array == NULL); // TODO
+                    }
+                    sa->sids_array[s->num / 8] |= 1 << (s->num % 8);
                 }
+                break;
             }
+            default:
+                abort();
+                break;
         }
-        a = a->next;
     }
-}
 
-static void PreparePktMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
-{
-    if (de_ctx->pkt_mpms_list_cnt == 0)
-        return;
+    sh->init->app_mpms = SCCalloc(de_ctx->app_mpms_list_cnt, sizeof(MpmCtx *));
+    BUG_ON(sh->init->app_mpms == NULL);
 
     sh->init->pkt_mpms = SCCalloc(de_ctx->pkt_mpms_list_cnt, sizeof(MpmCtx *));
     BUG_ON(sh->init->pkt_mpms == NULL);
 
-    DetectBufferMpmRegistery *a = de_ctx->pkt_mpms_list;
-    while (a != NULL) {
-        MpmStore *mpm_store = MpmStorePrepareBufferPkt(de_ctx, sh, a);
+    sh->init->frame_mpms = SCCalloc(de_ctx->frame_mpms_list_cnt, sizeof(MpmCtx *));
+    BUG_ON(sh->init->frame_mpms == NULL);
+
+    for (DetectBufferMpmRegistery *a = de_ctx->pkt_mpms_list; a != NULL; a = a->next) {
+        struct SidsArray *sa = &sids[a->sm_list][0];
+
+        MpmStore *mpm_store = MpmStorePrepareBufferPkt(de_ctx, sh, a, sa);
         if (mpm_store != NULL) {
             sh->init->pkt_mpms[a->id] = mpm_store->mpm_ctx;
 
@@ -1995,40 +1979,68 @@ static void PreparePktMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
                 SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
             }
         }
-        a = a->next;
     }
-}
+    for (DetectBufferMpmRegistery *a = de_ctx->frame_mpms_list; a != NULL; a = a->next) {
+        if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) ||
+                (a->direction == SIG_FLAG_TOCLIENT && SGH_DIRECTION_TC(sh))) {
+            const int dir = a->direction == SIG_FLAG_TOCLIENT;
+            struct SidsArray *sa = &sids[a->sm_list][dir];
 
-static void PrepareFrameMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
-{
-    if (de_ctx->frame_mpms_list_cnt == 0)
-        return;
+            SCLogDebug("a %s direction %d PrefilterRegisterWithListId %p", a->name, a->direction,
+                    a->PrefilterRegisterWithListId);
+            MpmStore *mpm_store = MpmStorePrepareBufferFrame(de_ctx, sh, a, sa);
+            if (mpm_store != NULL) {
+                sh->init->frame_mpms[a->id] = mpm_store->mpm_ctx;
 
-    sh->init->frame_mpms = SCCalloc(de_ctx->frame_mpms_list_cnt, sizeof(MpmCtx *));
-    BUG_ON(sh->init->frame_mpms == NULL);
+                SCLogDebug("a %p a->name %s a->reg->PrefilterRegisterWithListId %p "
+                           "mpm_store->mpm_ctx %p",
+                        a, a->name, a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
 
-    DetectBufferMpmRegistery *a = de_ctx->frame_mpms_list;
-    while (a != NULL) {
-        SCLogDebug("a %s direction %d PrefilterRegisterWithListId %p", a->name, a->direction,
-                a->PrefilterRegisterWithListId);
-        MpmStore *mpm_store = MpmStorePrepareBufferFrame(de_ctx, sh, a);
-        if (mpm_store != NULL) {
-            sh->init->frame_mpms[a->id] = mpm_store->mpm_ctx;
+                /* if we have just certain types of negated patterns,
+                 * mpm_ctx can be NULL */
+                SCLogDebug("mpm_store %p mpm_ctx %p", mpm_store, mpm_store->mpm_ctx);
+                if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
+                    BUG_ON(a->PrefilterRegisterWithListId(
+                                   de_ctx, sh, mpm_store->mpm_ctx, a, a->sm_list) != 0);
+                    SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
+                }
+            }
+        }
+    }
+    for (DetectBufferMpmRegistery *a = de_ctx->app_mpms_list; a != NULL; a = a->next) {
+        if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) ||
+                (a->direction == SIG_FLAG_TOCLIENT && SGH_DIRECTION_TC(sh))) {
+            const int dir = a->direction == SIG_FLAG_TOCLIENT;
+            struct SidsArray *sa = &sids[a->sm_list][dir];
 
-            SCLogDebug("a %p a->name %s a->reg->PrefilterRegisterWithListId %p "
-                       "mpm_store->mpm_ctx %p",
-                    a, a->name, a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
+            MpmStore *mpm_store = MpmStorePrepareBufferAppLayer(de_ctx, sh, a, sa);
+            if (mpm_store != NULL) {
+                sh->init->app_mpms[a->id] = mpm_store->mpm_ctx;
 
-            /* if we have just certain types of negated patterns,
-             * mpm_ctx can be NULL */
-            SCLogDebug("mpm_store %p mpm_ctx %p", mpm_store, mpm_store->mpm_ctx);
-            if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
-                BUG_ON(a->PrefilterRegisterWithListId(
-                               de_ctx, sh, mpm_store->mpm_ctx, a, a->sm_list) != 0);
-                SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
+                SCLogDebug("a %p a->name %s a->PrefilterRegisterWithListId %p "
+                           "mpm_store->mpm_ctx %p",
+                        a, a->name, a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
+
+                /* if we have just certain types of negated patterns,
+                 * mpm_ctx can be NULL */
+                if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
+                    BUG_ON(a->PrefilterRegisterWithListId(
+                                   de_ctx, sh, mpm_store->mpm_ctx, a, a->sm_list) != 0);
+                    SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
+                }
             }
         }
-        a = a->next;
+    }
+
+    /* free temp sig arrays */
+    for (int i = 0; i < max_buffer_id; i++) {
+        struct SidsArray *sa;
+        sa = &sids[i][0];
+        if (sa->sids_array != NULL)
+            SCFree(sa->sids_array);
+        sa = &sids[i][1];
+        if (sa->sids_array != NULL)
+            SCFree(sa->sids_array);
     }
 }
 
@@ -2085,9 +2097,7 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
         }
     }
 
-    PrepareAppMpms(de_ctx, sh);
-    PreparePktMpms(de_ctx, sh);
-    PrepareFrameMpms(de_ctx, sh);
+    PrepareMpms(de_ctx, sh);
     return 0;
 }