From d3c6351ed86adfb12abfce4b0b1bb2fff117483d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Thu, 5 May 2022 19:06:05 +0200 Subject: [PATCH] Fix nasty service matcher bug In some conditions, typically when the same command is used for multiple services, e.g. the modules-load plugin, the svc_find() function returned an existing "similar" entry instead of NULL, causing loss of config. When creating, and searching for, a run/task/service we must follow the new name:id paradigm to the letter. Always create based on name:id and always search for matching name:id. The name may be derived from the command, but they cannot be used interchangably. Signed-off-by: Joachim Wiberg --- src/api.c | 2 +- src/finit.c | 2 +- src/service.c | 4 ++-- src/svc.c | 41 ++++++++++------------------------------- src/svc.h | 5 ++--- 5 files changed, 16 insertions(+), 38 deletions(-) diff --git a/src/api.c b/src/api.c index 985a9dce..a4a3e09c 100644 --- a/src/api.c +++ b/src/api.c @@ -198,7 +198,7 @@ static svc_t *do_find(char *buf, size_t len) if (!id) return svc_named_iterator(&iter, 1, input); - return svc_find_by_nameid(input, id); + return svc_find(input, id); } static svc_t *do_find_byc(char *buf, size_t len) diff --git a/src/finit.c b/src/finit.c index b30e252c..4e3142c2 100644 --- a/src/finit.c +++ b/src/finit.c @@ -794,7 +794,7 @@ int main(int argc, char *argv[]) */ if (whichp(FINIT_LIBPATH_ "/watchdogd") && fexist(WDT_DEVNODE)) { service_register(SVC_TYPE_SERVICE, "[123456789] cgroup.init name:watchdog :finit " FINIT_LIBPATH_ "/watchdogd -- Finit watchdog daemon", global_rlimit, NULL); - wdog = svc_find_by_nameid("watchdog", "finit"); + wdog = svc_find("watchdog", "finit"); } /* diff --git a/src/service.c b/src/service.c index a3bda3b1..e3aca870 100644 --- a/src/service.c +++ b/src/service.c @@ -1352,11 +1352,11 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) next: svc = svc_find_by_tty(dev); } else - svc = svc_find(cmd, id); + svc = svc_find(name, id); if (!svc) { _d("Creating new svc for %s name %s id %s type %d", cmd, name, id, type); - svc = svc_new(cmd, id, type); + svc = svc_new(cmd, name, id, type); if (!svc) { _e("Out of memory, cannot register service %s", cmd); return errno = ENOMEM; diff --git a/src/svc.c b/src/svc.c index c946affa..1395edf5 100644 --- a/src/svc.c +++ b/src/svc.c @@ -107,16 +107,17 @@ static void svc_gc(void *arg) /** * svc_new - Create a new service * @cmd: External program to call + * @name: Default or custom svc name * @id: Instance id * @type: Service type, one of service, task, run * * Returns: * A pointer to a new &svc_t object, or %NULL if out of empty slots. */ -svc_t *svc_new(char *cmd, char *id, int type) +svc_t *svc_new(char *cmd, char *name, char *id, int type) { - int job = -1; svc_t *svc, *iter = NULL; + int job = -1; /* Find first job n:o if registering multiple instances */ for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) { @@ -134,6 +135,8 @@ svc_t *svc_new(char *cmd, char *id, int type) svc->type = type; svc->job = job; + if (name) + strlcpy(svc->name, name, sizeof(svc->name)); if (id && id[0]) strlcpy(svc->id, id, sizeof(svc->id)); if (cmd) @@ -348,13 +351,13 @@ svc_t *svc_stop_completed(void) /** * svc_find - Find a service object by its full path name - * @cmd: Full path name, e.g., /sbin/syslogd - * @id: Optional instance id + * @name: Full path name, e.g., /sbin/syslogd + * @id: Optional instance id * * Returns: * A pointer to an &svc_t object, or %NULL if not found. */ -svc_t *svc_find(char *cmd, char *id) +svc_t *svc_find(char *name, char *id) { svc_t *svc, *iter = NULL; @@ -362,7 +365,7 @@ svc_t *svc_find(char *cmd, char *id) id = ""; for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) { - if (!strcmp(svc->cmd, cmd) && !strcmp(svc->id, id)) + if (!strcmp(svc->name, name) && !strcmp(svc->id, id)) return svc; } @@ -411,30 +414,6 @@ svc_t *svc_find_by_jobid(int job, char *id) return NULL; } -/** - * svc_find_by_nameid - Find an service object by its basename:ID - * @name: Process name to match - * @id: Optional instance id - * - * Returns: - * A pointer to an &svc_t object, or %NULL if not found. - */ -svc_t *svc_find_by_nameid(char *name, char *id) -{ - svc_t *svc, *iter = NULL; - - if (!id) - id = ""; - - for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) { - if (!strcmp(svc->id, id) && !strcmp(name, svc->name)) - return svc; - } - - return NULL; -} - - svc_t *svc_find_by_tty(char *dev) { svc_t *svc, *iter = NULL; @@ -720,7 +699,7 @@ int svc_parse_jobstr(char *str, size_t len, void *user_data, int (*found)(svc_t *ptr++ = 0; id = ptr; - svc = svc_find_by_nameid(token, id); + svc = svc_find(token, id); if (!svc && not_found) result += not_found(token, id, user_data); else if (found) diff --git a/src/svc.h b/src/svc.h index 71536d03..4c0ceeca 100644 --- a/src/svc.h +++ b/src/svc.h @@ -193,14 +193,13 @@ typedef struct svc { struct timespec gc; } svc_t; -svc_t *svc_new (char *cmd, char *id, int type); +svc_t *svc_new (char *cmd, char *name, char *id, int type); int svc_del (svc_t *svc); void svc_validate (svc_t *svc); -svc_t *svc_find (char *cmd, char *id); +svc_t *svc_find (char *name, char *id); svc_t *svc_find_by_pid (pid_t pid); svc_t *svc_find_by_jobid (int job, char *id); -svc_t *svc_find_by_nameid (char *name, char *id); svc_t *svc_find_by_tty (char *dev); svc_t *svc_find_by_pidfile (char *fn);