Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

analysis: report rule state altered by other rule - v3 #12515

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion src/detect-engine-analyzer.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2023 Open Information Security Foundation
/* Copyright (C) 2007-2025 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
Expand Down Expand Up @@ -1047,6 +1047,34 @@ void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
break;
}

// dependencies object and its subfields only logged if we have values
if (s->init_data->is_rule_state_dependant) {
jb_open_object(ctx.js, "dependencies");
jb_open_object(ctx.js, "flowbits");
jb_open_object(ctx.js, "upstream");
if (s->init_data->rule_state_dependant_sids_size > 0) {
jb_open_object(ctx.js, "state_modifying_rules");
jb_open_array(ctx.js, "sids");
for (uint32_t i = 0; i < s->init_data->rule_state_dependant_sids_idx; i++) {
jb_append_uint(ctx.js, s->init_data->rule_state_dependant_sids_array[i]);
}
jb_close(ctx.js); // sids
jb_open_array(ctx.js, "names");
for (uint32_t i = 0; i < s->init_data->rule_state_flowbits_ids_size - 1; i++) {
if (s->init_data->rule_state_flowbits_ids_array[i] != 0) {
jb_append_string(ctx.js,
VarNameStoreSetupLookup(s->init_data->rule_state_flowbits_ids_array[i],
VAR_TYPE_FLOW_BIT));
}
}
jb_close(ctx.js); // names
jb_close(ctx.js); // state_modifying_rules
}
jb_close(ctx.js); // upstream
jb_close(ctx.js); // flowbits
jb_close(ctx.js); // dependencies
}

jb_open_array(ctx.js, "flags");
if (s->flags & SIG_FLAG_SRC_ANY) {
jb_append_string(ctx.js, "src_any");
Expand Down
4 changes: 3 additions & 1 deletion src/detect-engine-build.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2023 Open Information Security Foundation
/* Copyright (C) 2007-2025 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
Expand Down Expand Up @@ -2092,6 +2092,8 @@ static int SigMatchPrepare(DetectEngineCtx *de_ctx)
IPOnlyCIDRListFree(s->init_data->cidr_src);

SCFree(s->init_data->buffers);
SCFree(s->init_data->rule_state_dependant_sids_array);
SCFree(s->init_data->rule_state_flowbits_ids_array);
SCFree(s->init_data);
s->init_data = NULL;
}
Expand Down
74 changes: 69 additions & 5 deletions src/detect-flowbits.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2022 Open Information Security Foundation
/* Copyright (C) 2007-2025 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
Expand Down Expand Up @@ -624,12 +624,76 @@ int DetectFlowbitsAnalyze(DetectEngineCtx *de_ctx)
SCLogDebug("SET flowbit %s/%u: SID %u", varname, i,
de_ctx->sig_array[array[i].set_sids[x]]->id);
}
for (uint32_t x = 0; x < array[i].isset_sids_idx; x++) {
Signature *s = de_ctx->sig_array[array[i].isset_sids[x]];
SCLogDebug("GET flowbit %s/%u: SID %u", varname, i, s->id);
if (to_state) {
for (uint32_t x = 0; x < array[i].isset_sids_idx; x++) {
Signature *s = de_ctx->sig_array[array[i].isset_sids[x]];
SCLogDebug("GET flowbit %s/%u: SID %u", varname, i, s->id);

if (to_state) {
s->init_data->init_flags |= SIG_FLAG_INIT_STATE_MATCH;
s->init_data->is_rule_state_dependant = true;

uint32_t sids_array_size = array[i].set_sids_idx;

// save information about flowbits that affect this rule's state
if (s->init_data->rule_state_dependant_sids_array == NULL) {
s->init_data->rule_state_dependant_sids_array =
SCCalloc(sids_array_size, sizeof(uint32_t));
if (s->init_data->rule_state_dependant_sids_array == NULL) {
SCLogError("Failed to allocate memory for rule_state_dependant_ids");
goto end;
}
s->init_data->rule_state_flowbits_ids_size = 1;
s->init_data->rule_state_flowbits_ids_array =
SCCalloc(s->init_data->rule_state_flowbits_ids_size, sizeof(uint32_t));
if (s->init_data->rule_state_flowbits_ids_array == NULL) {
SCLogError("Failed to allocate memory for rule_state_variable_idx");
goto end;
}
s->init_data->rule_state_dependant_sids_size = sids_array_size;
SCLogDebug("alloc'ed array for rule dependency and fbs idx array, sid %u, "
"sizes are %u and %u",
s->id, s->init_data->rule_state_dependant_sids_size,
s->init_data->rule_state_flowbits_ids_size);
} else {
uint32_t new_array_size =
s->init_data->rule_state_dependant_sids_size + sids_array_size;
void *tmp_ptr = SCRealloc(s->init_data->rule_state_dependant_sids_array,
new_array_size * sizeof(uint32_t));
if (tmp_ptr == NULL) {
SCLogError("Failed to allocate memory for rule_state_variable_idx");
goto end;
}
s->init_data->rule_state_dependant_sids_array = tmp_ptr;
s->init_data->rule_state_dependant_sids_size = new_array_size;
SCLogDebug("realloc'ed array for rule dependency, sid %u, new size is %u",
s->id, s->init_data->rule_state_dependant_sids_size);
uint32_t new_fb_array_size = s->init_data->rule_state_flowbits_ids_size + 1;
void *tmp_fb_ptr = SCRealloc(s->init_data->rule_state_flowbits_ids_array,
new_fb_array_size * sizeof(uint32_t));
s->init_data->rule_state_flowbits_ids_array = tmp_fb_ptr;
if (s->init_data->rule_state_flowbits_ids_array == NULL) {
SCLogError("Failed to reallocate memory for rule_state_variable_idx");
goto end;
}
SCLogDebug(
"realloc'ed array for flowbits ids, new size is %u", new_fb_array_size);
s->init_data->rule_state_dependant_sids_size = new_array_size;
s->init_data->rule_state_flowbits_ids_size = new_fb_array_size;
}
for (uint32_t idx = 0; idx < s->init_data->rule_state_dependant_sids_size; idx++) {
if (idx < array[i].set_sids_idx) {
s->init_data->rule_state_dependant_sids_array
[s->init_data->rule_state_dependant_sids_idx] =
de_ctx->sig_array[array[i].set_sids[idx]]->id;
s->init_data->rule_state_dependant_sids_idx++;
}
}
s->init_data
->rule_state_flowbits_ids_array[s->init_data->rule_state_flowbits_ids_size -
1] = i;
s->init_data->rule_state_flowbits_ids_size += 1;
// flowbit info saving for rule made stateful rule work finished

SCLogDebug("made SID %u stateful because it depends on "
"stateful rules that set flowbit %s", s->id, varname);
}
Expand Down
7 changes: 6 additions & 1 deletion src/detect-parse.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2021 Open Information Security Foundation
/* Copyright (C) 2007-2025 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
Expand Down Expand Up @@ -1564,6 +1564,11 @@ Signature *SigAlloc (void)
* overwritten, we can then assign the default value of 3 */
sig->prio = -1;

/* rule interdepency is false, at start */
sig->init_data->is_rule_state_dependant = false;
/* first index is 0 */
sig->init_data->rule_state_dependant_sids_idx = 0;

sig->init_data->list = DETECT_SM_LIST_NOTSET;
return sig;
}
Expand Down
10 changes: 9 additions & 1 deletion src/detect.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2023 Open Information Security Foundation
/* Copyright (C) 2007-2025 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
Expand Down Expand Up @@ -602,6 +602,14 @@ typedef struct SignatureInitData_ {

/* highest list/buffer id which holds a DETECT_CONTENT */
uint32_t max_content_list_id;

/* inter-signature state dependency */
bool is_rule_state_dependant;
uint32_t *rule_state_dependant_sids_array;
uint32_t rule_state_dependant_sids_size;
uint32_t rule_state_dependant_sids_idx;
uint32_t *rule_state_flowbits_ids_array;
uint32_t rule_state_flowbits_ids_size;
} SignatureInitData;

/** \brief Signature container */
Expand Down
Loading