33 Commits
Author SHA1 Message Date
Joachim Wiberg cec76f18a3 doc: ChangeLog entry for the lost reload fix
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-09-27 18:56:03 +02:00
Joachim Wiberg 0548485be1 doc: update ChangeLog for 5.0
Covers the longer user and group names, the tmpfiles mode and owner
work, the shutdown remount order, and the stop/reload script timeout.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-09-27 18:00:13 +02:00
Joachim Wiberg 61b0e0f3e6 Fix #420: run services inside a PAM session
Apply a PAM session to run/task/sysv/services Finit starts, pam_limits
above all, so a service running as a given user picks up that user's
limits the way a login does.

Add a new `pam` setting for the new block format (only), like the
per-service directories, naming a file in /etc/pam.d:

    service weston {
        user    = "weston"
        pam     = "weston-autologin"
        command = "/usr/bin/weston --continue-without-input"
    }

pam_close_session() has to be called by a process still holding the
handle, and the handle does not survive exec().  Hence the keeper: it
holds the handle, drops to the service's credentials, and waits for a
parent-death signal before closing the session.  Same shape as
systemd's (sd-pam), for the same reason, and one per fork, so the
script hooks open and close their own.

The keeper closes the descriptors it inherited from Finit and only
those.  Closing everything would also take out what pam_open_session()
opened for itself, a keyring fd or a lock file, and leave the modules
to close a session with those pulled out from under them.  Closing
nothing, as (sd-pam) does, would leave it holding the write end of the
notify pipe for the service's whole lifetime and starve notify = "s6"
services of their ready signal.  So the fds open before pam_start()
are snapshotted and exactly those are closed, while the ones PAM opens
after are marked close-on-exec so the daemon does not inherit them
either.

A refused value, a denied account stack, an uninstalled pam.d file,
and a build without PAM support all keep the service from starting
rather than running it with the stacks skipped: one that quietly loses
pam_limits and its private /tmp, with nothing said.  Capabilities a
module like pam_cap.so granted are merged into the IAB Finit applies
instead of being replaced by it, which only helps a service that also
sets capabilities, the other arm being a plain setuid() with nothing
left to restore once permitted is empty.

The test sysroot gains pam_permit.so, pam_deny.so and pam_limits.so,
which ldd cannot see, libpam dlopen()s them, and the test skips when
the host has none to stage.  The negative cases pin the exit status
rather than only asserting crashed, which serv reports for any early
exit, so a bad command or an unwritable pidfile cannot pass for a
rejected session.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-09-23 16:30:14 +02:00
Joachim Wiberg a274677f05 configure: keep the replacement libsystemd opt-in
Building it by default installs our libsystemd.so.0 in $libdir.  Where
the real one is already present, and contrib/debian/build.sh configures
--prefix=/usr --exec-prefix= on a Debian host, ours outranks it in the
loader cache, and every program linking libsystemd loses
sd_journal_stream_fd and the LIBSYSTEMD_209 symbol versions.  The test
sysroot ran into exactly that, dbus-daemon exited 127 on every restart.

Restore the default to no.  sulogin and watchdogd stay on, they only add
binaries.  distcheck asks for the library so it stays covered.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 15:21:29 +02:00
Joachim Wiberg cdf2337346 configure: build sulogin, watchdogd, and libsystemd by default
v5.0 ships keventd and the D-Bus support enabled out of the box, but the
remaining bundled pieces stayed opt-in, and the help text for two of them
already claimed otherwise.

Default all three to yes; --without-sulogin, --without-watchdog, and
--without-libsystemd opt out.  The distcheck and CI configure lines drop
the flags they no longer need, so CI exercises the defaults.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 13:54:19 +02:00
Joachim Wiberg 7644874b42 Update ChangeLog and bump version for v5.0-rc1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 09:35:11 +02:00
Joachim Wiberg e8391864d7 conf: read /run/finit/system before /lib/finit/system
Stanzas in /lib/finit/system cannot use if:keventd, or any other
built-in service: if: is evaluated at parse time, and the generated
.conf files for built-ins were read after the system directory, so the
referenced service did not exist yet and the stanza was dropped.

The late position was deliberate: it kept bundled services from starting
before udev (5d703fd3).  The motivating case was dbus, which has since
moved to a build-time 20-dbus.conf (2e0b1d6f), and the built-ins that
remain want the early slot: watchdogd should start as soon as possible,
keventd is the device manager, and runparts is gated on int/bootstrap so
its position never mattered.

Reading /run/finit/system first also puts the override chain in its
natural order: built-in/generated defaults, then bundled (read-only)
system files in /lib, then the administrator (override) .conf file in
/etc/finit.d, always read last.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-17 19:04:52 +02:00
Joachim Wiberg 292e87c0d1 keventd: serve org.finit.Device1 on /run/keventd/bus
The udev parity gaps that were blocked on IPC -- settle, trigger,
info, queue introspection, runtime rule reload -- become bus methods.
keventd serves its own socket the way Finit serves /run/finit/bus:
brokerless, libink, one socket per daemon, no forwarding between the
two.

  Settle(u) -> b      parked until the queue drains or the timeout
                      passes; true when settled
  Trigger(s, s)       replay events, action + subsystem glob
  Info(s) -> a{ss}    /run/udev/data properties for a devpath
  RulesReload() -> u  re-read rules dirs, returns rule count
  QueueEmpty (b), SeqnumProcessed (t) properties
  DeviceProcessed (ss) signal after each fully handled event

The queue state is the highest kernel seqnum keventd has handled,
baselined at startup, against /sys/kernel/uevent_seqnum.  keventd -S
now asks the running daemon first and falls back to seqnum polling.
In passive mode Trigger and RulesReload refuse.  Adds
link_call_connection() for the park bookkeeping.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 22:03:43 +02:00
Joachim Wiberg a814e85356 doc: complete and cross-link the D-Bus documentation
dbus.md was orphaned: not in dist_docs_DATA, not linked from the
user guide.  Wire it into the doc dist and link it from the index
features list, features.md, initctl.md, and plugins.md, where the
dbus.so plugin entry now disambiguates the external system bus from
the built-in org.finit API.

Document the 64-peer cap, the supported AddMatch keys, the busconfig
policy file, the legacy-parity edge semantics with the deliberate
SetRunlevel InvalidArgs divergence, the reload-signal behavior of
Service1.Reload, and the reboot family timeout.  Refresh the stale
initctl.md usage paste, add monitor and the D-Bus transport to
initctl(8), add /run/finit/bus to the filesystem layout, and flatten
the ChangeLog D-Bus entry to house style.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 22:03:41 +02:00
Joachim Wiberg 3231ade38a dbus: fixes from a code review of the branch
A pass over the whole branch before merge, mostly in libink since
that is the new code and the part exposed to the wire.  Grouped here
rather than scattered so the review is easy to read in one place.

libink parser and dispatch:

 - Bound reader lengths so a 32-bit size_t can't wrap a wire length
   past the guard and read out of bounds.  Reachable pre-auth on any
   bus, so it matters on the 32-bit targets Finit runs on.
 - Drop a peer when a reply send fails instead of limping on with a
   half-written frame; a built-in whose send failed used to fall
   through and put a second frame on the wire.

initctl:

 - Copy a D-Bus error name out of the reply before closing the client;
   the reply points into memory the close frees.  Both error paths now
   share one helper so this can't creep back.

Authorization:

 - Take the caller's groups from the kernel (SO_PEERCRED plus
   SO_PEERGROUPS) rather than getpwuid()/getgrouplist(), which go
   through NSS and can block PID 1 on a slow LDAP or SSSD backend.
   The check is now a lookup against the group resolved once at init,
   with no NSS and no 256 KiB array on the stack.  A caller reaching
   us through a broker carries no group set, so system-bus privileged
   methods are root-only; the local bus keeps group support.  See
   libink/README.md for the note on lifting that.

Shutdown:

 - Call dbus_exit() from the shutdown path so the server, its peers,
   and the socket are let go cleanly.  The teardown existed but nobody
   called it.

Tests, CI, docs:

 - A fuzz target for the message parser, run as a quick sweep in the
   suite and properly under libFuzzer in CI, with the corpus carried
   between runs.  The -as-uid tests drop groups the way a login does
   so SO_PEERGROUPS sees the right set, and widen the test socket to
   reach the per-method check behind the 0660 gate.  Bring the GitHub
   actions up to versions that run on Node 24, and tidy a few small
   things a /simplify pass turned up.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 08:57:38 +02:00
Joachim Wiberg 2e0b1d6f8b plugin: start a system bus by default
Finit speaks D-Bus itself now and claims org.finit on the system bus
when it finds one, but nothing in a default build ever brings that bus
up.  The plugin that does was opt-in, so the built-in support sat idle
unless the integrator knew to ask for both halves.

Defaulting it on is only reasonable if the result stays the admin's to
change, and a service registered from C through conf_save_service() is
not: it lands in the run path where it cannot be overridden or emptied
out.  So the daemon moves to 20-dbus.conf and its directories to
tmpfiles.d/dbus.conf, the same way hotplug and every other daemon we
ship them for.  The plugin keeps only what has to look at the running
system, the stale pidfile and the machine UUID.

Those directories are no longer chowned to messagebus.  tmpfiles.d
skips a line whose user does not exist rather than falling back, so
the plugin's messagebus/dbus/root ladder has no equivalent there, and
dbus-daemon binds its socket before dropping privileges anyway.

The plugin already bows out where there is no dbus-daemon installed,
so systems that never wanted a bus are unaffected, and
--disable-dbus-plugin is there for those that have one and would still
rather init left it alone.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-13 10:15:19 +02:00
Joachim Wiberg ebc0ef62e6 libink/finit: properties, and org.finit on the system bus
Runlevel and version are state, not actions, so they belong behind
org.freedesktop.DBus.Properties rather than another method each.

Finit also claims org.finit on the system bus when it finds one, so
ordinary D-Bus clients can reach it without knowing about
/run/finit/bus.  Opportunistic on purpose: no dbus-daemon is a normal
state for the systems Finit runs on, not an error to report.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-13 09:28:14 +02:00
Joachim Wiberg 6b77a16f8b conf: add missing passenv to tty blocks
The line-based format has had the flag since v4.4 (issue #286), where
it prepends -p to the built-in getty, which turns it into login -p and
passes the environment on.  The block format was written from the three
documented tty variants and the flags listed in the tty documentation,
and passenv was in neither, so it was left out.  Converting a tty line
that used it therefore lost it, with nothing said.

It only reaches the built-in getty.  An external getty is handed its
arguments through command, so there is nowhere to put a -p, and the
setting is refused with a warning rather than quietly ignored.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-05 17:59:11 +02:00
Joachim Wiberg 96c5b4b031 doc: document the provides setting
The migration guide told anyone holding the repeated-stanza idiom for a
per-platform service to split the variants across files or stay on the
line-based format, because a block title is an identity and the
variants have to share one barrier.  provides is the answer, so the
guide converts that shape now instead of routing around it, and the
header of 10-hotplug.conf.in no longer points at the workaround.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-05 17:59:09 +02:00
Joachim Wiberg 4299ce8839 doc: document command candidates and the duplicate title rule
The migration guide covered a stanza at a time, which is the wrong
shape for the two idioms that repeated a whole stanza.  One of them,
several candidate binaries for one service, is now a command list.
The other, one service gated differently per platform, has no block
equivalent: those blocks share an identity because they share the
barrier condition downstream services wait for, so they cannot be
given separate titles.  For that one the guide says to split the
variants across files, or leave that file in the line-based format,
which Finit still reads.

The udevd example in services.md taught the merge-broken form, and
system/10-hotplug.conf.in pointed readers at it for their syslogd.

Also lists libConfuse among the build dependencies.  It has been
mandatory since the new .conf format landed, and build.md still said
two libraries.  And corrects the note on variable expansion: it is
${VAR} that libconfuse expands when the file is read, with
${VAR:-default} supported.  A plain $VAR reaches the service, which is
what makes `command = "syslogd -F $SYSLOGD_ARGS"` work with envfile.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-05 17:57:56 +02:00
Joachim Wiberg 7d09e34b80 doc: document stale pidfile cleanup and new restart log
* src/pid.c: note the stale-pidfile-cleanup exception to the
  documented "Finit does not touch pid:! pidfiles" rule.
* doc/config/services.md: add a user-facing paragraph on the same.
* doc/ChangeLog.md: add Unreleased section covering this PR --
  stale pidfile cleanup, restart log with signal name and core
  dump flag, and the SIGUNKOWN typo fix.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-05-12 10:11:50 +02:00
Joachim Wiberg e74dff96ba Update ChangeLog and bump version for v4.17 GA
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-28 10:09:16 +02:00
Joachim Wiberg 17d04779fb Update ChangeLog and bump version for v4.17-rc1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-26 21:54:49 +02:00
Joachim Wiberg 17c6791c70 Update ChangeLog and bump version for v4.16 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-27 10:35:32 +01:00
Joachim Wiberg cef5049bf0 Update ChangeLog and bump version for v4.16-rc1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 05:36:45 +01:00
Joachim Wiberg a1a92a04bd Update ChangeLog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-22 20:51:07 +01:00
Joachim Wiberg 60478106eb Update ChangeLog with latest changes and features
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-10 16:01:53 +01:00
Joachim Wiberg bbe588ac16 Bump version for new release cycle and update ChangeLog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-01-12 19:32:09 +01:00
Joachim Wiberg ad225156f1 Update ChangeLog and bump version for release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-01-01 11:09:16 +01:00
Joachim Wiberg f0032ab6b7 Throttle failing services, e.g., tty, on error exit code
Some 'respawn' type services, like gettys, may hog the CPU in error
states if the service immediately exits.  E.g., due to missing dev.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-27 12:32:01 +01:00
Joachim Wiberg 12f7855a78 Update ChangeLog for v4.15 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-26 13:41:18 +01:00
Joachim Wiberg f4a13687e8 initctl: resolve hierarchical cgroup limits
Cgroups v2 limits are hierarchical - a process is constrained by the
most restrictive limit in its ancestor chain, not just its immediate
cgroup.  This patch updates cg_conf() to walk up the hierarchy and
report effective limits by comparing values at each level.

This fixes incorrect "max" (unlimited) reporting in 'initctl --json
status', 'initctl cgroup', and 'initctl top' when child cgroups have
no explicit limits but parents do.

For memory.max and cpu.max: take minimum (most restrictive)
For memory.min: take maximum (most protection)

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-17 08:19:37 +01:00
Joachim Wiberg f513348963 doc: update ChangeLog for upcoming v4.15
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-15 22:38:41 +01:00
Joachim Wiberg 85baafe99c doc: update links to new project home and add release badge
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-15 22:37:08 +01:00
Joachim Wiberg 09b4aee5bc Update ChangeLog and bump version for v4.15-rc1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-07 09:38:14 +01:00
Joachim Wiberg 1be67c434e Update ChangeLog and bump version for v4.14 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-08-29 15:07:45 +02:00
Joachim Wiberg 85484178e0 Update ChangeLog and bump version for v4.13 GA
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-07-10 18:33:24 +02:00
Joachim Wiberg 2aa9e5bad6 doc: relocate AUTHORS and ChangeLog
Part of project cleanup-root

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-07-10 16:45:48 +02:00