Fix a content pattern matching bug related to signature grouping and mpm_ctx sharing. In certain conditions (signature combinations) the mpm_stream_ctx (the ctx that handles stream pattern scanning) wasn't properly setup.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent 18840bd96e
commit 0219b767b8

@ -75,6 +75,87 @@ SCEnumCharMap sc_mpm_algo_map[] = {
#endif #endif
}; };
/**
* \brief check if a signature has patterns that are to be inspected
* against a packets payload (as opposed to the stream payload)
*
* \param s signature
*
* \retval 1 true
* \retval 0 false
*/
int SignatureHasPacketContent(Signature *s) {
SCEnter();
if (s == NULL) {
SCReturnInt(0);
}
if (!(s->flags & SIG_FLAG_MPM)) {
SCLogDebug("no mpm");
SCReturnInt(0);
}
if (s->alproto != ALPROTO_UNKNOWN) {
SCLogDebug("inspecting app layer");
SCReturnInt(0);
}
SigMatch *sm = s->pmatch;
if (sm == NULL) {
SCReturnInt(0);
}
for ( ;sm != NULL; sm = sm->next) {
if (sm->type == DETECT_CONTENT) {
SCReturnInt(1);
}
}
SCReturnInt(0);
}
/**
* \brief check if a signature has patterns that are to be inspected
* against the stream payload (as opposed to the individual packets
* payload(s))
*
* \param s signature
*
* \retval 1 true
* \retval 0 false
*/
int SignatureHasStreamContent(Signature *s) {
SCEnter();
if (s == NULL) {
SCReturnInt(0);
}
if (!(s->flags & SIG_FLAG_MPM)) {
SCLogDebug("no mpm");
SCReturnInt(0);
}
if (s->flags & SIG_FLAG_DSIZE) {
SCLogDebug("dsize");
SCReturnInt(0);
}
SigMatch *sm = s->pmatch;
if (sm == NULL) {
SCReturnInt(0);
}
for ( ;sm != NULL; sm = sm->next) {
if (sm->type == DETECT_CONTENT) {
SCReturnInt(1);
}
}
SCReturnInt(0);
}
/** \brief Function to return the default multi pattern matcher algorithm to be /** \brief Function to return the default multi pattern matcher algorithm to be
* used by the engine * used by the engine
@ -292,15 +373,18 @@ void PatternMatchDestroyGroup(SigGroupHead *sh) {
} }
/* stream content */ /* stream content */
if (sh->flags & SIG_GROUP_HAVESTREAMCONTENT && sh->mpm_stream_ctx != NULL && if (sh->flags & SIG_GROUP_HAVESTREAMCONTENT) {
!(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) { if (sh->mpm_stream_ctx != NULL) {
SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx, sh); if (!(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) {
mpm_table[sh->mpm_stream_ctx->mpm_type].DestroyCtx(sh->mpm_stream_ctx); SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx, sh);
SCFree(sh->mpm_stream_ctx); mpm_table[sh->mpm_stream_ctx->mpm_type].DestroyCtx(sh->mpm_stream_ctx);
SCFree(sh->mpm_stream_ctx);
/* ready for reuse */
sh->mpm_stream_ctx = NULL; /* ready for reuse */
sh->flags &= ~SIG_GROUP_HAVESTREAMCONTENT; sh->mpm_stream_ctx = NULL;
sh->flags &= ~SIG_GROUP_HAVESTREAMCONTENT;
}
}
} }
} }
@ -628,35 +712,34 @@ static int PatternMatchPreprarePopulateMpm(DetectEngineCtx *de_ctx, SigGroupHead
} }
} }
if (s->flags & SIG_FLAG_DSIZE) { scan_packet = SignatureHasPacketContent(s);
scan_packet = 1; scan_stream = SignatureHasStreamContent(s);
} else if (s->alproto == ALPROTO_UNKNOWN) {
scan_packet = 1;
scan_stream = 1;
} else {
scan_stream = 1;
}
if (scan_packet) { if (scan_packet) {
/* add the content to the "packet" mpm */ if (sgh->flags & SIG_GROUP_HAVECONTENT && !(sgh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
if (co->flags & DETECT_CONTENT_NOCASE) { /* add the content to the "packet" mpm */
mpm_table[sgh->mpm_ctx->mpm_type].AddPatternNocase(sgh->mpm_ctx, if (co->flags & DETECT_CONTENT_NOCASE) {
co->content, co->content_len, offset, depth, co->id, mpm_table[sgh->mpm_ctx->mpm_type].AddPatternNocase(sgh->mpm_ctx,
s->num, flags); co->content, co->content_len, offset, depth, co->id,
} else { s->num, flags);
mpm_table[sgh->mpm_ctx->mpm_type].AddPattern(sgh->mpm_ctx, } else {
co->content, co->content_len, offset, depth, co->id, mpm_table[sgh->mpm_ctx->mpm_type].AddPattern(sgh->mpm_ctx,
s->num, flags); co->content, co->content_len, offset, depth, co->id,
s->num, flags);
}
} }
} }
if (scan_stream) { if (scan_stream) {
/* add the content to the "stream" mpm */ if (sgh->flags & SIG_GROUP_HAVESTREAMCONTENT && !(sgh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) {
if (co->flags & DETECT_CONTENT_NOCASE) { SCLogDebug("mpm_stream_ctx %p", sgh->mpm_stream_ctx);
mpm_table[sgh->mpm_stream_ctx->mpm_type].AddPatternNocase(sgh->mpm_stream_ctx, /* add the content to the "stream" mpm */
co->content, co->content_len, offset, depth, co->id, s->num, flags); if (co->flags & DETECT_CONTENT_NOCASE) {
} else { mpm_table[sgh->mpm_stream_ctx->mpm_type].AddPatternNocase(sgh->mpm_stream_ctx,
mpm_table[sgh->mpm_stream_ctx->mpm_type].AddPattern(sgh->mpm_stream_ctx, co->content, co->content_len, offset, depth, co->id, s->num, flags);
co->content, co->content_len, offset, depth, co->id, s->num, flags); } else {
mpm_table[sgh->mpm_stream_ctx->mpm_type].AddPattern(sgh->mpm_stream_ctx,
co->content, co->content_len, offset, depth, co->id, s->num, flags);
}
} }
} }
@ -694,7 +777,8 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
{ {
Signature *s = NULL; Signature *s = NULL;
SigMatch *sm = NULL; SigMatch *sm = NULL;
uint32_t co_cnt = 0; uint32_t has_co_packet = 0; /**< our sgh has packet payload inspecting content */
uint32_t has_co_stream = 0; /**< our shg has stream inspecting content */
uint32_t ur_cnt = 0; uint32_t ur_cnt = 0;
uint32_t cnt = 0; uint32_t cnt = 0;
uint32_t sig = 0; uint32_t sig = 0;
@ -717,12 +801,11 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
if (s == NULL) if (s == NULL)
continue; continue;
/* find flow setting of this rule */ if (SignatureHasPacketContent(s) == 1) {
for (sm = s->pmatch; sm != NULL; sm = sm->next) { has_co_packet = 1;
if (sm->type == DETECT_CONTENT) { }
co_cnt++; if (SignatureHasStreamContent(s) == 1) {
s->flags |= SIG_FLAG_MPM; has_co_stream = 1;
}
} }
for (sm = s->umatch; sm != NULL; sm = sm->next) { for (sm = s->umatch; sm != NULL; sm = sm->next) {
@ -733,9 +816,12 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
} }
} }
if (co_cnt > 0) { if (has_co_packet > 0) {
sh->flags |= SIG_GROUP_HAVECONTENT; sh->flags |= SIG_GROUP_HAVECONTENT;
} }
if (has_co_stream > 0) {
sh->flags |= SIG_GROUP_HAVESTREAMCONTENT;
}
if (ur_cnt > 0) { if (ur_cnt > 0) {
sh->flags |= SIG_GROUP_HAVEURICONTENT; sh->flags |= SIG_GROUP_HAVEURICONTENT;
} }
@ -753,20 +839,21 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
#else #else
MpmInitCtx(sh->mpm_ctx, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle); MpmInitCtx(sh->mpm_ctx, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle);
#endif #endif
//if (sh->flags & SIG_GROUP_HAVESTREAMCONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) { }
sh->mpm_stream_ctx = SCMalloc(sizeof(MpmCtx));
if (sh->mpm_stream_ctx == NULL) if (sh->flags & SIG_GROUP_HAVESTREAMCONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) {
goto error; sh->mpm_stream_ctx = SCMalloc(sizeof(MpmCtx));
if (sh->mpm_stream_ctx == NULL)
goto error;
memset(sh->mpm_stream_ctx, 0x00, sizeof(MpmCtx)); memset(sh->mpm_stream_ctx, 0x00, sizeof(MpmCtx));
#ifndef __SC_CUDA_SUPPORT__ #ifndef __SC_CUDA_SUPPORT__
MpmInitCtx(sh->mpm_stream_ctx, de_ctx->mpm_matcher, -1); MpmInitCtx(sh->mpm_stream_ctx, de_ctx->mpm_matcher, -1);
#else #else
MpmInitCtx(sh->mpm_stream_ctx, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle); MpmInitCtx(sh->mpm_stream_ctx, de_ctx->mpm_matcher, de_ctx->cuda_rc_mod_handle);
#endif #endif
//}
} }
if (sh->flags & SIG_GROUP_HAVEURICONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) { if (sh->flags & SIG_GROUP_HAVEURICONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) {
sh->mpm_uri_ctx = SCMalloc(sizeof(MpmCtx)); sh->mpm_uri_ctx = SCMalloc(sizeof(MpmCtx));
if (sh->mpm_uri_ctx == NULL) if (sh->mpm_uri_ctx == NULL)
@ -991,14 +1078,34 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
} }
} }
/* load the patterns */
PatternMatchPreprarePopulateMpm(de_ctx, sh);
/* content */ /* content */
if (sh->flags & SIG_GROUP_HAVECONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) { if (sh->flags & SIG_GROUP_HAVECONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
/* load the patterns */
PatternMatchPreprarePopulateMpm(de_ctx, sh);
if (mpm_table[sh->mpm_ctx->mpm_type].Prepare != NULL) { if (mpm_table[sh->mpm_ctx->mpm_type].Prepare != NULL) {
mpm_table[sh->mpm_ctx->mpm_type].Prepare(sh->mpm_ctx); mpm_table[sh->mpm_ctx->mpm_type].Prepare(sh->mpm_ctx);
} }
if (mpm_content_maxdepth) {
// printf("mpm_content_maxdepth %" PRIu32 "\n", mpm_content_maxdepth);
g_content_maxdepth++;
}
if (mpm_content_minoffset) {
// printf("mpm_content_minoffset %" PRIu32 "\n", mpm_content_minoffset);
g_content_minoffset++;
}
g_content_total++;
//if (mpm_content_depth_present) printf("(sh %p) at least one depth: %" PRId32 ", depth %" PRIu32 "\n", sh, mpm_content_depth_present, mpm_content_maxdepth_one);
//if (mpm_content_offset_present) printf("(sh %p) at least one offset: %" PRId32 ", offset %" PRIu32 "\n", sh, mpm_content_offset_present, mpm_content_minoffset_one);
//sh->mpm_ctx->PrintCtx(sh->mpm_ctx);
}
/* content */
if (sh->flags & SIG_GROUP_HAVESTREAMCONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) {
SCLogDebug("preparing mpm_stream_ctx %p", sh->mpm_stream_ctx);
if (mpm_table[sh->mpm_stream_ctx->mpm_type].Prepare != NULL) { if (mpm_table[sh->mpm_stream_ctx->mpm_type].Prepare != NULL) {
mpm_table[sh->mpm_stream_ctx->mpm_type].Prepare(sh->mpm_stream_ctx); mpm_table[sh->mpm_stream_ctx->mpm_type].Prepare(sh->mpm_stream_ctx);
} }

@ -1441,36 +1441,48 @@ int SigGroupHeadClearUricontent(SigGroupHead *sh)
*/ */
int SigGroupHeadLoadStreamContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) int SigGroupHeadLoadStreamContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
{ {
SCEnter();
Signature *s = NULL; Signature *s = NULL;
SigMatch *sm = NULL; SigMatch *sm = NULL;
uint32_t sig = 0; uint32_t sig = 0;
DetectContentData *co = NULL; DetectContentData *co = NULL;
if (sgh == NULL) if (sgh == NULL) {
return 0; SCReturnInt(0);
}
if (DetectContentMaxId(de_ctx) == 0) if (DetectContentMaxId(de_ctx) == 0) {
return 0; SCReturnInt(0);
}
BUG_ON(sgh->init == NULL); BUG_ON(sgh->init == NULL);
sgh->init->stream_content_size = (DetectContentMaxId(de_ctx) / 8) + 1; sgh->init->stream_content_size = (DetectContentMaxId(de_ctx) / 8) + 1;
sgh->init->stream_content_array = SCMalloc(sgh->init->stream_content_size); sgh->init->stream_content_array = SCMalloc(sgh->init->stream_content_size);
if (sgh->init->stream_content_array == NULL) if (sgh->init->stream_content_array == NULL) {
return -1; SCReturnInt(-1);
}
memset(sgh->init->stream_content_array,0, sgh->init->stream_content_size); memset(sgh->init->stream_content_array,0, sgh->init->stream_content_size);
for (sig = 0; sig < sgh->sig_cnt; sig++) { for (sig = 0; sig < sgh->sig_cnt; sig++) {
s = sgh->match_array[sig]; s = sgh->match_array[sig];
SCLogDebug("s %"PRIu32, s->id);
if (s == NULL) if (s == NULL)
continue; continue;
if (!(s->flags & SIG_FLAG_MPM)) if (!(s->flags & SIG_FLAG_MPM)) {
SCLogDebug("no mpm");
continue; continue;
}
if (s->flags & SIG_FLAG_DSIZE) if (s->flags & SIG_FLAG_DSIZE) {
SCLogDebug("dsize");
continue; continue;
}
sm = s->pmatch; sm = s->pmatch;
if (sm == NULL) if (sm == NULL)
@ -1485,7 +1497,7 @@ int SigGroupHeadLoadStreamContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
} }
} }
return 0; SCReturnInt(0);
} }
/** /**

@ -777,10 +777,15 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
/* have a look at the reassembled stream (if any) */ /* have a look at the reassembled stream (if any) */
if (p->flowflags & FLOW_PKT_ESTABLISHED) { if (p->flowflags & FLOW_PKT_ESTABLISHED) {
SCLogDebug("p->flowflags & FLOW_PKT_ESTABLISHED");
if (smsg != NULL && det_ctx->sgh->mpm_stream_ctx != NULL) { if (smsg != NULL && det_ctx->sgh->mpm_stream_ctx != NULL) {
cnt = StreamPatternSearch(th_v, det_ctx, p, smsg, flags); cnt = StreamPatternSearch(th_v, det_ctx, p, smsg, flags);
SCLogDebug("cnt %u", cnt); SCLogDebug("cnt %u", cnt);
} else {
SCLogDebug("smsg NULL (%p) or det_ctx->sgh->mpm_stream_ctx NULL (%p)", smsg, det_ctx->sgh->mpm_stream_ctx);
} }
} else {
SCLogDebug("NOT p->flowflags & FLOW_PKT_ESTABLISHED");
} }
if (p->payload_len > 0 && det_ctx->sgh->mpm_ctx != NULL && if (p->payload_len > 0 && det_ctx->sgh->mpm_ctx != NULL &&
@ -2473,7 +2478,7 @@ int BuildDestinationAddressHeadsWithBothPorts(DetectEngineCtx *de_ctx, DetectAdd
} else { } else {
/* XXX write dedicated function for this */ /* XXX write dedicated function for this */
dp->sh->mpm_ctx = mpmsh->mpm_ctx; dp->sh->mpm_ctx = mpmsh->mpm_ctx;
//SCLogDebug("replacing dp->sh, so setting mpm_content_maxlen to %u", mpmsh->mpm_content_maxlen); //SCLogDebug("replacing dp->sh, so setting mpm_content_maxlen to %u (was %u)", mpmsh->mpm_content_maxlen, dp->sh->mpm_content_maxlen);
//dp->sh->mpm_content_maxlen = mpmsh->mpm_content_maxlen; //dp->sh->mpm_content_maxlen = mpmsh->mpm_content_maxlen;
dp->sh->flags |= SIG_GROUP_HEAD_MPM_COPY; dp->sh->flags |= SIG_GROUP_HEAD_MPM_COPY;
SigGroupHeadClearContent(dp->sh); SigGroupHeadClearContent(dp->sh);
@ -2482,6 +2487,27 @@ int BuildDestinationAddressHeadsWithBothPorts(DetectEngineCtx *de_ctx, DetectAdd
} }
} }
/* content */
SigGroupHeadLoadStreamContent(de_ctx, dp->sh);
if (dp->sh->init->stream_content_size == 0) {
de_ctx->mpm_none++;
} else {
/* now have a look if we can reuse a mpm ctx */
SigGroupHead *mpmsh = SigGroupHeadMpmStreamHashLookup(de_ctx, dp->sh);
if (mpmsh == NULL) {
SigGroupHeadMpmStreamHashAdd(de_ctx, dp->sh);
de_ctx->mpm_unique++;
} else {
SCLogDebug("replacing mpm_stream_ctx %p by %p", dp->sh->mpm_stream_ctx, mpmsh->mpm_stream_ctx);
dp->sh->mpm_stream_ctx = mpmsh->mpm_stream_ctx;
dp->sh->flags |= SIG_GROUP_HEAD_MPM_STREAM_COPY;
SigGroupHeadClearStreamContent(dp->sh);
de_ctx->mpm_reuse++;
}
}
SigGroupHeadLoadUricontent(de_ctx, dp->sh); SigGroupHeadLoadUricontent(de_ctx, dp->sh);
if (dp->sh->init->uri_content_size == 0) { if (dp->sh->init->uri_content_size == 0) {
de_ctx->mpm_uri_none++; de_ctx->mpm_uri_none++;
@ -2834,7 +2860,7 @@ int SigAddressPrepareStage5(DetectEngineCtx *de_ctx) {
for (f = 0; f < FLOW_STATES; f++) { for (f = 0; f < FLOW_STATES; f++) {
printf("\n"); printf("\n");
for (proto = 0; proto < 256; proto++) { for (proto = 0; proto < 256; proto++) {
if (proto != 0) if (proto != 6)
continue; continue;
for (global_src_gr = de_ctx->flow_gh[f].src_gh[proto]->ipv4_head; global_src_gr != NULL; for (global_src_gr = de_ctx->flow_gh[f].src_gh[proto]->ipv4_head; global_src_gr != NULL;
@ -2898,6 +2924,7 @@ int SigAddressPrepareStage5(DetectEngineCtx *de_ctx) {
for ( ; dp != NULL; dp = dp->next) { for ( ; dp != NULL; dp = dp->next) {
printf(" 4 Dst port(range): "); DetectPortPrint(dp); printf(" 4 Dst port(range): "); DetectPortPrint(dp);
printf(" (sigs %" PRIu32 ", sgh %p, maxlen %" PRIu32 ")", dp->sh->sig_cnt, dp->sh, dp->sh->mpm_content_maxlen); printf(" (sigs %" PRIu32 ", sgh %p, maxlen %" PRIu32 ")", dp->sh->sig_cnt, dp->sh, dp->sh->mpm_content_maxlen);
printf(" mpm_ctx %p, mpm_stream_ctx %p", dp->sh->mpm_ctx, dp->sh->mpm_stream_ctx);
#ifdef PRINTSIGS #ifdef PRINTSIGS
printf(" - "); printf(" - ");
for (u = 0; u < dp->sh->sig_cnt; u++) { for (u = 0; u < dp->sh->sig_cnt; u++) {

Loading…
Cancel
Save