From f87b8e64a5fb80788897f7a9073c5407a2f5bc96 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Mon, 7 Sep 2026 14:48:58 +0200 Subject: [PATCH] detect: update progress in case of pcre-only rule group Ticket: 8684 The behavior of the rule alert ip any any -> any any (pcre:"/.*mc|\H+$/"; sid:4;) depended upon the presence of another rule such as alert ip any any -> any any (content:"*mcH"; sid:5;) With the sid 5 content rule, the code went through PrefilterPktStream which updated raw_stream_progress, which ended up updating raw_progress_rel which was used on later packets to know where to start. Without the sid 5 content rule, there was no update of these progresses. It led to quadratic complexity, as for each new packet, we ran the pcre engine on the whole tcp stream from the beginning, with the newly added payload data. Fix is to process sid 4 pcre rule the same way whether there is or there is not a sid 5 content rule. So, in case we do not have a mpm store for a signature group head, we register a dummy stream prefilter, whose goal will just be to update raw_stream_progress --- src/detect-engine-mpm.c | 22 ++++++++++++++++------ src/detect-engine-payload.c | 26 ++++++++++++++++++++++++++ src/detect-engine-payload.h | 1 + 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index 88e807a4f5..694fc26112 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -2402,11 +2402,17 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_STREAM_TS); - if (mpm_store != NULL) { + SetRawReassemblyFlag(de_ctx, sh); + if (mpm_store != NULL && mpm_store->mpm_ctx) { PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx); + } else if (sh->flags & SIG_GROUP_HEAD_HAVERAWSTREAM) { + MpmCtx *mpm_ctx = SCCalloc(1, sizeof(MpmCtx)); + if (mpm_ctx) { + // we want to update raw_stream_progress + // also when sgh does not have prefilter + PrefilterPktStreamRegisterNoMpm(de_ctx, sh, mpm_ctx); + } } - - SetRawReassemblyFlag(de_ctx, sh); } if (SGH_DIRECTION_TC(sh)) { mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TC); @@ -2415,11 +2421,15 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_STREAM_TC); - if (mpm_store != NULL) { + SetRawReassemblyFlag(de_ctx, sh); + if (mpm_store != NULL && mpm_store->mpm_ctx) { PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx); + } else if (sh->flags & SIG_GROUP_HEAD_HAVERAWSTREAM) { + MpmCtx *mpm_ctx = SCCalloc(1, sizeof(MpmCtx)); + if (mpm_ctx) { + PrefilterPktStreamRegisterNoMpm(de_ctx, sh, mpm_ctx); + } } - - SetRawReassemblyFlag(de_ctx, sh); } } else if (SGH_PROTO(sh, IPPROTO_UDP)) { if (SGH_DIRECTION_TS(sh)) { diff --git a/src/detect-engine-payload.c b/src/detect-engine-payload.c index ede9ad241d..cd8e311ad2 100644 --- a/src/detect-engine-payload.c +++ b/src/detect-engine-payload.c @@ -70,6 +70,21 @@ static int StreamMpmFunc( return 0; } +static int StreamMpmFuncNop( + void *cb_data, const uint8_t *data, const uint32_t data_len, const uint64_t _offset) +{ + return 0; +} + +static void PrefilterPktStreamNoMpm(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) +{ + /* used to advance raw_stream_progress */ + if (p->flags & PKT_DETECT_HAS_STREAMDATA) { + StreamReassembleRaw( + p->flow->protoctx, p, StreamMpmFuncNop, NULL, &det_ctx->raw_stream_progress, false); + } +} + static void PrefilterPktStream(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { @@ -112,6 +127,17 @@ int PrefilterPktStreamRegister(DetectEngineCtx *de_ctx, PrefilterPktStream, mpm_ctx, NULL, "stream"); } +static void FreePrefilterNoMpmCtx(void *ctx) +{ + SCFree(ctx); +} + +int PrefilterPktStreamRegisterNoMpm(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx) +{ + return PrefilterAppendPayloadEngine(de_ctx, sgh, PrefilterPktStreamNoMpm, mpm_ctx, + FreePrefilterNoMpmCtx, "stream_progress_only"); +} + static void PrefilterPktPayload(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { diff --git a/src/detect-engine-payload.h b/src/detect-engine-payload.h index bafaf790cc..832e490bd6 100644 --- a/src/detect-engine-payload.h +++ b/src/detect-engine-payload.h @@ -28,6 +28,7 @@ int PrefilterPktPayloadRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx); int PrefilterPktStreamRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx); +int PrefilterPktStreamRegisterNoMpm(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx); uint8_t DetectEngineInspectPacketPayload( DetectEngineCtx *, DetectEngineThreadCtx *, const Signature *, Flow *, Packet *);