detect/content: refactor limit propagation

pull/8624/head
Victor Julien 3 years ago
parent 8831ae9be7
commit 33bee20d3d

@ -501,16 +501,12 @@ bool DetectContentPMATCHValidateCallback(const Signature *s)
* cannot set a depth, but we can set an offset of 'offset:1;'. This will * cannot set a depth, but we can set an offset of 'offset:1;'. This will
* make the mpm a bit more precise. * make the mpm a bit more precise.
*/ */
void DetectContentPropagateLimits(Signature *s) static void PropagateLimits(Signature *s, SigMatch *sm_head)
{ {
#define VALIDATE(e) \ #define VALIDATE(e) \
if (!(e)) { \ if (!(e)) { \
return; \ return; \
} }
BUG_ON(s == NULL || s->init_data == NULL);
uint32_t list = 0;
for (list = 0; list < s->init_data->smlists_array_size; list++) {
uint16_t offset = 0; uint16_t offset = 0;
uint16_t offset_plus_pat = 0; uint16_t offset_plus_pat = 0;
uint16_t depth = 0; uint16_t depth = 0;
@ -520,12 +516,12 @@ void DetectContentPropagateLimits(Signature *s)
bool has_ends_with = false; bool has_ends_with = false;
uint16_t ends_with_depth = 0; uint16_t ends_with_depth = 0;
SigMatch *sm = s->init_data->smlists[list]; for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) {
for ( ; sm != NULL; sm = sm->next) {
switch (sm->type) { switch (sm->type) {
case DETECT_CONTENT: { case DETECT_CONTENT: {
DetectContentData *cd = (DetectContentData *)sm->ctx; DetectContentData *cd = (DetectContentData *)sm->ctx;
if ((cd->flags & (DETECT_CONTENT_DEPTH|DETECT_CONTENT_OFFSET|DETECT_CONTENT_WITHIN|DETECT_CONTENT_DISTANCE)) == 0) { if ((cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) == 0) {
offset = depth = 0; offset = depth = 0;
offset_plus_pat = cd->content_len; offset_plus_pat = cd->content_len;
SCLogDebug("reset"); SCLogDebug("reset");
@ -545,8 +541,10 @@ void DetectContentPropagateLimits(Signature *s)
has_active_depth_chain = true; has_active_depth_chain = true;
} }
SCLogDebug("sm %p depth %u offset %u distance %d within %d", sm, cd->depth, cd->offset, cd->distance, cd->within); SCLogDebug("sm %p depth %u offset %u distance %d within %d", sm, cd->depth,
SCLogDebug("stored: offset %u depth %u offset_plus_pat %u", offset, depth, offset_plus_pat); cd->offset, cd->distance, cd->within);
SCLogDebug("stored: offset %u depth %u offset_plus_pat %u", offset, depth,
offset_plus_pat);
if ((cd->flags & (DETECT_DEPTH | DETECT_CONTENT_WITHIN)) == 0) { if ((cd->flags & (DETECT_DEPTH | DETECT_CONTENT_WITHIN)) == 0) {
if (depth) if (depth)
@ -562,22 +560,20 @@ void DetectContentPropagateLimits(Signature *s)
SCLogDebug("stored: offset %u depth %u offset_plus_pat %u " SCLogDebug("stored: offset %u depth %u offset_plus_pat %u "
"has_active_depth_chain %s", "has_active_depth_chain %s",
offset, depth, offset_plus_pat, offset, depth, offset_plus_pat, has_active_depth_chain ? "true" : "false");
has_active_depth_chain ? "true" : "false");
if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX); VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance); offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
SCLogDebug("updated content to have offset %u", cd->offset); SCLogDebug("updated content to have offset %u", cd->offset);
} }
if (has_active_depth_chain) { if (has_active_depth_chain) {
if (offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && if (offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && cd->within >= 0) {
cd->within >= 0) {
if (depth && depth > offset_plus_pat) { if (depth && depth > offset_plus_pat) {
int32_t dist = 0; int32_t dist = 0;
if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance > 0) { if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance > 0) {
dist = cd->distance; dist = cd->distance;
SCLogDebug("distance to add: %u. depth + dist %u", dist, SCLogDebug(
depth + dist); "distance to add: %u. depth + dist %u", dist, depth + dist);
} }
SCLogDebug("depth %u + cd->within %u", depth, cd->within); SCLogDebug("depth %u + cd->within %u", depth, cd->within);
VALIDATE(depth + cd->within + dist >= 0 && VALIDATE(depth + cd->within + dist >= 0 &&
@ -585,8 +581,7 @@ void DetectContentPropagateLimits(Signature *s)
depth = cd->depth = (uint16_t)(depth + cd->within + dist); depth = cd->depth = (uint16_t)(depth + cd->within + dist);
} else { } else {
SCLogDebug("offset %u + cd->within %u", offset, cd->within); SCLogDebug("offset %u + cd->within %u", offset, cd->within);
VALIDATE(depth + cd->within >= 0 && VALIDATE(depth + cd->within >= 0 && depth + cd->within <= UINT16_MAX);
depth + cd->within <= UINT16_MAX);
depth = cd->depth = (uint16_t)(offset + cd->within); depth = cd->depth = (uint16_t)(offset + cd->within);
} }
SCLogDebug("updated content to have depth %u", cd->depth); SCLogDebug("updated content to have depth %u", cd->depth);
@ -616,15 +611,19 @@ void DetectContentPropagateLimits(Signature *s)
} }
} }
} }
if (cd->offset == 0) {// && offset != 0) { if (cd->offset == 0) { // && offset != 0) {
if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) { if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
cd->offset = offset_plus_pat; cd->offset = offset_plus_pat;
SCLogDebug("update content to have offset %u", cd->offset); SCLogDebug("update content to have offset %u", cd->offset);
} }
} }
if ((cd->flags & (DETECT_CONTENT_DEPTH|DETECT_CONTENT_OFFSET|DETECT_CONTENT_WITHIN|DETECT_CONTENT_DISTANCE)) == (DETECT_CONTENT_DISTANCE|DETECT_CONTENT_WITHIN) || if ((cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
(cd->flags & (DETECT_CONTENT_DEPTH|DETECT_CONTENT_OFFSET|DETECT_CONTENT_WITHIN|DETECT_CONTENT_DISTANCE)) == (DETECT_CONTENT_DISTANCE)) { DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) ==
(DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN) ||
(cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) ==
(DETECT_CONTENT_DISTANCE)) {
if (cd->distance >= 0) { if (cd->distance >= 0) {
// only distance // only distance
VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX); VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
@ -649,7 +648,7 @@ void DetectContentPropagateLimits(Signature *s)
ends_with_depth = MIN(ends_with_depth, depth); ends_with_depth = MIN(ends_with_depth, depth);
} }
} }
if ((cd->flags & (DETECT_CONTENT_WITHIN|DETECT_CONTENT_DEPTH)) == 0) { if ((cd->flags & (DETECT_CONTENT_WITHIN | DETECT_CONTENT_DEPTH)) == 0) {
has_active_depth_chain = false; has_active_depth_chain = false;
depth = 0; depth = 0;
} }
@ -667,18 +666,16 @@ void DetectContentPropagateLimits(Signature *s)
has_active_depth_chain = false; has_active_depth_chain = false;
break; break;
} }
default: { default:
SCLogDebug("keyword not supported, reset offset_plus_pat & offset"); SCLogDebug("keyword not supported, reset offset_plus_pat & offset");
offset_plus_pat = offset = depth = 0; offset_plus_pat = offset = depth = 0;
has_active_depth_chain = false; has_active_depth_chain = false;
break; break;
} }
} }
}
/* apply anchored 'ends with' as depth to all patterns */ /* apply anchored 'ends with' as depth to all patterns */
if (has_depth && has_ends_with) { if (has_depth && has_ends_with) {
sm = s->init_data->smlists[list]; for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) {
for ( ; sm != NULL; sm = sm->next) {
switch (sm->type) { switch (sm->type) {
case DETECT_CONTENT: { case DETECT_CONTENT: {
DetectContentData *cd = (DetectContentData *)sm->ctx; DetectContentData *cd = (DetectContentData *)sm->ctx;
@ -692,10 +689,17 @@ void DetectContentPropagateLimits(Signature *s)
} }
} }
} }
}
#undef VALIDATE #undef VALIDATE
} }
void DetectContentPropagateLimits(Signature *s)
{
for (uint32_t list = 0; list < s->init_data->smlists_array_size; list++) {
SigMatch *sm = s->init_data->smlists[list];
PropagateLimits(s, sm);
}
}
static inline bool NeedsAsHex(uint8_t c) static inline bool NeedsAsHex(uint8_t c)
{ {
if (!isprint(c)) if (!isprint(c))

Loading…
Cancel
Save