Commit Graph
4217 Commits
Author SHA1 Message Date
Joachim Wiberg 34a0a4b1ff conf: pass -- in a block command to the program
A command that takes -- as an argument lost it, and everything after
it, to the description:

    service name {
        command     = "cmd -- arg"
        description = "a cmd"
    }

ran `cmd` with description `arg`.

The block translator builds a legacy one-liner, appending the
description as "-- text", and service_register() splits that line at
the first "-- ", here the one in the command.

Split the description off only for legacy one-liners.  Blocks now hand
it to the new service_register_desc() as an argument.

Fixes #512

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-11-13 15:56:30 +01:00
Paweł c03059a9a0 keventd: don't publish whole-disk by-id links for partitions
disk_serial_id() falls back to <disk>/../serial so a partition got a
by-id link named after its parent disk's serial, clobbering the link
created for the whole disk.

(cherry picked from commit 4b2f8c89c5)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-11-13 15:06:08 +01:00
Joachim Wiberg 297d2de1da Merge pull request #511 from zhangxiaohui1/fix/remain-task-control
service: preserve explicit stop for remain tasks
2026-11-12 21:06:47 +01:00
Joachim Wiberg 3acf1cb7b1 Merge pull request #517 from vazub/hwdb-parse-fix
keventd: fix hwdb lookups that never match
2026-11-12 19:25:38 +01:00
Joachim Wiberg eb9fb83011 Merge pull request #516 from vazub/symlink-fix
keventd: fix dangling and misnamed /dev/input/by-id links
2026-11-12 19:24:02 +01:00
Joachim Wiberg b6f0d5314b Merge pull request #521 from firasuke/firasuke-patch-1
Add conditional include for sm.h based on AUTO_RELOAD
2026-11-12 19:22:53 +01:00
Joachim Wiberg 59a2f69345 Merge pull request #515 from augustebaum/patch-1
docs: Fix nested bulleted list
2026-11-09 17:14:29 +01:00
Firas Khana 90512b07a0 Add conditional include for sm.h based on AUTO_RELOAD 2026-11-06 23:09:13 +03:00
Firas Khana d313b1fd74 Add conditional include for sm.h based on AUTO_RELOAD 2026-11-06 23:04:57 +03:00
Basil Zubko 439cab0558 keventd: fix hwdb parsing issues 2026-10-31 20:42:07 +01:00
Basil Zubko 98b2effb52 keventd: fix dev symlinks 2026-10-30 12:30:40 +01:00
Auguste Baum cbd5f79ffd docs: Fix nested bulleted list 2026-10-30 12:13:23 +01:00
Joachim Wiberg a220e0fa9b Merge pull request #514 from vazub/static-fix
Fix static build dropping all built-in plugins
2026-10-27 12:24:28 +01:00
Basil Zubko 1efd50191c fix static build dropping all built-in plugins 2026-10-24 15:13:10 +02:00
Joachim Wiberg 096e6337c5 Merge pull request #513 from vazub/keventd-input
keventd: fix ENV{} match on unset properties
2026-10-24 12:33:46 +02:00
Basil Zubko 02cd1bac42 keventd: fix ENV{} match on unset properties 2026-10-24 09:06:23 +00:00
zhangxiaohui 3a18ca4a30 service: preserve explicit stop for remain tasks
A completed remain task unconditionally cleared its user stop block
after running its post script.  Since it was still valid in the current
runlevel, it immediately started again, making initctl stop ineffective.

Keep explicit stops blocked, distinguish automatic and requested
restarts, and route initctl restart through teardown before rerunning the
task.  Cover stop, start, restart, reload, and runlevel transitions with
a regression test.

Signed-off-by: zhangxiaohui <xiaohui.zhang@wbstar.com>
2026-10-21 19:03:46 +08:00
Joachim Wiberg 530d6703f1 Merge pull request #509 from anees-r3hman/umount-rc
mount: report unmount failures
2026-10-12 09:38:08 +02:00
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 ee6d4a1dae service: keep a pending reload across a second conf reload
A service whose condition goes into flux during a reload is paused
with its reload still pending.  If another reload was requested in
the meantime, re-parsing its unchanged .conf file cleared the pending
mark, so the service was resumed without ever being reloaded.  Seen
with sshd <pid/syslogd> on Infix, where a configuration change that
touched both landed as two reloads in a row and sshd kept its old
listen addresses.

The mark is only ever cleared once the change has been applied, so a
mark that is still set when the file is parsed again means exactly
that: not applied yet.  Leave it alone.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-09-27 18:41:05 +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 1b10c3746e Merge pull request #508 from anees-r3hman/avoid-fstab-on-root-remount
sig: avoid reading fstab during shutdown
2026-09-27 17:58:33 +02:00
Joachim Wiberg 24911ebbc2 Merge pull request #507 from anees-r3hman/master
svc: allow longer user and group names
2026-09-27 17:42:11 +02:00
Joachim Wiberg 88a9e6575b tmpfiles: apply mode and owner of e and f/F entries through an fd
Same treatment as d/D got: e went through fisdir() and a path based
chmod/chown, f/F did the chmod/chown by path after closing the file.
Both now work on the open fd, so the mode and owner end up on the
directory or file that was just checked or written.  f/F use open(2)
directly, which lets a plain f rely on O_EXCL for create-if-missing
instead of the earlier stat().

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
(cherry picked from commit 75739fbeef)
2026-09-27 17:30:16 +02:00
Sam Brkopac 9bfbdc6bac tmpfiles: set mode and owner of d/D directories through an fd
makedir() swallows EEXIST, so the chmod branch for directories that
already existed never ran, while chown() ran every time.  On finix
/var/empty is immutable, which gave a warning on every boot even
though the owner was already correct.

mksubsys() is the original of this code and has the same shape, the
dbus plugin uses it for /tmp/dbus.  Both now go through dirperm(),
which opens the directory and uses fstat/fchmod/fchown on the fd,
changing only what differs.  A failed chown in mksubsys() is a warning
now rather than err(1), PID 1 should not exit over a directory it
cannot adjust.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
(cherry picked from commit 3a72d1263c)
2026-09-27 17:26:08 +02:00
Anees Rehman c016965371 mount: report unmount failures
Return a failure status from unmount_regular() when filesystems remain
mounted, and use it to report the final shutdown unmount result.

Signed-off-by: Anees Rehman <anees.rehman@atlascopco.com>
2026-09-25 21:20:02 +02:00
Anees Rehman 263ea929fd sig: avoid reading fstab during shutdown
Only fall back to the regular mount invocation when both
fstab-independent root remount attempts fail.
This avoids reading an encrypted fstab during a normal shutdown.

Signed-off-by: Anees Rehman <anees.rehman@atlascopco.com>
2026-09-25 19:41:05 +02:00
Anees Rehman cc5e0c5175 svc: allow longer user and group names
Service user and group names are stored in 16-byte buffers, limiting
them to 15 characters. This silently truncates longer names before
getpwnam() and getgrnam(), preventing services configured with valid
longer account names from starting.

Increase the buffers to match the existing maximum configuration
argument length.

Signed-off-by: Anees Rehman <anees.rehman@atlascopco.com>
2026-09-25 16:09:35 +02:00
Joachim Wiberg 417abf9000 Merge pull request #500 from finit-project/pam 2026-09-23 17:52:38 +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 bad7c5c99a .github: unwrap ChangeLog paragraphs in release notes
The ChangeLog is hard-wrapped at 72 columns, which the GitHub releases
page renders verbatim as a ragged right edge.  Join the continuation
lines of each paragraph and list item, as already done in Infix, and
let the browser do the wrapping.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-30 10:12:29 +02:00
Joachim Wiberg 4c16190831 build: drop md5 and sha256 files from releases
GitHub now shows a sha256 digest for every uploaded release asset, so
the sidecar hash files only clutter the asset list.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-30 10:12:29 +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>
5.0-rc1
2026-08-29 15:21:29 +02:00
Joachim Wiberg f51aee1ec5 test: keep the replacement libsystemd out of the sysroot
dbus-broker fails, the bus never comes up:

    Service dbus[19] died (exit status: 127), restarting

The sysroot stages dbus-daemon from the host, which links the real
libsystemd, and since v5.0 builds ours by default the install puts a
second libsystemd.so.0 in the sysroot.  It wins the ld.so cache, and
dbus-daemon finds neither sd_journal_stream_fd nor the LIBSYSTEMD_209
symbol versions in it.

Uninstall the library from the sysroot after the install.  The test serv
compiles sd-daemon.c in, so nothing there needs it.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 14:28:59 +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 847f4db974 dbus: install the bus policy in $datadir/dbus-1/system.d
make distcheck fails in install:

    /usr/bin/install: cannot create regular file '/etc/dbus-1/system.d/org.finit.conf': Permission denied

The policy was installed to $sysconfdir/dbus-1/system.d.  distcheck only
overrides the prefix, so the file escaped its sandbox and aimed for the
real /etc.

Install it where dbus looks for package owned policy, leaving
/etc/dbus-1/system.d to the admin.  The test bus config reads it
relative to itself.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 13:54:14 +02:00
Joachim Wiberg 969f9a112c test: locate the fuzz sweep in the build tree
fuzz-msg-parse.sh looked for its driver next to the script, which only
holds when srcdir and builddir are the same.  Every VPATH build skipped
the sweep, claiming D-Bus was off:

    SKIP: fuzz-msg-parse.sh

distcheck, and with it the release job, is a VPATH build.  Use
top_builddir, which the test environment already exports.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 13:54:13 +02:00
Joachim Wiberg 2b812101be test: run keventd from the configured libexec path
make distcheck fails in dbus-device:

    sh: /libexec/finit/keventd: not found

distcheck configures with --prefix=$(distdir)/_inst, so the bundled
helpers install below that prefix, not in /libexec/finit, which the test
had hard coded.

Export the configured pkglibexecdir as FINIT_EXECPATH in test.env and
run keventd from there, the same path finit itself is built with.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 13:54:06 +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 c512d57df4 doc: describe the udev rules keventd actually implements
The engine covers most of the udev grammar but not all of it, and the
gaps are invisible until a rule silently does nothing.  Write down what
is implemented and where it parts ways with udev(7), rather than
leaving people to infer it from a ruleset that happens to work.  The
man page gets the directory precedence and a pointer to udev(7) and
the User's Guide, which hold the details.

Rename the menu entry to Device Manager while here, matching how the
watchdog daemon is listed.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 09:27:26 +02:00
Joachim Wiberg 59945b87f7 keventd: load udev rules in udev's order, with masking
The rules directories were read one after the other, each sorted on
its own.  udev instead sorts all files from all directories together
and lets a file mask one of the same name in a lower priority
directory.  The difference broke both standard override idioms
without a sound: copying a rules file to /etc/udev/rules.d/ to edit
it left the original running too, and symlinking a name to /dev/null
disabled nothing.

Collect everything with glob(), drop entries shadowed by a later
directory, and sort the survivors by filename, same as udev and the
tmpfiles.d handling in Finit itself.  The -r directory sits above
/etc/ so a test ruleset can override anything shipped.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 09:26:18 +02:00
Joachim Wiberg d23a9b8a16 Merge pull request #499 from aanderse/docs
docs: cleanup some development work
2026-08-29 08:05:54 +02:00
Joachim Wiberg e5040385f5 test: fix flaky crashing.sh
Two races, both around the post:script Finit runs when it gives up on a
service.

Finit marks the service crashed before it forks post:script, so the file
the test greps for lands a moment later.  Waiting for the state is not
enough.

slay then takes the PID from initctl status, and service_post_script()
sets svc->pid to the script's PID, so once Finit has given up the PID
reported for the service is the post:script.  Killing that takes out the
script instead of the service and the file never arrives at all.  The
guard for this was already there, with a comment describing it, but
inside the loop that waits for a PID to appear, so it only covered the
case where there was none.  A PID that was already there went straight
to kill -9.  Hence the gcc leg killing once more at lap 13, after Finit
had stopped restarting, where clang stopped at 12.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-22 10:25:28 +02:00
Joachim Wiberg e9efec8694 Merge pull request #501 from aanderse/libsystemd
libsystemd: guard sd-daemon.h with extern C for c++ consumers
2026-08-22 07:51:27 +02:00
Aaron Andersen 7110ae4427 libsystemd: guard sd-daemon.h with extern C for c++ consumers 2026-08-21 16:08:15 -04:00
Aaron Andersen a7ee24662f docs: cleanup some development work 2026-08-19 21:00:48 -04:00
Joachim Wiberg 48e85efb88 Merge pull request #491 from finit-project/devman
Finit 5: udev/eudev replacement

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-18 10:37:14 +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 2a2f7cda63 Merge pull request #496 from FixeQD/master
switch-root: return real errors instead of false success

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 23:41:08 +02:00
Paweł Sobczak ad02b343f2 initramfs: drop to sulogin when switch_root fails past the ACK
A failed move of /dev, /proc, /sys or /run is logged at dbg() level
and ignored, so the new init boots without its virtual filesystems
and falls over much later in some unrelated way.  The steps after,
chdir/mount/chroot and the final execl(), do return -1 on failure,
but by then all services are dead and the API socket is gone, so
there is nobody left to report to: the system hangs with a live but
useless PID 1.

Make a failed move fatal, and try all four moves even if one fails,
so a bad /dev does not also skip /proc, /sys and /run.  A plain
directory is not an error though: /run stays a plain directory on a
tmpfs rootfs, so only a path on a different device than / is treated
as a mount point and moved.

Any failure past the point of no return now drops to sulogin(1) for
a maintenance shell that reboots on exit, same as a fatal fsck() at
boot.  Signals are unblocked before the moves so the shell does not
inherit finit's blocked signal mask.

Signed-off-by: Paweł Sobczak <github@fixeq.qzz.io>
2026-08-16 23:17:57 +02:00