From: Shivani Bhardwaj Date: Wed, 21 Feb 2024 06:42:30 +0000 (+0530) Subject: detect/port: merge port ranges for same signatures X-Git-Tag: suricata-7.0.6~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83eb0a01004183bd7e76148e5e3f1701e4eaff69;p=thirdparty%2Fsuricata.git detect/port: merge port ranges for same signatures To avoid getting multiple entries in the final port list and to also make the next step more efficient by reducing the size of the items to traverse over. Ticket 6792 Bug 6414 (cherry picked from commit 643ae85b5faa91958fe9ee79987fa20f06849059) --- diff --git a/src/detect-engine-build.c b/src/detect-engine-build.c index e8ca516ec2..1fc5190dc8 100644 --- a/src/detect-engine-build.c +++ b/src/detect-engine-build.c @@ -1190,9 +1190,7 @@ static inline uint32_t SetUniquePortPoints( } /* Treat right boundary as single point to avoid creating unneeded - * ranges later on - * TODO merge the extra entry created in the rulegroup - * for such points in *CreateGroupedPortList* fn */ + * ranges later on */ if (unique_list[p->port2] == 0) { size_list++; } diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c index c75a5d0ed8..c05b6c3daa 100644 --- a/src/detect-engine-siggroup.c +++ b/src/detect-engine-siggroup.c @@ -438,6 +438,28 @@ void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx) return; } +/** + * \brief Finds if two Signature Group Heads are the same. + * + * \param sgha First SGH to be compared + * \param sghb Secornd SGH to be compared + * + * \return true if they're a match, false otherwise + */ +bool SigGroupHeadEqual(const SigGroupHead *sgha, const SigGroupHead *sghb) +{ + if (sgha == NULL || sghb == NULL) + return false; + + if (sgha->init->sig_size != sghb->init->sig_size) + return false; + + if (SCMemcmp(sgha->init->sig_array, sghb->init->sig_array, sgha->init->sig_size) != 0) + return false; + + return true; +} + void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh, uint8_t ipproto, int dir) { diff --git a/src/detect-engine-siggroup.h b/src/detect-engine-siggroup.h index d4c9e93c67..456979aed2 100644 --- a/src/detect-engine-siggroup.h +++ b/src/detect-engine-siggroup.h @@ -42,6 +42,7 @@ int SigGroupHeadHashRemove(DetectEngineCtx *, SigGroupHead *); void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid); void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx); +bool SigGroupHeadEqual(const SigGroupHead *, const SigGroupHead *); void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh, uint8_t ipproto, int dir); int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t max_idx); diff --git a/src/util-port-interval-tree.c b/src/util-port-interval-tree.c index 53f8ef5508..d4c770585a 100644 --- a/src/util-port-interval-tree.c +++ b/src/util-port-interval-tree.c @@ -127,6 +127,35 @@ int SCPortIntervalInsert(DetectEngineCtx *de_ctx, SCPortIntervalTree *it, const return SC_OK; } +/** + * \brief Function to remove multiple sig entries corresponding to the same + * signature group and merge them into one. + * + * \param de_ctx Detection Engine Context + * \param list Pointer to the list to be modified + */ +static void SCPortIntervalSanitizeList(DetectEngineCtx *de_ctx, DetectPort **list) +{ + DetectPort *cur = (*list)->last; + if (cur == NULL) + return; + + DetectPort *prev = (*list)->last->prev; + if (prev == NULL) + return; + + /* rulegroup IDs are assigned much later so, compare SGHs */ + if (SigGroupHeadEqual(prev->sh, cur->sh)) { + if (prev->port2 == (cur->port - 1)) { + /* Merge the port objects */ + prev->port2 = cur->port2; + (*list)->last = prev; + (*list)->last->next = NULL; + DetectPortFree(de_ctx, cur); + } + } +} + /** * \brief Function to check if a port range overlaps with a given set of ports * @@ -226,6 +255,7 @@ static void SCPortIntervalFindOverlaps(DetectEngineCtx *de_ctx, const uint16_t p ((*list)->last->port2 != new_port->port)) { DEBUG_VALIDATE_BUG_ON(new_port->port < (*list)->last->port); (*list)->last->next = new_port; + new_port->prev = (*list)->last; (*list)->last = new_port; } else { SCLogDebug("Port already exists in the list"); @@ -260,6 +290,8 @@ static void SCPortIntervalFindOverlaps(DetectEngineCtx *de_ctx, const uint16_t p BUG_ON(popped == NULL); current = IRB_RIGHT(popped, irb); } + if (new_port != NULL) + SCPortIntervalSanitizeList(de_ctx, list); if (stack != NULL) SCFree(stack); return;