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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
The precheck accepts a directory as new init: access(path, X_OK)
only checks search permission, which directories almost always have,
so the mistake is not caught until after teardown. The snprintf()
building init_path also never checks for truncation, so an overlong
newroot + newinit validates the wrong path.
Require a regular file, with EISDIR or ENOEXEC to match what is
printed, and fail with ENAMETOOLONG on a truncated init path.
Signed-off-by: Paweł Sobczak <github@fixeq.qzz.io>
initctl switch-root always exits 0, no matter what happens on the
finit side. do_switch_root_api() sends the ACK before switch_root()
has validated anything, so any failure after that point never reaches
the client -- the error only shows up in the log. The runlevel guard
in api_cb() has the same problem: it rejects the request but still
sends an ACK.
Split the validation out of switch_root() into switch_root_precheck()
and run it before the ACK. A failed check now sends a NACK with the
error message, which initctl prints before exiting 1:
initctl switch-root /mnt
switch-root: /mnt is not a mount point
The ACK is only sent once the precheck passes, since after that point
we are committed. On success finit execs the new init and the
connection dies with no reply at all, so initctl treats only an
explicit NACK as failure.
Signed-off-by: Paweł Sobczak <github@fixeq.qzz.io>
Half the daemon was missing: -p, -r, -S, -t from SYNOPSIS and
OPTIONS, class/ and driver/ conditions, SIGHUP rules reload, the
rules engine and its directories, /run/udev/data, and the D-Bus
socket in FILES.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Three copies of read-first-line-from-a-file (sysfs_read_file, a
static sysfs_read, fgetline), two condition emitters symlinking the
same reconf marker (cond_emit, sys_cond), two seqnum-stable loops,
and five hand-rolled logit() prototypes, none with a printf
attribute, so no format string was ever checked.
Keep one of each: cond_emit() is exported and mkpaths its parents,
which also retires init_dev_condition_dir() and the sys/ directory
priming loop; logit() moves to keventd.h with the format attribute;
the stability test becomes seqnum_stable(), shared by the coldplug
gate and settle; kev_now_ms() serves dbus.c too. rule_ctx_free()
and kev_seq_baseline() had one caller each in their own files, now
static.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
initctl reload freezes conditions to the old generation and each
owner re-asserts. Finit's own providers do this in-process; an
external provider whose conditions are generation files, rather than
the oneshot symlinks keventd uses, has no way to know the moment.
Emit Manager1.ConfigReloaded when reconfiguration completes.
keventd needs no subscriber: its conditions are symlinks to the
reconf marker itself, so they read the current generation by
construction and never flux, which the device bus test now pins
down.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Introspection, queue-state properties, immediate and bus-first
settle, Info by devpath, Trigger(add, net) observed via the
DeviceProcessed signal, and RulesReload -- driven by dummy interface
hotplug like keventd.sh. New call-ss and call-u client modes, and
getprop learns the b and t variants.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
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>
udevdb_read_parent() contained the general capability, keyed from
sysfs when no uevent is in hand. Split it out as
udevdb_read_devpath() for the D-Bus Info method; parent lookup
becomes a wrapper.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
coldplug_trigger(action, subsystem-glob) replays events for a subset
of devices, the D-Bus Trigger method needs both knobs; coldplug() is
now the ("add", NULL) case. nftw() has no user cookie, so the
parameters ride in file statics.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The park machinery was welded to broker uid resolution; a handler
that cannot answer yet, like a device-settle call waiting for the
event queue to drain, had no way to defer. link_call_park() holds
the request, link_call_resume() re-runs the handler with
link_call_resumed() reading true, and the expire sweep remains the
backstop for a resume that never comes.
Resume also no longer drops a local caller's kernel group set in the
privileged re-check: group source now keys on broker-ness.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Device seqnums are 64-bit; the writer and reader stopped at u32.
Adds t/x/d to the skip path so a{sv} consumers tolerate them.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
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>
The D-Bus support is default-enabled, so the HAVE_DBUS paths only
bit-rot silently without this: the leg caught initctl failing to
build with --disable-dbus on its first local run. Also asserts the
binaries carry no bus references and smoke-runs one non-dbus test.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
initctl_CPPFLAGS is only assigned under the DBUS conditional, but an
automake per-target variable exists even when its conditional is
false, so a --disable-dbus build dropped AM_CPPFLAGS entirely:
util.c:319:16: error: invalid use of undefined type 'struct FTW'
Assign the base flags unconditionally and append under DBUS.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The path encoding in libink/path.c was untested for identities with
separators; dbus-service.sh only used the bare keventd identity.
Declare a dhcp-client:eth1 service and verify the escaped path, that
the object introspects, and that Identity round-trips.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
All three org.finit signals were invisible to generated proxies, and
org.freedesktop.DBus was missing from the standard interfaces even
though Hello, AddMatch, and RemoveMatch are answered.
Add a link_signal_t table to the vtable, emitted like methods and
properties, declare the Manager1 and Cond1 signals, and complete the
static XML with PropertiesChanged and org.freedesktop.DBus.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The D-Bus methods carried byte-for-byte copies of api.c's static
start/stop/restart helpers. Promote them to service.c alongside
service_reload(), which already serves both callers, and reduce both
sides to svc_parse_jobstr-style adapters.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Regression tests for the recent handler fixes: bogus SetRunlevel is
InvalidArgs, Signal on a stopped service is Failed, and the reboot
family declares the timeout argument. Reboot cannot be invoked
without taking down the sandbox, so the latter is asserted via
introspection. New call-u and call-su modes in dbus-auth-client.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
initctl -t N reboot arms an emergency bypass timer over the legacy
socket, but the bus methods took no argument, so the timeout was
silently dropped whenever D-Bus was up.
Reboot, Halt, and Poweroff now take a timeout in seconds, 0 for
none, armed via the same shutdown_bypass() the legacy path uses.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Service1 Start/Stop/Restart discarded the action return value, their
Manager1 twins map it to org.finit.Error.Failed. Cond1 Set/Clear
replied success even when the condition symlink operation failed,
where legacy initctl exits 73. Verify the resulting condition state
with cond_get() rather than the noupdate return values, which report
no-change, not failure, and would reject an idempotent re-set.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Manager1.Signal silently skipped stopped services, so the same
command gave different exit codes depending on transport: the legacy
INIT_CMD_SIGNAL path fails when the service is not running. Mirror
the legacy behavior.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The bus method called sm_runlevel() unconditionally. In runlevel 0
and 6 that aborts an in-flight shutdown, which INIT_CMD_RUNLVL
refuses with a warning, and during bootstrap it switches immediately
where the legacy path defers via cfglevel to the end of runlevel S.
Port both. A bad runlevel argument still returns InvalidArgs, where
the legacy protocol acks silently: a typed interface rejects garbage.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The legacy INIT_CMD_SUSPEND is refused in runlevel S, 0, and 6, the
bus method suspended unconditionally, even mid-shutdown. Add the
same guard, replying WrongRunlevel like the reboot family.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Once it gives up it forks the post:script and reports that PID as the
service's, so a slay still waiting for the service to come back killed
the script instead, and crashing.sh lost the /tmp/post it checks for.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The unified keventd has no automated coverage, only the devmon
fallback is exercised by the test suite. Network interfaces are
the one device class an unprivileged test can hotplug: the sandbox
has its own network namespace, so 'ip link add' makes the kernel
emit genuine uevents.
Verify keventd readiness, <class/net/IFNAME> driving a service --
and <dev/IFNAME> NOT asserted, interfaces are not device nodes --
libudev-compatible n<ifindex> keying in /run/udev/data, conditions
surviving initctl reload, and cleanup on interface remove.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
A service with a <class/net/eth0>, or any other keventd-provided,
condition is never started when the device appears. keventd asserts
the condition file, but devmon only watches /dev, so no cond_update()
ever reaches affected services. Reload made it worse:
devmon_reconf() clears any registered dev/ condition without a /dev
node behind it.
Watch the dev/, class/, and driver/ condition directories, like the
sys and usr plugins do for their namespaces, and treat an existing
condition file as device presence in devmon_reconf().
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
keventd links libblkid, which finit itself does not, but sysroot.mk
only copied the libraries finit links. Inside the sysroot keventd
then fails to start:
Service keventd[18] died (exit status: 127)
Collect libraries from finit and everything installed under
libexec/finit/ instead.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When started with -c (the default when keventd is the device manager),
gate the pidfile on the kernel's uevent_seqnum having been stable for
200ms. Up to now ready signaling with the pidfile was done right after
coldplug() triggered the kernel to re-emit events, but before uev_run()
had drained any of them, so <pid/keventd> really only meant "listening
on netlink".
With the gate, services that depend on <pid/keventd> can now assume /dev
is populated and persistent symlinks are live.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Stop-gap "settle" equivalent of udevadm settle for migration scenarios.
Polls /sys/kernel/uevent_seqnum every 50ms and exits zero when the
sequence number has been stable for 200ms (or non-zero after -t SECONDS
timeout, default 30s).
This is racy by design -- a slow probe firing after we return still
races -- so the doc steers users toward dev/, class/, and bind/
conditions for any service they control. Settle is for legacy boot
scripts and init transitions where condition wiring isn't feasible.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
dev/<X> only fires when a device gets a /dev node, which leaves a lot of
embedded-relevant hardware uncoverable: DSA switch cores, IIO sensors,
LEDs, backlight, PHYs, regulators -- all live purely under sysfs.
Two new condition namespaces:
class/<subsystem>/<sysname> asserted on every sysfs class device add
(e.g. <class/leds/blue>)
driver/<name> asserted while the driver is bound to at
least one device (e.g. <driver/mt7530>)
A driver can bind to several devices, so driver/ conditions are
refcounted: asserted on first bind, cleared when the last device is
unbound.
dev_cond() is generalized into a static cond_emit(prefix, rel, set) so
class_cond() and driver_cond() share the same mkpath + symlink/erase
code. The name avoids colliding with src/cond.h's public cond_path()
helper (unrelated function that returns a condition's filesystem path).
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When a rule references an absolute helper path (e.g. /lib/udev/fido_id,
/lib/udev/scsi_id) that the system does not ship and we have no matching
builtin either, return 1 from try_builtin_fallback() so the caller does
not fork /bin/sh on a binary that's known to be missing. Previously
each such uevent left a zombie 127 child for keventd's sigchld_cb to
reap -- harmless but noisy and wasteful at coldplug.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>