]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
profiling/rules: Improve dynamic rule handling
authorJeff Lucovsky <jlucovsky@oisf.net>
Sat, 16 Mar 2024 12:58:11 +0000 (08:58 -0400)
committerVictor Julien <victor@inliniac.net>
Thu, 23 May 2024 15:27:37 +0000 (17:27 +0200)
Issue: 6861

Without this commit, disabling rule profiling via suricatasc's command
'ruleset-profile-stop' may crash because profiling_rules_entered becomes
negative.

This can happen because
- There can be multiple rules evaluated for a single packet
- Each rule is profiled individually.
- Starting profiling is gated by a configuration setting and rule
  profiling being active
- Ending profiling is gated by the same configuration setting and
  whether the packet was marked as profiling.

The crash can occur when a rule is being profiled and rule profiling
is then disabled after one at least one rule was profiled for the packet
(which marks the packet as being profiled).

In this scenario, the value of profiling_rules_entered was
not incremented so the BUG_ON in the end profiling macro trips
because it is 0.

The changes to fix the problem are:
- In the profiling end macro, gate the actions taken there by the same
  configuration setting and use the profiling_rues_entered (instead of
  the per-packet profiling flag). Since the start and end macros are
  tightly coupled, this will permit profiling to "finish" if started.
- Modify SCProfileRuleStart to only check the sampling values if the
  packet hasn't been marked for profiling already. This change makes all
  rules for a packet (once selected) to be profiled (without this change
  sampling is applied to each *rule* that applies to the packet.

(cherry picked from commit bf5cfd6ab7c728125c09c1ee5fb36c4906dc02ea)

src/util-profiling.c
src/util-profiling.h

index 5d4bcc8905ce281ac6a01d9588139fa3b019dc7a..e1f19ad20c4113bf64daeb01d258b77eb70f518a 100644 (file)
@@ -1208,15 +1208,16 @@ int SCProfileRuleStart(Packet *p)
         p->flags |= PKT_PROFILE;
         return 1;
     }
-#else
+#endif
+    if (p->flags & PKT_PROFILE) {
+        return 1;
+    }
+
     uint64_t sample = SC_ATOMIC_ADD(samples, 1);
-    if (sample % rate == 0) {
+    if ((sample % rate) == 0) {
         p->flags |= PKT_PROFILE;
         return 1;
     }
-#endif
-    if (p->flags & PKT_PROFILE)
-        return 1;
     return 0;
 }
 
@@ -1450,17 +1451,20 @@ void SCProfilingInit(void)
 /* see if we want to profile rules for this packet */
 int SCProfileRuleStart(Packet *p)
 {
+    /* Move first so we'll always finish even if dynamically disabled */
+    if (p->flags & PKT_PROFILE)
+        return 1;
+
     if (!SC_ATOMIC_GET(profiling_rules_active)) {
         return 0;
     }
+
     uint64_t sample = SC_ATOMIC_ADD(samples, 1);
     if ((sample & rate) == 0) {
         p->flags |= PKT_PROFILE;
         return 1;
     }
 
-    if (p->flags & PKT_PROFILE)
-        return 1;
     return 0;
 }
 
index 6450bc8cefe3f5b72102b18c41d89d0f5423c519..c066d0b36f40e01a5ca2c49973c8a722de268b7a 100644 (file)
@@ -417,7 +417,7 @@ void SCProfilingRuleThreatAggregate(DetectEngineThreadCtx *det_ctx);
     }
 
 #define RULE_PROFILING_END(ctx, r, m, p)                                                           \
-    if (profiling_rules_enabled && ((p)->flags & PKT_PROFILE)) {                                   \
+    if (profiling_rules_enabled && profiling_rules_entered) {                                      \
         profile_rule_end_ = UtilCpuGetTicks();                                                     \
         SCProfilingRuleUpdateCounter(                                                              \
                 ctx, r->profiling_id, profile_rule_end_ - profile_rule_start_, m);                 \