From d0176612c9ccb1ee30a35defae25aeec8ae5b586 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 31 Dec 2025 22:51:55 +0100 Subject: [PATCH] Default to user/group root for services and check for errors This is a refactor of getuser() and getgroup() so that they always return a valid user, and group, for all normal use-cases. When an error occurs we now handle it properly in service_fork() so as to not attempt to start services with an invalid user/group setting as root. Signed-off-by: Joachim Wiberg --- src/service.c | 12 ++++++++++++ src/util.c | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/service.c b/src/service.c index a1868dc5..4f1b2955 100644 --- a/src/service.c +++ b/src/service.c @@ -556,6 +556,18 @@ static pid_t service_fork(svc_t *svc) #else int uid = getuser(svc->username, &home); int gid = getgroup(svc->group); + + /* Check for invalid user/group - fail rather than silent fallback */ + if (uid < 0) { + err(1, "%s: user '%s' not found, cannot start service", + svc_ident(svc, NULL, 0), svc->username); + return -1; + } + if (gid < 0) { + err(1, "%s: group '%s' not found, cannot start service", + svc_ident(svc, NULL, 0), svc->group); + return -1; + } #endif sched_yield(); diff --git a/src/util.c b/src/util.c index 1188f021..3d8a0b22 100644 --- a/src/util.c +++ b/src/util.c @@ -180,16 +180,34 @@ char *str(char *fmt, ...) return buf; } +/* + * Return UID for the given user, with fallback to 'root' if user is unset. + * Fails with -1 only if user (incl. fallback) does not exist. + */ int getuser(const char *username, char **home) { #ifdef ENABLE_STATIC + if (!username || !username[0]) + username = "root"; + if (home) *home = "/"; /* XXX: Fixme */ return fgetint("/etc/passwd", "x:\n", username); #else - struct passwd *usr; + const struct passwd *usr; - if (!username || (usr = getpwnam(username)) == NULL) + if (!username || !username[0]) { + usr = getpwuid(0); + if (!usr) + return -1; + + if (home) + *home = usr->pw_dir; + return usr->pw_uid; + } + + usr = getpwnam(username); + if (!usr) return -1; if (home) @@ -198,14 +216,30 @@ int getuser(const char *username, char **home) #endif } +/* + * Return GID for the given group, with fallback to 'root' if group is unset. + * Fails with -1 only if user (incl. fallback) does not exist. + */ int getgroup(const char *group) { #ifdef ENABLE_STATIC + if (!group || !group[0]) + group = "root"; + return fgetint("/etc/group", "x:\n", group); #else - struct group *grp; + const struct group *grp; - if ((grp = getgrnam(group)) == NULL) + if (!group || !group[0]) { + grp = getgrgid(0); + if (!grp) + return -1; + + return grp->gr_gid; + } + + grp = getgrnam(group); + if (!grp) return -1; return grp->gr_gid;