diff --git a/doc/userguide/configuration/multi-tenant.rst b/doc/userguide/configuration/multi-tenant.rst index e727facf5d9e..dcd7c29affca 100644 --- a/doc/userguide/configuration/multi-tenant.rst +++ b/doc/userguide/configuration/multi-tenant.rst @@ -21,6 +21,7 @@ Settings: * `selector`: direct (for unix socket pcap processing, see below), VLAN or device * `loaders`: number of `loader` threads, for parallel tenant loading at startup * `tenants`: list of tenants +* `config-path`: path from where the tenant yamls are loaded * id: tenant id (numeric values only) * yaml: separate yaml file with the tenant specific settings diff --git a/src/detect-engine-loader.c b/src/detect-engine-loader.c index b216112a3bd0..5a5e79c09934 100644 --- a/src/detect-engine-loader.c +++ b/src/detect-engine-loader.c @@ -401,7 +401,7 @@ static int num_loaders = NLOADERS; /** \param loader -1 for auto select * \retval loader_id or negative in case of error */ -int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx) +int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx, LoaderFreeFunc FreeFunc) { if (loader_id == -1) { loader_id = cur_loader; @@ -421,6 +421,7 @@ int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx) t->Func = Func; t->ctx = func_ctx; + t->FreeFunc = FreeFunc; SCMutexLock(&loader->m); TAILQ_INSERT_TAIL(&loader->task_list, t, next); @@ -596,7 +597,7 @@ static TmEcode DetectLoader(ThreadVars *th_v, void *thread_data) int r = task->Func(task->ctx, ftd->instance); loader->result |= r; TAILQ_REMOVE(&loader->task_list, task, next); - SCFree(task->ctx); + task->FreeFunc(task->ctx); SCFree(task); } diff --git a/src/detect-engine-loader.h b/src/detect-engine-loader.h index 6b8aa5cf9e05..7ffb8c8648a0 100644 --- a/src/detect-engine-loader.h +++ b/src/detect-engine-loader.h @@ -32,10 +32,12 @@ * \param loader_id id of the loader that executed the task */ typedef int (*LoaderFunc)(void *ctx, int loader_id); +typedef void (*LoaderFreeFunc)(void *ctx); typedef struct DetectLoaderTask_ { LoaderFunc Func; void *ctx; + LoaderFreeFunc FreeFunc; TAILQ_ENTRY(DetectLoaderTask_) next; } DetectLoaderTask; @@ -46,7 +48,7 @@ typedef struct DetectLoaderControl_ { TAILQ_HEAD(, DetectLoaderTask_) task_list; } DetectLoaderControl; -int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx); +int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx, LoaderFreeFunc FreeFunc); int DetectLoadersSync(void); void DetectLoadersInit(void); diff --git a/src/detect-engine.c b/src/detect-engine.c index 4e75fa13a8d7..251c586bc061 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -3918,9 +3918,18 @@ static int DetectEngineMultiTenantReloadTenant(uint32_t tenant_id, const char *f typedef struct TenantLoaderCtx_ { uint32_t tenant_id; int reload_cnt; /**< used by reload */ - const char *yaml; + char *yaml; /**< heap alloc'd copy of file path for the yaml */ } TenantLoaderCtx; +static void DetectLoaderFreeTenant(void *ctx) +{ + TenantLoaderCtx *t = (TenantLoaderCtx *)ctx; + if (t->yaml != NULL) { + SCFree(t->yaml); + } + SCFree(t); +} + static int DetectLoaderFuncLoadTenant(void *vctx, int loader_id) { TenantLoaderCtx *ctx = (TenantLoaderCtx *)vctx; @@ -3939,9 +3948,13 @@ static int DetectLoaderSetupLoadTenant(uint32_t tenant_id, const char *yaml) return -ENOMEM; t->tenant_id = tenant_id; - t->yaml = yaml; + t->yaml = SCStrdup(yaml); + if (t->yaml == NULL) { + SCFree(t); + return -ENOMEM; + } - return DetectLoaderQueueTask(-1, DetectLoaderFuncLoadTenant, t); + return DetectLoaderQueueTask(-1, DetectLoaderFuncLoadTenant, t, DetectLoaderFreeTenant); } static int DetectLoaderFuncReloadTenant(void *vctx, int loader_id) @@ -3969,12 +3982,17 @@ static int DetectLoaderSetupReloadTenant(uint32_t tenant_id, const char *yaml, i return -ENOMEM; t->tenant_id = tenant_id; - t->yaml = yaml; + t->yaml = SCStrdup(yaml); + if (t->yaml == NULL) { + SCFree(t); + return -ENOMEM; + } t->reload_cnt = reload_cnt; SCLogDebug("loader_id %d", loader_id); - return DetectLoaderQueueTask(loader_id, DetectLoaderFuncReloadTenant, t); + return DetectLoaderQueueTask( + loader_id, DetectLoaderFuncReloadTenant, t, DetectLoaderFreeTenant); } /** \brief Load a tenant and wait for loading to complete @@ -4223,6 +4241,13 @@ int DetectEngineMultiTenantSetup(const bool unix_socket) ConfNode *tenant_node = NULL; if (tenants_root_node != NULL) { + const char *path = NULL; + ConfNode *path_node = ConfGetNode("multi-detect.config-path"); + if (path_node) { + path = path_node->val; + SCLogConfig("tenants config path: %s", path); + } + TAILQ_FOREACH(tenant_node, &tenants_root_node->head, next) { ConfNode *id_node = ConfNodeLookupChild(tenant_node, "id"); if (id_node == NULL) { @@ -4243,16 +4268,24 @@ int DetectEngineMultiTenantSetup(const bool unix_socket) } SCLogDebug("tenant id: %u, %s", tenant_id, yaml_node->val); + char yaml_path[PATH_MAX] = ""; + if (path) { + PathMerge(yaml_path, PATH_MAX, path, yaml_node->val); + } else { + strlcpy(yaml_path, yaml_node->val, sizeof(yaml_path)); + } + SCLogDebug("tenant path: %s", yaml_path); + /* setup the yaml in this loop so that it's not done by the loader * threads. ConfYamlLoadFileWithPrefix is not thread safe. */ char prefix[64]; snprintf(prefix, sizeof(prefix), "multi-detect.%u", tenant_id); - if (ConfYamlLoadFileWithPrefix(yaml_node->val, prefix) != 0) { - SCLogError("failed to load yaml %s", yaml_node->val); + if (ConfYamlLoadFileWithPrefix(yaml_path, prefix) != 0) { + SCLogError("failed to load yaml %s", yaml_path); goto bad_tenant; } - int r = DetectLoaderSetupLoadTenant(tenant_id, yaml_node->val); + int r = DetectLoaderSetupLoadTenant(tenant_id, yaml_path); if (r < 0) { /* error logged already */ goto bad_tenant;