]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app-layer: make some arrays even more dynamic
authorPhilippe Antoine <pantoine@oisf.net>
Thu, 16 Jan 2025 07:40:46 +0000 (08:40 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 7 Apr 2025 04:57:45 +0000 (06:57 +0200)
Ticket: 5053

Do not asume that we know the number of alprotos at the end
of AppLayerNamesSetup, but make arrays allocated by later
AppLayerProtoDetectSetup dynamic so that it can be reallocated
from AppLayerParserRegisterProtocolParsers

This helps have a single entry point for a protocol like SNMP

src/app-layer-detect-proto.c
src/app-layer-parser.c

index a64ffe96ba014a7c8fbf9169a765eb01fbcc0ae2..767350628dbc06d02012c2ac92f3ac859bce4ef0 100644 (file)
@@ -157,12 +157,14 @@ typedef struct AppLayerProtoDetectCtx_ {
      * ipproto. It should be allocated to contain ALPROTO_MAX
      * protocols. */
     const char **alproto_names;
+    size_t alproto_names_len;
 
     /* Protocol expectations, like ftp-data on tcp.
      * It should be allocated to contain ALPROTO_MAX
      * app-layer protocols. For each protocol, an iptype
      * is referenced (or 0 if there is no expectation). */
     uint8_t *expectation_proto;
+    size_t expectation_proto_len;
 } AppLayerProtoDetectCtx;
 
 typedef struct AppLayerProtoDetectAliases_ {
@@ -1704,11 +1706,13 @@ int AppLayerProtoDetectSetup(void)
     if (unlikely(alpd_ctx.alproto_names == NULL)) {
         FatalError("Unable to alloc alproto_names.");
     }
+    alpd_ctx.alproto_names_len = g_alproto_max;
     // to realloc when dynamic protos are added
     alpd_ctx.expectation_proto = SCCalloc(g_alproto_max, sizeof(uint8_t));
     if (unlikely(alpd_ctx.expectation_proto == NULL)) {
         FatalError("Unable to alloc expectation_proto.");
     }
+    alpd_ctx.expectation_proto_len = g_alproto_max;
     AppLayerExpectationSetup();
 
     SCReturnInt(0);
@@ -1742,8 +1746,10 @@ int AppLayerProtoDetectDeSetup(void)
 
     SCFree(alpd_ctx.alproto_names);
     alpd_ctx.alproto_names = NULL;
+    alpd_ctx.alproto_names_len = 0;
     SCFree(alpd_ctx.expectation_proto);
     alpd_ctx.expectation_proto = NULL;
+    alpd_ctx.expectation_proto_len = 0;
 
     SpmDestroyGlobalThreadCtx(alpd_ctx.spm_global_thread_ctx);
 
@@ -1758,7 +1764,16 @@ void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_n
 {
     SCEnter();
 
-    // should have just been realloced when dynamic protos is added
+    if (alpd_ctx.alproto_names_len <= alproto && alproto < g_alproto_max) {
+        void *tmp = SCRealloc(alpd_ctx.alproto_names, sizeof(char *) * g_alproto_max);
+        if (unlikely(tmp == NULL)) {
+            FatalError("Unable to realloc alproto_names.");
+        }
+        alpd_ctx.alproto_names = tmp;
+        memset(&alpd_ctx.alproto_names[alpd_ctx.alproto_names_len], 0,
+                sizeof(char *) * (g_alproto_max - alpd_ctx.alproto_names_len));
+        alpd_ctx.alproto_names_len = g_alproto_max;
+    }
     if (alpd_ctx.alproto_names[alproto] == NULL)
         alpd_ctx.alproto_names[alproto] = alproto_name;
 
@@ -2111,6 +2126,9 @@ void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
                                              uint8_t *ipprotos)
 {
+    if (alproto >= alpd_ctx.expectation_proto_len) {
+        return;
+    }
     if (alpd_ctx.expectation_proto[alproto] == IPPROTO_TCP) {
         ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
     }
index 0237bbb7a049a411cdfe6ce3577d58ffa4f07f3c..6f36def8feeb620ffbd0d203779389cdbb058bcf 100644 (file)
@@ -124,6 +124,7 @@ typedef struct AppLayerParserProtoCtx_
 
 typedef struct AppLayerParserCtx_ {
     AppLayerParserProtoCtx (*ctxs)[FLOW_PROTO_MAX];
+    size_t ctxs_len;
 } AppLayerParserCtx;
 
 struct AppLayerParserState_ {
@@ -259,6 +260,7 @@ int AppLayerParserSetup(void)
     if (unlikely(alp_ctx.ctxs == NULL)) {
         FatalError("Unable to alloc alp_ctx.ctxs.");
     }
+    alp_ctx.ctxs_len = g_alproto_max;
     SCReturnInt(0);
 }
 
@@ -431,6 +433,20 @@ void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
 {
     SCEnter();
 
+    if (alp_ctx.ctxs_len <= alproto && alproto < g_alproto_max) {
+        // Realloc now as AppLayerParserRegisterStateFuncs is called first
+        void *tmp = SCRealloc(
+                alp_ctx.ctxs, sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX]) * g_alproto_max);
+        if (unlikely(tmp == NULL)) {
+            FatalError("Unable to realloc alp_ctx.ctxs.");
+        }
+        alp_ctx.ctxs = tmp;
+        memset(&alp_ctx.ctxs[alp_ctx.ctxs_len], 0,
+                sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX]) *
+                        (g_alproto_max - alp_ctx.ctxs_len));
+        alp_ctx.ctxs_len = g_alproto_max;
+    }
+
     alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateAlloc = StateAlloc;
     alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateFree = StateFree;
 
@@ -1680,7 +1696,6 @@ bad:
 }
 #undef BOTH_SET
 #undef BOTH_SET_OR_BOTH_UNSET
-#undef THREE_SET_OR_THREE_UNSET
 #undef THREE_SET
 
 static void ValidateParser(AppProto alproto)