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>
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>
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>
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>
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>
keventd is the only thing in the tree that links libblkid, so a tree
that used to build now stops in configure with no hint of which package
to install. Say so where people look for dependencies, and give CI the
package it now needs.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
__msg_parse() turns bytes off a socket into pointers, before anything
has vouched for the peer, and it is the only place in libink that
does. It had no test of its own beyond whatever the other tests
happened to send it, all of it well-formed.
The target checks the parser's contract, not merely that it survived.
A header field must point into the header field array, and terminate
inside it, and the parse must never claim more bytes than it was
handed. Crash-only would pass a parser that walked into the body and
returned fields from there, since those bytes were handed over too.
The expected bounds are derived from the raw header rather than from
the parser, so the two have to agree independently.
Every input is copied into an allocation sized to it first. Reading
past the end of a roomy buffer stays inside the allocation and the
sanitizer never sees it; against an exact one the same read is a
fault, which is where the sharpest findings come from.
Under libFuzzer it is an ordinary fuzz target and named files replay,
which is how a find gets reproduced. With no arguments it runs a
fixed sweep -- every truncation, every single-byte corruption, every
value of the length that decides where the header ends, and seeded
garbage -- so the suite covers the same contract on every build,
without clang or a corpus in the tree. It takes 40 ms.
CI fuzzes it properly on every pull request, keeps the crashers, and
carries the corpus between runs so it reaches deeper over time than
any single run can. Note that clang links the fuzzer runtime against
the newest GCC tree it finds, so the libstdc++ headers have to match
that one and not the default compiler, which is worth saying since
installing the obvious package leaves you exactly where you started.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The other dbus-*.sh tests drive libink's own client, so the wire format
was only ever checked against the implementation that wrote it, and the
broker path had no coverage at all. Every bug found in it so far was
found by hand on a target.
Let the dbus plugin bring up a real dbus-daemon, wait for Finit to
claim org.finit, then talk to Finit with dbus-send, which shares no
code with us. The privileged call is the interesting one: it can only
be answered by parking the call and asking the broker who sent it.
The bus reads the policy Finit installs, so a malformed org.finit.conf
fails here rather than on a target.
Tests no longer build --with-libsystemd. Our replacement carries the
real soname but only the sd_notify() symbols, so in the test root it
shadowed the libsystemd the host's libdbus-1 wants and dbus-daemon
died on a missing sd_is_socket. Nothing under test needs the shared
library: serv is the only consumer and it compiles sd-daemon.c
straight in, which it now does regardless of the flag so notify.sh
keeps testing notify:systemd either way.
Staged from the host by lib/sysroot.mk like any other binary, and
skipped when the host has neither program.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
libink was written against the only bus it had, its own, where the
peer on the other end is the client. A broker is not: it routes for
senders it names itself, expects a DESTINATION on anything addressed
through it, and answers on its own schedule rather than next.
Runlevels go on the wire as S and N rather than the digits Finit
keeps internally, since that is what a caller outside Finit means by
one.
The library stays a convenience library, linked into finit and
initctl and installed nowhere: the ABI promise waits until libink is
its own project.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The summary table, the per-service detail, JSON and the quiet and
ident forms all read state Finit already publishes, so they read it
from the bus like everything else rather than through a second path
that has to be kept in step.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The workflows install libuev and libite from source and everything
else from apt, but never libconfuse, so every build job on this
branch dies in configure:
checking for libconfuse >= 3.3... no
Ubuntu ships libconfuse 3.3 with the static library included, which
covers both the static and regular builds. Staying on 3.3 in CI is
deliberate: it exercises the fallback paths marked
"XXX: Workaround for libConfuse <3.4" that a from-source 3.4 would
leave untested.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Finit 5.0 changes the .conf syntax, which has been essentially
unchanged since 1.x. The published docs track master, so when 5.x
lands, 4.x users lose their reference.
Publish the site under a per-major directory, /4.x/ for now, with
the Material version selector to switch between them. The selector
only needs mike's file layout -- a versions.json at the site root --
which the deploy job now generates from the version directories in
the pages repo, so mike itself is not needed.
The major comes from AC_INIT and the future 4.x maintenance branch
is already in the workflow triggers, so once 5.0 is on master, doc
fixes on the 4.x branch keep /4.x/ updated. A root index.html
redirects to the newest version, and a 404.html rewrites
pre-versioned deep links so old bookmarks and search hits land in
the right place.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
At least the sysvpart.sh regression test cannot run in parallel yet with
other tests (probably runparts.sh), so we must ensure the tests never
run in parallel, in particular at release.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
We now require readsnf() introduced in libite 2.6.0, with bug fixes
this effectively means v2.6.2.
The libuev bump is for 64-bit time_t, with bug fix => v2.4.1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Implement Linux capability support for services, allowing them to run
with minimal required privileges instead of running as root. This uses
the modern IAB (Inheritable, Ambient, Bounding) API from libcap.