threshold: fix multi-tenant file parsing

Switch to DetectParseRegex and use a local pcre2_match_data to
avoid concurrency issues.

Bug: #6247.
pull/9380/head
Victor Julien 3 years ago
parent e5e58d5647
commit f052b524bc

@ -409,7 +409,6 @@ static void GlobalsDestroy(SCInstance *suri)
LuajitFreeStatesPool(); LuajitFreeStatesPool();
#endif #endif
DetectParseFreeRegexes(); DetectParseFreeRegexes();
SCThresholdConfGlobalFree();
SCPidfileRemove(suri->pid_filename); SCPidfileRemove(suri->pid_filename);
SCFree(suri->pid_filename); SCFree(suri->pid_filename);

@ -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 * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * 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" #define THRESHOLD_CONF_DEF_CONF_FILEPATH CONFIG_DIR "/threshold.config"
#endif #endif
static pcre2_code *regex_base = NULL; static DetectParseRegex *regex_base = NULL;
static pcre2_match_data *regex_base_match = NULL; static DetectParseRegex *regex_threshold = NULL;
static DetectParseRegex *regex_rate = NULL;
static pcre2_code *regex_threshold = NULL; static DetectParseRegex *regex_suppress = 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 void SCThresholdConfDeInitContext(DetectEngineCtx *de_ctx, FILE *fd); static void SCThresholdConfDeInitContext(DetectEngineCtx *de_ctx, FILE *fd);
void SCThresholdConfGlobalInit(void) void SCThresholdConfGlobalInit(void)
{ {
int en; regex_base = DetectSetupPCRE2(DETECT_BASE_REGEX, 0);
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);
if (regex_base == NULL) { if (regex_base == NULL) {
pcre2_get_error_message(en, errbuffer, sizeof(errbuffer)); FatalError("classification base regex setup failed");
FatalError("pcre2 compile of \"%s\" failed at "
"offset %d: %s",
DETECT_BASE_REGEX, (int)eo, errbuffer);
} }
regex_base_match = pcre2_match_data_create_from_pattern(regex_base, NULL); regex_threshold = DetectSetupPCRE2(DETECT_THRESHOLD_REGEX, 0);
regex_threshold = pcre2_compile(
(PCRE2_SPTR8)DETECT_THRESHOLD_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
if (regex_threshold == NULL) { if (regex_threshold == NULL) {
pcre2_get_error_message(en, errbuffer, sizeof(errbuffer)); FatalError("classification threshold regex setup failed");
FatalError("pcre2 compile of \"%s\" failed at "
"offset %d: %s",
DETECT_THRESHOLD_REGEX, (int)eo, errbuffer);
} }
regex_threshold_match = pcre2_match_data_create_from_pattern(regex_threshold, NULL); regex_rate = DetectSetupPCRE2(DETECT_RATE_REGEX, 0);
regex_rate = pcre2_compile(
(PCRE2_SPTR8)DETECT_RATE_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
if (regex_rate == NULL) { if (regex_rate == NULL) {
pcre2_get_error_message(en, errbuffer, sizeof(errbuffer)); FatalError("classification rate_filter regex setup failed");
FatalError("pcre2 compile of \"%s\" failed at "
"offset %d: %s",
DETECT_RATE_REGEX, (int)eo, errbuffer);
} }
regex_rate_match = pcre2_match_data_create_from_pattern(regex_rate, NULL); regex_suppress = DetectSetupPCRE2(DETECT_SUPPRESS_REGEX, 0);
regex_suppress = pcre2_compile(
(PCRE2_SPTR8)DETECT_SUPPRESS_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
if (regex_suppress == NULL) { if (regex_suppress == NULL) {
pcre2_get_error_message(en, errbuffer, sizeof(errbuffer)); FatalError("classification suppress regex setup failed");
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;
} }
} }
@ -661,10 +587,11 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
if (de_ctx == NULL) if (de_ctx == NULL)
return -1; return -1;
ret = pcre2_match( pcre2_match_data *regex_base_match = NULL;
regex_base, (PCRE2_SPTR8)rawstr, strlen(rawstr), 0, 0, regex_base_match, NULL); ret = DetectParsePcreExec(regex_base, &regex_base_match, rawstr, 0, 0);
if (ret < 4) { if (ret < 4) {
SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret, rawstr); SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret, rawstr);
pcre2_match_data_free(regex_base_match);
goto error; 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); regex_base_match, 1, (PCRE2_UCHAR8 *)th_rule_type, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(regex_base_match);
goto error; 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); ret = pcre2_substring_copy_bynumber(regex_base_match, 2, (PCRE2_UCHAR8 *)th_gid, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(regex_base_match);
goto error; 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); ret = pcre2_substring_copy_bynumber(regex_base_match, 3, (PCRE2_UCHAR8 *)th_sid, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(regex_base_match);
goto error; 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); regex_base_match, 4, (PCRE2_UCHAR8 **)&rule_extend, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_get_bynumber failed"); SCLogError("pcre2_substring_get_bynumber failed");
pcre2_match_data_free(regex_base_match);
goto error; goto error;
} }
pcre2_match_data_free(regex_base_match);
regex_base_match = NULL;
/* get type of rule */ /* get type of rule */
if (strcasecmp(th_rule_type,"event_filter") == 0) { 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_EVENT_FILTER:
case THRESHOLD_TYPE_THRESHOLD: case THRESHOLD_TYPE_THRESHOLD:
if (strlen(rule_extend) > 0) { if (strlen(rule_extend) > 0) {
ret = pcre2_match(regex_threshold, (PCRE2_SPTR8)rule_extend, strlen(rule_extend), 0, pcre2_match_data *match = NULL;
0, regex_threshold_match, NULL);
ret = DetectParsePcreExec(regex_threshold, &match, rule_extend, 0, 0);
if (ret < 4) { if (ret < 4) {
SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret, SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret,
rule_extend); rule_extend);
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_type); copylen = sizeof(th_type);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)th_type, &copylen);
regex_threshold_match, 1, (PCRE2_UCHAR8 *)th_type, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_track); copylen = sizeof(th_track);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)th_track, &copylen);
regex_threshold_match, 2, (PCRE2_UCHAR8 *)th_track, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_count); copylen = sizeof(th_count);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)th_count, &copylen);
regex_threshold_match, 3, (PCRE2_UCHAR8 *)th_count, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_seconds); copylen = sizeof(th_seconds);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 4, (PCRE2_UCHAR8 *)th_seconds, &copylen);
regex_threshold_match, 4, (PCRE2_UCHAR8 *)th_seconds, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
pcre2_match_data_free(match);
if (strcasecmp(th_type,"limit") == 0) if (strcasecmp(th_type,"limit") == 0)
parsed_type = TYPE_LIMIT; parsed_type = TYPE_LIMIT;
@ -776,28 +712,30 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
break; break;
case THRESHOLD_TYPE_SUPPRESS: case THRESHOLD_TYPE_SUPPRESS:
if (strlen(rule_extend) > 0) { if (strlen(rule_extend) > 0) {
ret = pcre2_match(regex_suppress, (PCRE2_SPTR8)rule_extend, strlen(rule_extend), 0, pcre2_match_data *match = NULL;
0, regex_suppress_match, NULL); ret = DetectParsePcreExec(regex_suppress, &match, rule_extend, 0, 0);
if (ret < 2) { if (ret < 2) {
SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret, SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret,
rule_extend); rule_extend);
pcre2_match_data_free(match);
goto error; goto error;
} }
/* retrieve the track mode */ /* retrieve the track mode */
copylen = sizeof(th_seconds); copylen = sizeof(th_seconds);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
regex_suppress_match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
/* retrieve the IP; use "get" for heap allocation */ /* retrieve the IP; use "get" for heap allocation */
ret = pcre2_substring_get_bynumber( ret = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&th_ip, &copylen);
regex_suppress_match, 2, (PCRE2_UCHAR8 **)&th_ip, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_get_bynumber failed"); SCLogError("pcre2_substring_get_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
pcre2_match_data_free(match);
} else { } else {
parsed_track = TRACK_RULE; parsed_track = TRACK_RULE;
} }
@ -805,53 +743,56 @@ static int ParseThresholdRule(const DetectEngineCtx *de_ctx, char *rawstr, uint3
break; break;
case THRESHOLD_TYPE_RATE: case THRESHOLD_TYPE_RATE:
if (strlen(rule_extend) > 0) { if (strlen(rule_extend) > 0) {
ret = pcre2_match(regex_rate, (PCRE2_SPTR8)rule_extend, strlen(rule_extend), 0, 0, pcre2_match_data *match = NULL;
regex_rate_match, NULL); ret = DetectParsePcreExec(regex_rate, &match, rule_extend, 0, 0);
if (ret < 5) { if (ret < 5) {
SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret, SCLogError("pcre2_match parse error, ret %" PRId32 ", string %s", ret,
rule_extend); rule_extend);
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_track); copylen = sizeof(th_track);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
regex_rate_match, 1, (PCRE2_UCHAR8 *)th_track, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_count); copylen = sizeof(th_count);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)th_count, &copylen);
regex_rate_match, 2, (PCRE2_UCHAR8 *)th_count, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_seconds); copylen = sizeof(th_seconds);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)th_seconds, &copylen);
regex_rate_match, 3, (PCRE2_UCHAR8 *)th_seconds, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_new_action); copylen = sizeof(th_new_action);
ret = pcre2_substring_copy_bynumber( 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) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
copylen = sizeof(th_timeout); copylen = sizeof(th_timeout);
ret = pcre2_substring_copy_bynumber( ret = pcre2_substring_copy_bynumber(match, 5, (PCRE2_UCHAR8 *)th_timeout, &copylen);
regex_rate_match, 5, (PCRE2_UCHAR8 *)th_timeout, &copylen);
if (ret < 0) { if (ret < 0) {
SCLogError("pcre2_substring_copy_bynumber failed"); SCLogError("pcre2_substring_copy_bynumber failed");
pcre2_match_data_free(match);
goto error; goto error;
} }
pcre2_match_data_free(match);
/* TODO: implement option "apply_to" */ /* TODO: implement option "apply_to" */

@ -30,6 +30,5 @@ int SCThresholdConfInitContext(DetectEngineCtx *);
void SCThresholdConfRegisterTests(void); void SCThresholdConfRegisterTests(void);
void SCThresholdConfGlobalInit(void); void SCThresholdConfGlobalInit(void);
void SCThresholdConfGlobalFree(void);
#endif /* __UTIL_THRESHOLD_CONFIG_H__ */ #endif /* __UTIL_THRESHOLD_CONFIG_H__ */

Loading…
Cancel
Save