You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/detect-pktvar.c

173 lines
4.9 KiB
C

/* Copyright (C) 2007-2020 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
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Victor Julien <victor@inliniac.net>
*
* Implements the pktvar keyword
*/
#include "suricata-common.h"
#include "decode.h"
#include "detect.h"
#include "detect-parse.h"
#include "threads.h"
#include "pkt-var.h"
#include "detect-pktvar.h"
#include "detect-content.h"
#include "util-spm.h"
#include "util-debug.h"
#include "util-var-name.h"
#define PARSE_REGEX "(.*),(.*)"
static DetectParseRegex parse_regex;
static int DetectPktvarMatch (DetectEngineThreadCtx *, Packet *,
const Signature *, const SigMatchCtx *);
static int DetectPktvarSetup (DetectEngineCtx *, Signature *, const char *);
static void DetectPktvarFree(DetectEngineCtx *, void *data);
void DetectPktvarRegister (void)
{
sigmatch_table[DETECT_PKTVAR].name = "pktvar";
sigmatch_table[DETECT_PKTVAR].Match = DetectPktvarMatch;
sigmatch_table[DETECT_PKTVAR].Setup = DetectPktvarSetup;
sigmatch_table[DETECT_PKTVAR].Free = DetectPktvarFree;
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
}
/*
* returns 0: no match
* 1: match
* -1: error
*/
static int DetectPktvarMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
const Signature *s, const SigMatchCtx *ctx)
{
int ret = 0;
const DetectPktvarData *pd = (const DetectPktvarData *)ctx;
PktVar *pv = PktVarGet(p, pd->id);
if (pv != NULL) {
uint8_t *ptr = SpmSearch(pv->value, pv->value_len, pd->content, pd->content_len);
if (ptr != NULL)
ret = 1;
}
return ret;
}
static void DetectPktvarFree(DetectEngineCtx *de_ctx, void *ptr)
{
DetectPktvarData *data = ptr;
if (data != NULL) {
var-names: reimplement var name handling Implement a new design for handling var name id's. The old logic was aware of detection engine versions and generally didn't work well for multi-tenancy cases. Other than memory leaks and crashes, logging of var names worked or failed based on which tenant was loaded last. This patch implements a new approach, where there is a global store of vars and their id's for the lifetime of the program. Overall Design: Base Store: "base" Used during keyword registration. Operates under lock. Base is shared between all detect engines, detect engine versions and tenants. Each variable name is ref counted. During the freeing of a detect engine / tenant, unregistration decreases the ref cnt. Base has both a string to id and a id to string hash table. String to id is used during parsing/registration. id to string during unregistration. Active Store Pointer (atomic) The "active" store atomic pointer points to the active lookup store. The call to `VarNameStoreActivate` will build a new lookup store and hot swap the pointer. Ensuring memory safety. During the hot swap, the pointer is replaced, so any new call to the lookup functions will automatically use the new store. This leaves the case of any lookup happening concurrently with the pointer swap. For this case we add the old store to a free list. It gets a timestamp before which it cannot be freed. Free List The free list contains old stores that are waiting to get removed. They contain a timestamp that is checked before they are freed. Bug: #6044. Bug: #6201.
3 years ago
VarNameStoreUnregister(data->id, VAR_TYPE_PKT_VAR);
SCFree(data->content);
SCFree(data);
}
}
static int DetectPktvarSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
{
char *varname = NULL, *varcontent = NULL;
int res = 0;
size_t pcre2_len;
uint8_t *content = NULL;
uint16_t len = 0;
DetectPktvarData *cd = NULL;
pcre2_match_data *match = NULL;
int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
if (ret != 3) {
SCLogError("\"%s\" is not a valid setting for pktvar.", rawstr);
goto error;
}
const char *str_ptr;
res = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
if (res < 0) {
SCLogError("pcre2_substring_get_bynumber failed");
goto error;
}
varname = (char *)str_ptr;
res = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
if (res < 0) {
pcre2_substring_free((PCRE2_UCHAR8 *)varname);
SCLogError("pcre2_substring_get_bynumber failed");
goto error;
}
varcontent = (char *)str_ptr;
SCLogDebug("varname '%s', varcontent '%s'", varname, varcontent);
char *parse_content;
if (strlen(varcontent) >= 2 && varcontent[0] == '"' &&
varcontent[strlen(varcontent) - 1] == '"')
{
parse_content = varcontent + 1;
varcontent[strlen(varcontent) - 1] = '\0';
} else {
parse_content = varcontent;
}
ret = DetectContentDataParse("pktvar", parse_content, &content, &len);
if (ret == -1 || content == NULL) {
pcre2_substring_free((PCRE2_UCHAR8 *)varname);
pcre2_substring_free((PCRE2_UCHAR8 *)varcontent);
goto error;
Memory leak cleanup in detectors Hello, I ran the code through an analysis program and found several leaks that should be cleaned up. *In src/detect-engine-address-ipv4.c at line 472, the test for ag == NULL will never be true since that is the loop entry test. *In src/detect-engine-port.c at line 1133, the test for p == NULL will never be true since that is the loop entry test. *In src/detect-engine-mpm.c at line 263 is a return without freeing fast_pattern *In src/detect-ack.c at line 80 and 85, data catches the return from malloc. One of them should be deleted. *In src/detect-seq.c at line 81 and 86, data catches the return from malloc. One of them should be deleted. *In src/detect-content.c at line 749, many of the paths that lead to the error exit still has temp pointing to allocated memory. To clean this up, temp should be set to NULL if not immediately assigning and new value. *In src/detect-uricontent.c at line 319, both cd and str needto be freed. At lines 344, str needs to be freed. And at line 347 str and temp need to be freed. *In src/detect-flowbits.c at line 231 and 235, str was not being freed. cd was not being freed at line 235. *In src/detect-flowvar.c at line 127, str was not being freed. At line 194, cd and str were not being freed. *In src/detect-flowint.c at line 277, sfd was not being freed. At line 315, str was not being freed. *In src/detect-pktvar.c at line 121, str was not being freed. At line 188, str and cd was not being freed. *In src/detect-pcre.c at line 389, there is an extra free of "re" that should be deleted. *In src/detect-depth.c at line 42 & 48, str has not been freed. *In src/detect-distance.c at line 49 and 55, str has not been freed *In src/detect-offset.c at line 45, str has not been freed. The patch below fixes these issues. -Steve
17 years ago
}
pcre2_substring_free((PCRE2_UCHAR8 *)varcontent);
cd = SCCalloc(1, sizeof(DetectPktvarData));
if (unlikely(cd == NULL)) {
pcre2_substring_free((PCRE2_UCHAR8 *)varname);
SCFree(content);
goto error;
Memory leak cleanup in detectors Hello, I ran the code through an analysis program and found several leaks that should be cleaned up. *In src/detect-engine-address-ipv4.c at line 472, the test for ag == NULL will never be true since that is the loop entry test. *In src/detect-engine-port.c at line 1133, the test for p == NULL will never be true since that is the loop entry test. *In src/detect-engine-mpm.c at line 263 is a return without freeing fast_pattern *In src/detect-ack.c at line 80 and 85, data catches the return from malloc. One of them should be deleted. *In src/detect-seq.c at line 81 and 86, data catches the return from malloc. One of them should be deleted. *In src/detect-content.c at line 749, many of the paths that lead to the error exit still has temp pointing to allocated memory. To clean this up, temp should be set to NULL if not immediately assigning and new value. *In src/detect-uricontent.c at line 319, both cd and str needto be freed. At lines 344, str needs to be freed. And at line 347 str and temp need to be freed. *In src/detect-flowbits.c at line 231 and 235, str was not being freed. cd was not being freed at line 235. *In src/detect-flowvar.c at line 127, str was not being freed. At line 194, cd and str were not being freed. *In src/detect-flowint.c at line 277, sfd was not being freed. At line 315, str was not being freed. *In src/detect-pktvar.c at line 121, str was not being freed. At line 188, str and cd was not being freed. *In src/detect-pcre.c at line 389, there is an extra free of "re" that should be deleted. *In src/detect-depth.c at line 42 & 48, str has not been freed. *In src/detect-distance.c at line 49 and 55, str has not been freed *In src/detect-offset.c at line 45, str has not been freed. The patch below fixes these issues. -Steve
17 years ago
}
cd->content = content;
cd->content_len = len;
uint32_t varname_id = VarNameStoreRegister(varname, VAR_TYPE_PKT_VAR);
if (unlikely(varname_id == 0))
goto error;
cd->id = varname_id;
pcre2_substring_free((PCRE2_UCHAR8 *)varname);
/* Okay so far so good, lets get this into a SigMatch
* and put it in the Signature. */
if (SCSigMatchAppendSMToList(
de_ctx, s, DETECT_PKTVAR, (SigMatchCtx *)cd, DETECT_SM_LIST_MATCH) == NULL) {
goto error;
}
pcre2_match_data_free(match);
return 0;
error:
DetectPktvarFree(de_ctx, cd);
if (match) {
pcre2_match_data_free(match);
}
return -1;
}