-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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/v26 #12662
base: master
Are you sure you want to change the base?
Feat/flowbit prefilter/v26 #12662
Conversation
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.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #12662 +/- ##
========================================
Coverage 80.77% 80.78%
========================================
Files 932 932
Lines 259517 259990 +473
========================================
+ Hits 209629 210028 +399
- Misses 49888 49962 +74
Flags with carried forward coverage won't be shown. Click here to find out more. |
Information: QA ran without warnings. Pipeline 24875 |
if (sgh->init->post_rule_match_engines == NULL) { | ||
sgh->init->post_rule_match_engines = e; | ||
} else { | ||
PrefilterEngineList *t = sgh->init->post_rule_match_engines; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this list expected to be more than a few items? If so, would a list/queue that allows tail adds be more efficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently just one I think.
/** \brief add a flowbit to the flow | ||
* \retval -1 error | ||
* \retval 0 not added, already set before | ||
* \retval 1 added */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wonder if using an enum would be better...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding a enum just for this func seems like overkill to me, but perhaps it makes sense explore this for a bit more generally throughout more API calls
I wonder how much of this need is covered by #12646 ... |
Why ? |
This looks strange and counterintuitive.
How does the engine know to run first the rules that set flowbits before the ones that need them ? |
During rule ordering a rule that sets a bit will be put before a sigs that checks the bit. |
Most flowbits will not use this, so the id space is quite sparse. An array is going to be large. |
How do you handle cycles ? Like
|
Indeed, but are not a few kilobytes of RAM worth the nanoseconds for direct access ? I think prefilter is about optimizing speed, right ? |
This isn't new, the ordering code exists for a long time already. |
This discussion is getting ahead of itself. If you want to argue about the performance you'll have to bring profiling results, not just theory to the table here. |
Sure. |
I am just discussing the design, I did not even look at the code. I can do a benchmark to show that |
I mean of this implementation with a real world use case. |
For the "important corner case", am I correct to say that a dumb implementation of prefilter without this corner case will make
with a packet that is not trigger rule 12 when it should (and does trigger without the prefilter keyword), because rule 12 will be skipped at prefilter stage ? Does it make sense for rule writers to prefilter on a flowbit that will be set during rules evaluation ? |
@@ -861,6 +871,51 @@ static inline void DetectRulePacketRules( | |||
} | |||
} | |||
AlertQueueAppend(det_ctx, s, p, txid, alert_flags); | |||
|
|||
if (det_ctx->post_rule_work_queue.len > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be a while
?
Like for
alert http any any -> any any (http.uri; content:"test"; flowbits:set,uritest; sid:11;)
alert http any any -> any any (http.method; content:"HEAD"; flowbits:isset,uritest; prefilter; flowbits:set,headtest; sid:12;)
alert http any any -> any any (http.ua; content:"toto"; flowbits:isset, headtest; prefilter; sid:13;)
- Prefilter removes sids 12 and 13 because flowbits are not set
- Rule evaluation makes sid 11 match and set flowbit uritest
- We run post-"prefilter" for flowbit uritest, get sid 12
- Rule evaluation makes sid 12 match and set flowbit headtest
- We run post-"prefilter" again but for flowbit headtest, get sid 13
- Rule evaluation makes sid 13 match and we have no more new flowbits set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why it should be a while. It's run a single time per signature that has this functionality enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed because the loop is done one level up as for (uint32_t i = 0; i < array_idx; i++) {
and we just keep increasing the array
Partly, but flowbits have a much wider scope. Ppl build state machines with them. |
It should not be affected by prefilter or not. Sid 11 will be evaluated first, because rule sorting puts it before 12 due to the flowbit set. In non-prefilter, sid 12 would be evaluated, and in the evaluation we check if the flowbit "uritest" was set. In the prefilter case sid 11 "knows" which sids depend on it, and it will add those dependencies for evaluation to the list of sig candidates. So without the match of sid 11, sid 12 would not have been evaluated. But now it is. |
Sure, but I can feel people doing flowbits because they do not have bidirectional rules, and then complain that the second rule does not have a good fast_pattern... |
To be closed in favor of #12681 ? |
You mean that is what your smart PR does with |
https://redmine.openinfosecfoundation.org/issues/2486
Rebase of #12380, also addresses some of the issues.
SV_BRANCH=OISF/suricata-verify#2317