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
pull/16497/head
Philippe Antoine 2 months ago committed by Victor Julien
parent 4e875c80d7
commit f87b8e64a5

@ -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)) {

@ -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)
{

@ -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 *);

Loading…
Cancel
Save