conf: adopt the systemd semantics for per-service directories

Aaron Andersen points out in the #492 discussion that the *Directory
settings carry more contract than create-and-chown: per-directory
modes, specific ownership rules, and cleanup toggles.  Without them
config-dir was chowned to the service user, which systemd never does,
an existing directory with drifted ownership was left wrong, and the
runtime directory could not survive a restart.

Now matching systemd.exec(5), and where the man page is vague, the
code in setup_exec_directory():

  - each directory takes a matching -mode key, octal with the leading
    zero, default 0755.  The mode of the named directory is locked
    down again on every start, also when it already exists
  - config-dir is created but never chowned
  - the contents of an existing directory are left alone as long as
    the owner is right; on drift everything under it is chowned back
  - runtime-dir-preserve = no | restart | yes maps
    RuntimeDirectoryPreserve=.  A service still qualified to run when
    the runtime directory would be removed is restarting, not
    stopping, which is what svc_enabled() answers

The dir mechanics move to mksubsysd(), taking resolved ids, with
mksubsys() reduced to a name-resolving wrapper for the dbus plugin.
The child resolves uid/gid once for both directory setup and
privilege drop.

The symlink form, RuntimeDirectory=foo:bar, is not adopted.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2026-07-30 15:23:38 +02:00
1 parent f0d7257374
commit 6b03a1ec8f
8 files changed
+191 -44

No files matched your search

+15 -2
View File
@@ -114,13 +114,26 @@ are refused:
Each resolved path is exported to the process environment under the
listed name, the same names systemd uses for `RuntimeDirectory=` and
friends.
friends. As in systemd, `config-dir` is the odd one out: it is created
but never chowned.
Each takes a matching `-mode`, e.g. `runtime-dir-mode = 0700`, default
0755. Modes are octal, with the leading zero.
The mode of the named directory is locked down again on every start.
Its contents are left alone as long as the owner is right; if the owner
has drifted, everything under it is chowned back.
The runtime directory is removed again when the service stops, after
any `exec-stop-post` script has run; `/run` is a tmpfs so it would not
survive a reboot anyway. The other four persist. A completed `run` or
`task` counts as stopped, unless `remain-after-exit` keeps it alive
until stopped for real.
until stopped for real. `runtime-dir-preserve` adjusts this, same
values as systemd's `RuntimeDirectoryPreserve=`:
* `"no"` -- removed when the service stops, the default
* `"restart"` -- kept across restarts, removed on a real stop
* `"yes"` -- never removed
This is what lets a service drop privileges and still create, and
later touch, its own PID file: