Strings like command, description, and environment may contain characters
that need escaping for valid JSON, e.g., embedded quotes in command line
arguments like -V "NanoPi R2S".
Add json_escape() helper to handle quotes, backslashes, and control chars.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When a TTY exited with non-zero code (e.g., user with shell=/sbin/false),
it would enter restart state but never recover, requiring manual restart.
The throttling logic from commit f0032ab had two issues:
1. Duplicate exit code check in service_retry() created infinite timer loop
2. TTYs lacked default restart_tmo, causing timer to never start
Fix by removing duplicate check and ensuring TTYs get a 2-second default
restart_tmo for proper throttling.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When a service is configured to run as a non-root user (@user), finit
correctly drops privileges via setuid() and sets HOME and PATH, but
does not set the USER and LOGNAME environment variables. They remain
set to "root" from boot time.
This causes problems for software that determines its identity from
the environment rather than getuid(). For example, rootless Podman
checks os.Getenv("USER") first when looking up subordinate UID/GID
ranges in /etc/subuid and /etc/subgid.
With USER=root but UID=1000, Podman looks up root's subuid entry
instead of the actual user's, causing applications like newuidmap
to fail. Setting USER and LOGNAME to match the actual user identity
follows POSIX conventions and matches the behavior of su, sudo, and
login.
The do_ prefix is conventionally reserved for local helper functions.
Move switch_root() declaration to private.h alongside iterate_proc()
and remove the now-empty initramfs.h header.
in an initramfs, then transition to the real root filesystem. Useful
for systems requiring early boot tasks like LUKS unlock, LVM activation,
or network boot before mounting the real root.
Adds INIT_CMD_SWITCH_ROOT API command, `initctl switch-root` subcommand,
and HOOK_SWITCH_ROOT plugin hook point. The implementation gracefully
stops services, moves virtual filesystems (/dev, /proc, /sys, /run) to
the new root, deletes initramfs contents to free memory, then execs the
new init as PID 1.
See GitHub Discussion #292 for background.
Add handling for EBUSY when mounting cgroup2 filesystem, which occurs
when cgroups are already mounted. This can happen after switch_root
when cgroups were moved from the initramfs, or in container environments.
Verify the existing mount is actually cgroup2 before proceeding, and
track whether we mounted to avoid unmounting on error if we didn't.
Finit has support for "Please press Enter to activate this console."
which means there's no getty yet running. However, when profiling
systems with Finit, and embedded systems in general, a common metric
is the time from power-on to getty has started.
This commit makes sure to rename the process so that BusyBox pidof is
capable of detecting that "getty" has started. This is mostly for the
bootchart2 project's bootchartd, the native BusyBox bootchartd does not
have this issue.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This is a refactor of getuser() and getgroup() so that they always
return a valid user, and group, for all normal use-cases. When an
error occurs we now handle it properly in service_fork() so as to
not attempt to start services with an invalid user/group setting
as root.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When running Finit under boothcartd (bootchart2 project) the PATH is
lost due to a bug. This was a wakeup, so set critical variables in
main() early, before calling fs_init().
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
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>
During /bin/login phase the TTY device node is chowned and chmodded to
the authenticated user. It will remain in this state until the next
call to getty.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
A user reports inability to re-start getty on the console after logging
out from a serial console. After some digging it was found that the tty
was owned by the last user logged in and 600. Even thougn getty runs as
root, it did not have permission to re-open the device node.
Turns out there was a minor bug in the new capability code that cleared
all capabilities from the root user. A surprising amount of programs
worked just fine, but restarting getty gave it away.
The fix is to only call cap_setuid() when capabilities are set for the
service, otherwise we just fall back to setuid().
Also, refactor service_register() wrt. capabilities a bit so that we can
give users an early warning if the configuration is invalid, by adding a
parse_caps() helper function that calls cap_iab_from_text() to verify.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Implement supplementary group support for services, allowing them to
access resources owned by multiple groups. Uses the @user:group,sup1,sup2
syntax to explicitly specify supplementary groups, in addition to now
reading group membership from /etc/group.
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>
Comment-out code that makes the cursor "jump" around at boot before
displaying: Please press Enter to activate this console.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Fixes an issue where the mouse scroll wheel and Shift+PgUp/PgDn
sometimes would not work properly after login.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Drop clear screen to fix flickering in 'initctl top' output. Also, make
sure to not garble the display if the the terminal is too small.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This should not be needed, but for some reason we don't get events when
early processes exit, so we end up with lingering cgroups.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The container monitor that podman forks off when starting a container
instance creates subgroups in the cgroup v2 hieararchy that we want to
reuse. This patch adds cgroup_move_svc() which we call from the pidfile
plugins to relocate the conmon process.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit activates the use of clone3() for service_fork(), to allow
Linux to create the new process directly in the correct cgroup instead
of later moving it there -- much cheaper and less error prone.
To facilitate this a few new helper cgroup functions have been added and
two new configuration directives introduced: delegate and name:leafname.
The delegate option is for running, e.g., container runtimes that want
to create their own cgroup v2 structur, and the name:leafname allows a
user to change the name of the subgroup under user/system/init.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The PTY approach caused isatty() to return true for services using
the log directive, triggering programs like fprintd (using glib) to
emit ANSI escape codes and other TTY-specific formatting in syslog.
Using a standard pipe ensures isatty() correctly returns false, so
programs produce plain text output suitable for logging.
For services that require line-buffered output, users can wrap the
command with `stdbuf -oL` as documented in doc/config/logging.md.
Fixes#455
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When setting up a new system with Finit it is very common to make small
logical mistakes that cause "hangs" at boot. This is when Finit waits
for 180 sec. for run/tasks to complete before moving to the configured
runlevel. This patch adds console input monitoring during bootstrap
wait that allows users to press Ctrl-C to skip waiting and proceed to
the configured runlevel.
When Ctrl-C is detected, all incomplete run/task/services are logged
to syslog for later troubleshooting after login.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Relax the constraints introduced in a39ee0b, for issue #342, a bit on
when start/stop/restart/reload service can be called. Also, allow
'initctl reload', but ignore it when the system is in runlevels S/0/6.
This makes it possible to start manual:yes type services at botostrap,
for example, which has been a common feature request.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add missing memory information to JSON output in json_status_one().
The memory field shows cgroup memory usage in bytes when cgroup
support is available and the service has a valid PID, matching
the behavior of the text status output.
Signed-off-by: Richard Alpe <richard@bit42.se>
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.
Allow service IDs up to 64 characters to support SHA-256 hashes,
UUIDs, and other long unique identifiers. This increases memory
usage by ~98 bytes per service instance, which is negligible for
typical deployments.
The IDENT column width in initctl output adapts dynamically based
on actual ID lengths in use, so short IDs remain unaffected.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Both service and sysv stanzas support a cleanup:script (since v4.10), with an
optional timeout. These timers must be stopped when collecting a PID for an
svc_t, or when unregistering an svc_t, otherwise the timer callback will be
continuously called, reporting "spurious problem", and cause 100% CPU usage.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch fixes an ordering issue where the configuration generation is
stepped before all old/disabled services had been stopped. Finit should
ensure disabled services are stopped before entering the next generation.
If the genation is stepped first, all conditions are put in "flux" state,
so, e.g, a podman container running as a sysv service may lock-up until
it is killed by Finit. Found in the Infix OS project.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>