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

Feat/flowbit prefilter/v24 #12132

Closed

Conversation

victorjulien
Copy link
Member

Draft for QA/CI & review. Not fully ready yet.

SV_BRANCH=OISF/suricata-verify#2131

https://redmine.openinfosecfoundation.org/issues/2486

victorjulien and others added 4 commits November 19, 2024 15:18
In preparation of flowbit prefilter work that needs this info
earlier.

Track potential prefilter sm's to avoid unnecessary looping during
setup.
Allow for more efficient rules that 'prefilter' on flowbits with 'isset' logic.

This prefilter is enabled by default, which means that if no mpm is present or
no explicit prefilter is used, the flowbits prefilter will be set up for a rule.

flowbits 'isset' prefilter

For rules that have a 'flowbits:isset,<bit>' statement, a "regular" prefilter
facility is created. It means that the rules are removed from the normal
match list(s) and added to a prefilter engine that runs prior to the individual
rule inspection stage.

Implementation: the prefilter is implemented as an RB_TREE of flowbits, with the
rule id's they "enable" stored per tree node. The matching logic is walking the
list of bits set in the flow and looking each of them up in the RB_TREE, adding
the rule ids of each of the matching bits to the list of rule candidates.

The 'isset' prefilter has one important corner case, which is that bits can in
fact be set during the rule evaluation stage. This is different from all other
prefilter engines, that evaluate an immutable state (for the lifetime of the
packets inspection).

flowbits 'set' post-match prefilter

For flowbits 'set' action, special post-match 'prefilter' facilities deal with
this corner case. The high level logic is that these track which 'isset' sigs
depend on them, and add these dependencies to the candidates list when a 'set'
action occurs.

This is implemented in a few steps:

1. flowbits 'set' is flagged
2. when 'set' action occurs the flowbit is added to a "post rule
   match work queue"
3. when the rule evaluation ends, the post-match "prefilter" engine is run
   on each of the flowbits in the "post rule match work queue"
4. these engines ammend the candidates list with the rule id dependencies
   for the flowbit
5. the candidates list is sorted to make sure within the execution for that
   packet the inspection order is maintained

Ticket: OISF#2486.
@@ -2523,6 +2523,9 @@ static DetectEngineCtx *DetectEngineCtxInitReal(
goto error;
}

// TODO test enable flowbits prefilter
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to check how we may enable a selection of prefilter engines for keywords, but not all.

src/detect-flowbits.c Outdated Show resolved Hide resolved
void *ptr = SCRealloc(
det_ctx->post_rule_work_queue.q, (det_ctx->post_rule_work_queue.size + QUEUE_STEP) *
sizeof(PostRuleMatchWorkQueueItem));
BUG_ON(ptr == NULL);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: error handle

src/detect-flowbits.c Outdated Show resolved Hide resolved
src/detect-flowbits.c Outdated Show resolved Hide resolved
return 0;
}

// TODO misses IPOnly rules. IPOnly flowbit rules are set only though.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests appear to show this is not an issue

src/detect-flowbits.c Outdated Show resolved Hide resolved
src/detect-flowbits.c Outdated Show resolved Hide resolved

#define BLOCK_SIZE 8

static int AddBitIsset(const DetectEngineCtx *de_ctx, struct PrefilterEngineFlowbits *ctx,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func needs docs and error handling

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also needs cleanup as there is duplication between or and non-or support

return added;
}

/* TODO shouldn't add sids for which Signature::num is < our num. Is this possible after sorting? */
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to see if I can reach this condition in a test

if (fb->cmd == DETECT_FLOWBITS_CMD_SET) {
SCLogDebug(
"DETECT_SM_LIST_POSTMATCH: sid %u DETECT_FLOWBITS set %u", s->id, fb->idx);
// else if (fb->cmd == DETECT_FLOWBITS_CMD_TOGGLE) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: review 'toggle' support

}

SCLogDebug("setting up sets/toggles for sid %u", s->id);
if (AddBitSetToggle(de_ctx, &fb_analysis, set_ctx, fb, s) == 1) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this builds a post-rule-match state, that looks at which isset flowbits depend on the current "set" flowbit. Need to make this code clearer, and doc it

fb->prefilter = true; // flag the set/toggle to trigger the post-rule match logic
}

// TODO don't add for sigs that don't have isset in this sgh. Reasoning:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: this is essentially done in AddSids above

}

const DetectFlowbitsData *fb = (DetectFlowbitsData *)s->init_data->prefilter_sm->ctx;
if (fb_analysis.array[fb->idx].toggle_sids_idx ||
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this uses the per sgh analysis, but maybe we need to check this for all groups?

}

if (set_ctx == NULL) {
set_ctx = SCCalloc(1, sizeof(*set_ctx));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this "set" post-rule-prefilter state should only be built if there are isset flowbit rules, with prefilter enabled, in the same sgh. Need to review is this is checked correctly.

src/detect-flowbits.h Outdated Show resolved Hide resolved
/* rewrite match_array to include the new additions */
Signature **m = match_array;
for (uint32_t x = 0; x < match_cnt; x++) {
*m++ = (Signature *)replace[x];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memcpy?

/* run post match prefilter engines on work queue */
PrefilterPostRuleMatch(det_ctx, scratch->sgh, p, pflow);

if (det_ctx->pmq.rule_id_array_cnt > 0) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably move this into a helper func

de_ctx->sig_array_len, det_ctx->pmq.rule_id_array_cnt);
const Signature **r = replace;
for (uint32_t x = 0; x < match_cnt; x++) {
*r++ = match_array[x];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memcpy?

}
/* append the prefilter results, then sort it */
for (uint32_t x = 0; x < det_ctx->pmq.rule_id_array_cnt; x++) {
// TODO what happens if a tx engine is added?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to look into this

match_cnt++;
}
}
// TODO if sid 12 is added twice, how do we dedup
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will try to add a test for this

src/detect.h Outdated Show resolved Hide resolved
Copy link

codecov bot commented Nov 19, 2024

Codecov Report

Attention: Patch coverage is 87.86611% with 87 lines in your changes missing coverage. Please review.

Project coverage is 83.01%. Comparing base (5d766df) to head (c036600).
Report is 158 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##           master   #12132       +/-   ##
===========================================
+ Coverage   62.68%   83.01%   +20.32%     
===========================================
  Files         840      909       +69     
  Lines      153669   258309   +104640     
===========================================
+ Hits        96323   214427   +118104     
+ Misses      57346    43882    -13464     
Flag Coverage Δ
fuzzcorpus 60.18% <22.50%> (?)
livemode 19.39% <4.01%> (?)
pcap 44.27% <17.68%> (?)
suricata-verify 62.80% <85.04%> (+0.12%) ⬆️
unittests 59.17% <29.42%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

@suricata-qa
Copy link

Information: QA ran without warnings.

Pipeline 23430

@suricata-qa
Copy link

Information:

ERROR: QA failed on SURI_TLPR1_alerts_cmp.

field baseline test %
SURI_TLPR1_stats_chk
.app_layer.flow.dcerpc_tcp 40 42 105.0%

Pipeline 23439

@suricata-qa
Copy link

Information:

ERROR: QA failed on SURI_TLPR1_alerts_cmp.

field baseline test %
SURI_TLPR1_stats_chk
.app_layer.flow.dcerpc_tcp 40 42 105.0%

Pipeline 23467

@victorjulien victorjulien force-pushed the feat/flowbit-prefilter/v24 branch from f6b294b to c036600 Compare November 21, 2024 12:38
@suricata-qa
Copy link

Information:

ERROR: QA failed on SURI_TLPR1_alerts_cmp.

field baseline test %
SURI_TLPR1_stats_chk
.app_layer.flow.dcerpc_tcp 40 42 105.0%

Pipeline 23475

@victorjulien
Copy link
Member Author

replaced by #12380

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants