package/finit: backport fixes to critical issues in v4.15

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2026-01-22 22:44:12 +01:00
parent b88dc40fa9
commit c7b409304f
2 changed files with 134 additions and 0 deletions
@@ -0,0 +1,48 @@
From abaad560f0bf1f7de832a55222e20e2a9a61986f Mon Sep 17 00:00:00 2001
From: Aaron Andersen <aaron@fosslib.net>
Date: Sat, 10 Jan 2026 18:57:52 -0500
Subject: [PATCH 1/2] Set USER and LOGNAME environment variables when dropping
privileges
Organization: Wires
When a service is configured to run as a non-root user (@user), finit
correctly drops privileges via setuid() and sets HOME and PATH, but
does not set the USER and LOGNAME environment variables. They remain
set to "root" from boot time.
This causes problems for software that determines its identity from
the environment rather than getuid(). For example, rootless Podman
checks os.Getenv("USER") first when looking up subordinate UID/GID
ranges in /etc/subuid and /etc/subgid.
With USER=root but UID=1000, Podman looks up root's subuid entry
instead of the actual user's, causing applications like newuidmap
to fail. Setting USER and LOGNAME to match the actual user identity
follows POSIX conventions and matches the behavior of su, sudo, and
login.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
src/service.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/service.c b/src/service.c
index 2c8fb6e..d45db40 100644
--- a/src/service.c
+++ b/src/service.c
@@ -627,8 +627,11 @@ static pid_t service_fork(svc_t *svc)
set_uid(uid, svc);
/* Set default path for regular users */
- if (uid > 0)
+ if (uid > 0) {
setenv("PATH", _PATH_DEFPATH, 1);
+ setenv("USER", svc->username, 1);
+ setenv("LOGNAME", svc->username, 1);
+ }
if (home) {
setenv("HOME", home, 1);
if (chdir(home)) {
--
2.43.0
@@ -0,0 +1,86 @@
From 34bf9a77765db4d963fc66dde29b415ecc8ab611 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 12 Jan 2026 19:31:39 +0100
Subject: [PATCH 2/2] Fix #467: TTY services stuck in restart state after
non-zero exit
Organization: Wires
When a TTY exited with non-zero code (e.g., user with shell=/sbin/false),
it would enter restart state but never recover, requiring manual restart.
The throttling logic from commit f0032ab had two issues:
1. Duplicate exit code check in service_retry() created infinite timer loop
2. TTYs lacked default restart_tmo, causing timer to never start
Fix by removing duplicate check and ensuring TTYs get a 2-second default
restart_tmo for proper throttling.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
src/service.c | 31 ++++++++++++++-----------------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/src/service.c b/src/service.c
index d45db40..ff8e180 100644
--- a/src/service.c
+++ b/src/service.c
@@ -2194,15 +2194,20 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
/* only set forking based on pidfile if user supplied pid: option */
if (pid && svc->pidfile[0] == '!')
svc->forking = 1;
+ }
- if (svc->restart_tmo == 0) {
- if (svc_is_forking(svc))
- svc->restart_tmo = 2000;
- else
- svc->restart_tmo = 1;
- }
+ /* Set default restart_tmo for services and TTYs that can restart */
+ if (svc_is_daemon(svc) && svc->restart_tmo == 0) {
+ if (svc_is_forking(svc))
+ svc->restart_tmo = 2000;
+ else
+ svc->restart_tmo = 1;
}
+ /* TTYs need a longer default to throttle errors (e.g., missing device) */
+ if (svc_is_tty(svc) && svc->restart_tmo == 0)
+ svc->restart_tmo = 2000;
+
/* Set configured limits */
memcpy(svc->rlimit, rlimit, sizeof(svc->rlimit));
@@ -2631,7 +2636,6 @@ static void service_cleanup_script(svc_t *svc)
static void service_retry(svc_t *svc)
{
char *restart_cnt = (char *)&svc->restart_cnt;
- int rc = WEXITSTATUS(svc->status);
int timeout;
service_timeout_cancel(svc);
@@ -2641,17 +2645,10 @@ static void service_retry(svc_t *svc)
if (svc->respawn) {
/*
- * Non-zero exit indicates an error that may not be resolved
- * by immediate retry. Add delay to prevent busy-loop and to
- * rate-limit retries, e.g. when TTY device doesn't exist.
+ * Respawn services (TTYs) that exited with non-zero status
+ * have already been delayed in the SVC_RUNNING_STATE handler.
+ * Just restart now.
*/
- if (WIFEXITED(svc->status) && rc != 0) {
- dbg("%s exited with error %d, delaying respawn ...",
- svc_ident(svc, NULL, 0), rc);
- service_timeout_after(svc, svc->restart_tmo, service_retry);
- return;
- }
-
dbg("%s crashed/exited, respawning ...", svc_ident(svc, NULL, 0));
svc_unblock(svc);
service_step(svc);
--
2.43.0