mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
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>
288 lines
10 KiB
Markdown
288 lines
10 KiB
Markdown
Building Finit
|
|
==============
|
|
|
|
Finit comes with a traditional configure script to control features and
|
|
optional plugins to enable. It depends on three external libraries:
|
|
|
|
- [libuEv][], the event loop
|
|
- [libite][] (-lite), much needed frog DNA
|
|
- [libConfuse][], the parser behind the .conf format
|
|
|
|
The bundled device manager, keventd, needs a fourth: libblkid from
|
|
[util-linux][]. It reads the filesystem UUID and label off block
|
|
devices, which is what the curated rules name the `/dev/disk/by-uuid/`
|
|
and `/dev/disk/by-label/` symlinks after. keventd is enabled by
|
|
default, so this is a hard requirement unless you build with
|
|
`--without-keventd`.
|
|
|
|
> [!IMPORTANT]
|
|
> Most free/open source software packages that use `configure` default
|
|
> to install to `/usr/local`. However, some Linux distributions do no
|
|
> longer search that path for installed software, e.g. Fedora and Alpine
|
|
> Linux. To get finit's configure script to find its dependencies you
|
|
> have to help the `pkg-config` tool a bit if you do not change the
|
|
> default prefix path:
|
|
>
|
|
> PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
|
|
|
The configure script checks for all dependencies, including the correct
|
|
version of the above mentioned libraries. Currently required versions:
|
|
|
|
- libite v2.2.0, or later
|
|
- libuEv v2.2.0, or later
|
|
- libConfuse v3.3, or later
|
|
- libblkid, any version, when keventd is enabled
|
|
|
|
|
|
Configure
|
|
---------
|
|
|
|
Below are a few of the main switches to configure:
|
|
|
|
* `--prefix=..`: Usually you want to set this to `/usr`, default is the GNU
|
|
default: `/usr/local`
|
|
|
|
* `--exec-prefix=..`: This you want to set to the empty string, or `/`, to
|
|
ensure the programs `finit` and `initctl` are installed to the proper
|
|
locations. Linux expects an "init" in `/sbin`, default: `--prefix`
|
|
|
|
* `--sysconfdir=..`: follows `--prefix`, you likely want it to be `/etc`
|
|
|
|
* `--localstatedir=..`: follows `--prefix`, you likely want `/var`
|
|
|
|
* `--enable-static`: Build Finit statically. The plugins will be
|
|
built-ins (.o files) and all external libraries, except the C library
|
|
will be linked statically.
|
|
|
|
* `--enable-kernel-cmdline`: Enable Finit pre-4.1 parsing of init args from
|
|
`/proc/cmdline`, this is *not recommended* since Finit may be running as the
|
|
init for container apps that can see the host's `/proc` filesystem
|
|
|
|
* `--disable-dbus`: Opt out of Finit's built-in D-Bus support, enabled by
|
|
default. See [D-Bus Integration](dbus.md) for what it provides. Not to
|
|
be confused with `--disable-dbus-plugin` below, which only governs
|
|
starting an external `dbus-daemon`
|
|
|
|
* `--enable-alsa-utils-plugin`: Enable the optional `alsa-utils.so` sound plugin.
|
|
|
|
* `--disable-dbus-plugin`: Drop the `dbus.so` plugin, which launches
|
|
`dbus-daemon` at boot. Enabled by default; the plugin does nothing on
|
|
a system that has no `dbus-daemon` installed, so opting out is only
|
|
needed to keep init from starting a bus on a system that has one.
|
|
Unrelated to the built-in bus, see `--disable-dbus` above.
|
|
|
|
* `--enable-resolvconf-plugin`: Enable the `resolvconf.so` optional plugin.
|
|
|
|
* `--enable-x11-common-plugin`: Enable the optional X Window `x11-common.so` plugin.
|
|
|
|
* `--without-keventd`: Drop the bundled device manager, for systems that
|
|
run mdev, mdevd, or udevd instead. Enabled by default, and the only
|
|
thing that pulls in libblkid. See [Bundled Device Manager](keventd.md).
|
|
|
|
* `--without-sulogin`: Drop the bundled `sulogin`, enabled by default,
|
|
and use the system `sulogin(8)` instead. The one shipped with Finit
|
|
*allows password-less* login if the `root` user is disabled or has no
|
|
password at all. `--with-sulogin=USER` prompts for another user's
|
|
password than `root`'s.
|
|
|
|
* `--without-watchdog`: Drop the bundled `watchdogd`, enabled by default
|
|
on `/dev/watchdog`, `--with-watchdog=DEV` selects another device.
|
|
Finit starts it when the device node exists, see [Watchdog](watchdog.md).
|
|
|
|
* `--with-libsystemd`: Build the replacement `libsystemd`, which lets
|
|
programs that use `sd_notify()` talk to Finit without systemd. Off by
|
|
default because it installs `libsystemd.so.0` in `$libdir`: on a host
|
|
that has the real one, ours shadows it in the loader cache and every
|
|
program linking it, `dbus-daemon` and `udevd` included, loses the
|
|
symbols it needs. Safe on a systemd-free system, which is the point
|
|
of it.
|
|
|
|
For more configure flags, see <kbd>./configure --help</kbd>
|
|
|
|
> [!NOTE]
|
|
> The configure script is not available in the GIT sources. It is
|
|
> however included in (officially supported) released tarballs. The
|
|
> idea is that you should not need GNU autotools to build, only the
|
|
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
|
> Any contributing to Finit can generate it from `configure.ac` using
|
|
> the `autogen.sh` script.
|
|
|
|
|
|
Example
|
|
-------
|
|
|
|
First, unpack the archive:
|
|
|
|
```shell
|
|
$ tar xf finit-4.3.tar.gz
|
|
$ cd finit-4.3/
|
|
```
|
|
|
|
Then configure, build and install:
|
|
|
|
```shell
|
|
$ ./configure --prefix=/usr --exec-prefix= \
|
|
--sysconfdir=/etc --localstatedir=/var
|
|
$ make
|
|
.
|
|
.
|
|
.
|
|
$ DESTDIR=/tmp/finit make install
|
|
```
|
|
|
|
In this example the [finit-4.3.tar.gz][1] archive is unpacked to the
|
|
user's home directory, configured, built and installed to a temporary
|
|
staging directory. The environment variable `DESTDIR` controls the
|
|
destination directory when installing, very useful for building binary
|
|
standalone packages.
|
|
|
|
Finit 4.1 and later can detect if it runs on an embedded system, or a
|
|
system that use BusyBox tools instead of udev & C:o. On such systems
|
|
`mdev` instead of `udev` is used. However, remember to also change the
|
|
Linux config to:
|
|
|
|
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
|
|
|
> [!TIP]
|
|
> If you run into problems starting Finit, take a look at `finit.c`.
|
|
> One of the most common problems is a custom Linux kernel build that
|
|
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
|
|
> `/etc/fstab`.
|
|
|
|
|
|
Testing
|
|
-------
|
|
|
|
`make check` runs the test suite in a private namespace, so it is safe
|
|
on a running system. It needs `unshare` and, on Ubuntu, unprivileged
|
|
user namespaces enabled:
|
|
|
|
```shell
|
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
make check
|
|
```
|
|
|
|
The D-Bus message parser is the only place in Finit where bytes off a
|
|
socket become pointers, so it also has a fuzz target. `make check`
|
|
runs it as a fixed sweep, which takes milliseconds and needs nothing
|
|
beyond the normal build. To fuzz it properly, build it with clang and
|
|
libFuzzer:
|
|
|
|
```shell
|
|
clang -fsanitize=fuzzer,address -DLINK_FUZZ_LIBFUZZER -D_GNU_SOURCE \
|
|
-I libink -I . -o fuzz-msg-parse \
|
|
test/src/fuzz-msg-parse.c libink/*.c
|
|
mkdir -p .fuzz-corpus
|
|
./fuzz-msg-parse .fuzz-corpus -max_total_time=300
|
|
```
|
|
|
|
Give it a corpus directory as above and it saves what it learns there,
|
|
so the next run picks up where this one left off instead of starting
|
|
cold. Nothing writes to it unless you name it: without the argument
|
|
libFuzzer keeps everything in memory and the run leaves only crashes
|
|
behind. `make distclean` clears the corpus and the target.
|
|
|
|
Once a corpus has grown, most of it reaches code some earlier input
|
|
already reached. Minimise it:
|
|
|
|
```shell
|
|
./fuzz-msg-parse -merge=1 .fuzz-corpus-min .fuzz-corpus
|
|
rm -rf .fuzz-corpus && mv .fuzz-corpus-min .fuzz-corpus
|
|
```
|
|
|
|
Run `./configure` first, the target needs the generated `config.h`.
|
|
If the link fails with `cannot find -lstdc++`, install the `libstdc++`
|
|
headers matching the newest GCC on the system, not the default one:
|
|
clang picks the newest tree it finds, and that is the one that needs
|
|
them. CI runs this target on every pull request, carrying its
|
|
corpus between runs so it reaches deeper over time.
|
|
|
|
Feed a file back to the target to reproduce a find:
|
|
|
|
```shell
|
|
./fuzz-msg-parse crash-3f2a...
|
|
```
|
|
|
|
|
|
Running
|
|
-------
|
|
|
|
Having successfully built Finit it is now be time to take it for a test
|
|
drive. The `make install` attempts to set up finit as the system system
|
|
init, `/sbin/init`, but this is usually a symlink pointing to the
|
|
current init.
|
|
|
|
So either change the symlink, or change your boot loader (GRUB, LOADLIN,
|
|
LILO, U-Boot/Barebox or RedBoot) configuration to append the following
|
|
to the kernel command line:
|
|
|
|
```shell
|
|
append="init=/sbin/finit"
|
|
```
|
|
|
|
Remember to also set up an initial `/etc/finit.conf` before rebooting!
|
|
|
|
|
|
Recovery
|
|
--------
|
|
|
|
To rescue a system with Finit, append the following to the kernel
|
|
command line:
|
|
|
|
```shell
|
|
append="init=/sbin/finit rescue"
|
|
```
|
|
|
|
This tells Finit to start in a very limited recovery mode, no services
|
|
are loaded, no filesystems are mounted or checked, and no networking is
|
|
enabled. The default Finit rescue mode configuration is installed into
|
|
`/lib/finit/rescue.conf`, which can be safely removed or changed.
|
|
|
|
By default the a root shell, without login, is started.
|
|
|
|
> [!IMPORTANT]
|
|
> In rescue mode `initctl` will not work, the same goes for `reboot`,
|
|
> `shutdown`, and `poweroff` commands, provided they are the Finit
|
|
> versions of these commands. Use the `-f` flag to force the action.
|
|
|
|
|
|
Debugging
|
|
---------
|
|
|
|
Edit, or append to, the kernel command line: remove `quiet` to enable
|
|
kernel messages and add `finit.debug` to enable Finit debug messages.
|
|
|
|
```shell
|
|
append="init=/sbin/finit -- finit.debug"
|
|
```
|
|
|
|
Notice the `--` separator.
|
|
|
|
To debug startup issues, in particular issues with getty/login, add
|
|
the following to your Finit .conf file:
|
|
|
|
tty board {
|
|
runlevel = "12345789"
|
|
notty = true
|
|
noclear = true
|
|
}
|
|
|
|
The `notty` option ensures reusing the stdin/stdout set up by the
|
|
kernel. Remember, this is only for debugging and would leave your
|
|
production system potentially wide open.
|
|
|
|
There is also a rescue shell available, in case Finit crashes and the
|
|
kernel usually reboots: `configure --enable-emergency-shell`. However,
|
|
the behavior of Finit is severely limited when this is enabled, so use
|
|
it only for debugging start up issues when Finit crashes.
|
|
|
|
> [!CAUTION]
|
|
> None of these options should be enabled on production systems since
|
|
> they can potentially give a user root access.
|
|
|
|
[1]: https://github.com/finit-project/finit/releases/download/4.3/finit-4.3.tar.gz
|
|
[libuEv]: https://github.com/troglobit/libuev
|
|
[libite]: https://github.com/troglobit/libite
|
|
[libConfuse]: https://github.com/libconfuse/libconfuse
|
|
[util-linux]: https://github.com/util-linux/util-linux
|