`daemon: failed to set user environment` when using daemon(8) with -u and rc script with a user set

The forgejo-runner port is broken since a recent update. I am waiting for a bugzilla account to submit a bug report and a patch. However, before that I need to understand why this is happening:
  • Starting act_runner directly as root (i.e., without daemon(8)) works correctly. -> no surprises here
  • Running daemon(8) inside act_runner_prestart also (as done up to version 9.1.0_4 of the port) also works (act_runner would start but in some situations would terminate and remain stopped — this is the original reason for the patch linked above).
Since the patch, the daemon is started with $command outside of act_runner_prestart (I omitted some parts of the patch to focus on the relevant bits):

Code:
-command="${procname} ${act_runner_flags}"
+command="/usr/sbin/daemon"
 
-start_cmd="${name}_start"

-act_runner_start() {

+act_runner_prestart() {
   #  ensure the log directories are owned by the unprivileged user
   for d in "${act_runner_log_dir}"; do
     if [ ! -e "$d" ]; then
@@ -42,11 +44,12 @@
       chown "${act_runner_user}" "$d"
     fi
   done
-  /usr/sbin/daemon -S -l "${act_runner_facility}" -s "${act_runner_priority}" \
-    -T "${name}" \
-    -u "${act_runner_user}" -p "${pidfile}" \
-    -o "${act_runner_log_file}" \
-    $command
}
+
+command_args=" -r -S -l ${act_runner_facility} -s ${act_runner_priority} \
+    -T ${name} \
+    -u ${act_runner_user} -P ${pidfile} \
+    -o ${act_runner_log_file} \
+    ${exec_path} ${act_runner_args}"

Running the script like this results in "daemon: failed to set user environment" in the logs.

To fix this, the only change needed was to remove -u ${act_runner_user} from the daemon incantation — why, and is it even fixing the "right thing"?

Some more context:
  • the act_runner user exists and its home is owned by act_runner
Code:
pw user show act_runner
act_runner:*:806:806::0:0:Act Runner User:/var/db/act_runner:/usr/sbin/nologin
 
After exploring a bit further, I may have answered my question here.

My understanding is that daemon: failed to set user environment happens because setting %{name}_user to an unprivileged user and the -u flag for daemon(1) results in a scenario where daemon(1) lacks permissions to set the HOME env var (among others). Removing the flag means both daemon(1) and the runner run as the unprivileged user; however, the env vars are not updated, so we get a new error when the runner gets a job: it tries to create a .cache directory under / (root), because HOME was never updated by rc.

This could be fixed by adding HOME to %{name}_env but that means also updating PATH and others.

The solution I'm falling back to is to remove %{name}_user and set the -u flag for daemon(1). Thus, daemon(1) is launched as root, but the child process runs as the unprivileged user with the correct HOME env var set.

This feels “correct”, but if it somehow is a bad security practice, please let me know.
 
Back
Top