]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
threshold: fix multi-tenant file parsing
authorVictor Julien <vjulien@oisf.net>
Sun, 6 Aug 2023 07:40:37 +0000 (09:40 +0200)
committerVictor Julien <vjulien@oisf.net>
Fri, 11 Aug 2023 05:02:06 +0000 (07:02 +0200)
Switch to DetectParseRegex and use a local pcre2_match_data to
avoid concurrency issues.

Bug: #6247.

src/suricata.c
src/util-threshold-config.c
src/util-threshold-config.h

index ccf37c3881b4b97bf61ec8a00f964422ee8b5785..d436b0ba7da377f029c1c4625e08667d236517fe 100644 (file)
@@ -409,7 +409,6 @@ static void GlobalsDestroy(SCInstance *suri)
     LuajitFreeStatesPool();
 #endif
     DetectParseFreeRegexes();
-    SCThresholdConfGlobalFree();
 
     SCPidfileRemove(suri->pid_filename);
     SCFree(suri->pid_filename);
index f8593c9ea326dfa2d0cf441deb208007e894f08b..f19e8108d7ff33c96342cc7e54e20ccd064d9486 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2021 Open Information Security Foundation
+/* Copyright (C) 2007-2023 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
@@ -90,104 +90,30 @@ static FILE *g_ut_threshold_fp = NULL;
 #define THRESHOLD_CONF_DEF_CONF_FILEPATH CONFIG_DIR "/threshold.config"
 #endif
 
-static pcre2_code *regex_base = NULL;
-static pcre2_match_data *regex_base_match = NULL;
-
-static pcre2_code *regex_threshold = NULL;
-static pcre2_match_data *regex_threshold_match = NULL;
-
-static pcre2_code *regex_rate = NULL;
-static pcre2_match_data *regex_rate_match = NULL;
-
-static pcre2_code *regex_suppress = NULL;
-static pcre2_match_data *regex_suppress_match = NULL;
+static DetectParseRegex *regex_base = NULL;
+static DetectParseRegex *regex_threshold = NULL;
+static DetectParseRegex *regex_rate = NULL;
+static DetectParseRegex *regex_suppress = NULL;
 
 static void SCThresholdConfDeInitContext(DetectEngineCtx *de_ctx, FILE *fd);
 
 void SCThresholdConfGlobalInit(void)
 {
-    int en;
-    PCRE2_SIZE eo;
-    int opts = 0;
-    PCRE2_UCHAR errbuffer[256];
-
-    regex_base = pcre2_compile(
-            (PCRE2_SPTR8)DETECT_BASE_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
+    regex_base = DetectSetupPCRE2(DETECT_BASE_REGEX, 0);
     if (regex_base == NULL) {
-        pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
-        FatalError("pcre2 compile of \"%s\" failed at "
-                   "offset %d: %s",
-                DETECT_BASE_REGEX, (int)eo, errbuffer);
+        FatalError("classification base regex setup failed");
     }
-    regex_base_match = pcre2_match_data_create_from_pattern(regex_base, NULL);
-
-    regex_threshold = pcre2_compile(
-            (PCRE2_SPTR8)DETECT_THRESHOLD_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
+    regex_threshold = DetectSetupPCRE2(DETECT_THRESHOLD_REGEX, 0);
     if (regex_threshold == NULL) {
-        pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
-        FatalError("pcre2 compile of \"%s\" failed at "
-                   "offset %d: %s",
-                DETECT_THRESHOLD_REGEX, (int)eo, errbuffer);
+        FatalError("classification threshold regex setup failed");
     }
-    regex_threshold_match = pcre2_match_data_create_from_pattern(regex_threshold, NULL);
-
-    regex_rate = pcre2_compile(
-            (PCRE2_SPTR8)DETECT_RATE_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
+    regex_rate = DetectSetupPCRE2(DETECT_RATE_REGEX, 0);
     if (regex_rate == NULL) {
-        pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
-        FatalError("pcre2 compile of \"%s\" failed at "
-                   "offset %d: %s",
-                DETECT_RATE_REGEX, (int)eo, errbuffer);
+        FatalError("classification rate_filter regex setup failed");
     }
-    regex_rate_match = pcre2_match_data_create_from_pattern(regex_rate, NULL);
-
-    regex_suppress = pcre2_compile(
-            (PCRE2_SPTR8)DETECT_SUPPRESS_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
+    regex_suppress = DetectSetupPCRE2(DETECT_SUPPRESS_REGEX, 0);
     if (regex_suppress == NULL) {
-        pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
-        FatalError("pcre2 compile of \"%s\" failed at "
-                   "offset %d: %s",
-                DETECT_SUPPRESS_REGEX, (int)eo, errbuffer);
-    }
-    regex_suppress_match = pcre2_match_data_create_from_pattern(regex_suppress, NULL);
-}
-
-void SCThresholdConfGlobalFree(void)
-{
-    if (regex_base != NULL) {
-        pcre2_code_free(regex_base);
-        regex_base = NULL;
-    }
-    if (regex_base_match != NULL) {
-        pcre2_match_data_free(regex_base_match);
-        regex_base_match = NULL;
-    }
-
-    if (regex_threshold != NULL) {
-        pcre2_code_free(regex_threshold);
-        regex_threshold = NULL;
-    }
-    if (regex_threshold_match != NULL) {
-        pcre2_match_data_free(regex_threshold_match);
-        regex_threshold_match = NULL;
-    }
-
-    if (regex_rate != NULL) {
-        pcre2_code_free(regex_rate);
-        regex_rate = NULL;
-    }
-    if (regex_rate_match != NULL) {
-        pcre2_match_data_free(regex_rate_match);
-        regex_rate_match = NULL;
-    }
-
-    if (regex_suppress != NULL) {
-        pcre2_code_free(regex_suppress);
-        regex_suppress = NULL;
-    }
-    if (regex_suppress_match != NULL) {
-        pcre2_match_data_free(regex_suppress_match);
-        regex_suppress_match = NULL;
+        FatalError("classification suppress regex setup failed");
     }
 }
 
@@ -661,10 +587,11 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
     if (de_ctx == NULL)
         return -1;
 
-    ret = pcre2_match(
-            regex_base, (PCRE2_SPTR8)rawstr, strlen(rawstr), 0, 0, regex_base_match, NULL);
+    pcre2_match_data *regex_base_match = NULL;
+    ret = DetectParsePcreExec(regex_base, &regex_base_match, rawstr, 0, 0);
     if (ret < 4) {
         SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret, rawstr);
+        pcre2_match_data_free(regex_base_match);
         goto error;
     }
 
@@ -674,6 +601,7 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
             regex_base_match, 1, (PCRE2_UCHAR8 *)th_rule_type, &copylen);
     if (ret < 0) {
         SCLogError("pcre2_substring_copy_bynumber failed");
+        pcre2_match_data_free(regex_base_match);
         goto error;
     }
 
@@ -682,6 +610,7 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
     ret = pcre2_substring_copy_bynumber(regex_base_match, 2, (PCRE2_UCHAR8 *)th_gid, &copylen);
     if (ret < 0) {
         SCLogError("pcre2_substring_copy_bynumber failed");
+        pcre2_match_data_free(regex_base_match);
         goto error;
     }
 
@@ -689,6 +618,7 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
     ret = pcre2_substring_copy_bynumber(regex_base_match, 3, (PCRE2_UCHAR8 *)th_sid, &copylen);
     if (ret < 0) {
         SCLogError("pcre2_substring_copy_bynumber failed");
+        pcre2_match_data_free(regex_base_match);
         goto error;
     }
 
@@ -697,8 +627,11 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
             regex_base_match, 4, (PCRE2_UCHAR8 **)&rule_extend, &copylen);
     if (ret < 0) {
         SCLogError("pcre2_substring_get_bynumber failed");
+        pcre2_match_data_free(regex_base_match);
         goto error;
     }
+    pcre2_match_data_free(regex_base_match);
+    regex_base_match = NULL;
 
     /* get type of rule */
     if (strcasecmp(th_rule_type,"event_filter") == 0) {
@@ -719,45 +652,48 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
         case THRESHOLD_TYPE_EVENT_FILTER:
         case THRESHOLD_TYPE_THRESHOLD:
             if (strlen(rule_extend) > 0) {
-                ret = pcre2_match(regex_threshold, (PCRE2_SPTR8)rule_extend, strlen(rule_extend), 0,
-                        0, regex_threshold_match, NULL);
+                pcre2_match_data *match = NULL;
+
+                ret = DetectParsePcreExec(regex_threshold, &match, rule_extend, 0, 0);
                 if (ret < 4) {
                     SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret,
                             rule_extend);
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_type);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_threshold_match, 1, (PCRE2_UCHAR8 *)th_type, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)th_type, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_track);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_threshold_match, 2, (PCRE2_UCHAR8 *)th_track, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)th_track, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_count);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_threshold_match, 3, (PCRE2_UCHAR8 *)th_count, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)th_count, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_seconds);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_threshold_match, 4, (PCRE2_UCHAR8 *)th_seconds, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 4, (PCRE2_UCHAR8 *)th_seconds, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
+                pcre2_match_data_free(match);
 
                 if (strcasecmp(th_type,"limit") == 0)
                     parsed_type = TYPE_LIMIT;
@@ -776,28 +712,30 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
             break;
         case THRESHOLD_TYPE_SUPPRESS:
             if (strlen(rule_extend) > 0) {
-                ret = pcre2_match(regex_suppress, (PCRE2_SPTR8)rule_extend, strlen(rule_extend), 0,
-                        0, regex_suppress_match, NULL);
+                pcre2_match_data *match = NULL;
+                ret = DetectParsePcreExec(regex_suppress, &match, rule_extend, 0, 0);
                 if (ret < 2) {
                     SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret,
                             rule_extend);
+                    pcre2_match_data_free(match);
                     goto error;
                 }
                 /* retrieve the track mode */
                 copylen = sizeof(th_seconds);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_suppress_match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
                 /* retrieve the IP; use "get" for heap allocation */
-                ret = pcre2_substring_get_bynumber(
-                        regex_suppress_match, 2, (PCRE2_UCHAR8 **)&th_ip, &copylen);
+                ret = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&th_ip, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_get_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
+                pcre2_match_data_free(match);
             } else {
                 parsed_track = TRACK_RULE;
             }
@@ -805,53 +743,56 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
             break;
         case THRESHOLD_TYPE_RATE:
             if (strlen(rule_extend) > 0) {
-                ret = pcre2_match(regex_rate, (PCRE2_SPTR8)rule_extend, strlen(rule_extend), 0, 0,
-                        regex_rate_match, NULL);
+                pcre2_match_data *match = NULL;
+                ret = DetectParsePcreExec(regex_rate, &match, rule_extend, 0, 0);
                 if (ret < 5) {
                     SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret,
                             rule_extend);
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_track);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_rate_match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_count);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_rate_match, 2, (PCRE2_UCHAR8 *)th_count, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)th_count, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_seconds);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_rate_match, 3, (PCRE2_UCHAR8 *)th_seconds, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)th_seconds, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_new_action);
                 ret = pcre2_substring_copy_bynumber(
-                        regex_rate_match, 4, (PCRE2_UCHAR8 *)th_new_action, &copylen);
+                        match, 4, (PCRE2_UCHAR8 *)th_new_action, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
 
                 copylen = sizeof(th_timeout);
-                ret = pcre2_substring_copy_bynumber(
-                        regex_rate_match, 5, (PCRE2_UCHAR8 *)th_timeout, &copylen);
+                ret = pcre2_substring_copy_bynumber(match, 5, (PCRE2_UCHAR8 *)th_timeout, &copylen);
                 if (ret < 0) {
                     SCLogError("pcre2_substring_copy_bynumber failed");
+                    pcre2_match_data_free(match);
                     goto error;
                 }
+                pcre2_match_data_free(match);
 
                 /* TODO: implement option "apply_to" */
 
index 982bf3e1c9c3f0ea56cd844fd87e03811bfdbf9c..ff0eadcf312594805c46b1881bd3ebeeee715c63 100644 (file)
@@ -30,6 +30,5 @@ int SCThresholdConfInitContext(DetectEngineCtx *);
 void SCThresholdConfRegisterTests(void);
 
 void SCThresholdConfGlobalInit(void);
-void SCThresholdConfGlobalFree(void);
 
 #endif /* __UTIL_THRESHOLD_CONFIG_H__ */