From: Philippe Antoine Date: Thu, 16 Jan 2025 07:40:46 +0000 (+0100) Subject: app-layer: make some arrays even more dynamic X-Git-Tag: suricata-8.0.0-beta1~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6750274d48d1de319ff29785bdb956604ebeaee7;p=thirdparty%2Fsuricata.git app-layer: make some arrays even more dynamic 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 --- diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index a64ffe96ba..767350628d 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -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); } diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 0237bbb7a0..6f36def8fe 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -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)