Since Linux 2.6.4 the SOCK_SEQPACKET socket type is available for UNIX
domain sockets on Linux. It is intended for; "a sequenced-packet socket
that is connection-oriented, preserves message boundaries, and delivers
messages in the order that they were sent." which sounds like us.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The finalize() function is a bit too long, which means it may block the
API socket initctl (from the final runlevel switch at the beginning) use
to contact os via.
We should perhaps break it up even more, but at least once like this to
give the event loop a chance to interleave with an API callback.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
In particular this can happen from cgroup.c when multiple services map
to the same cgroup.events (due to being in the same cgroup)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When calling initctl early in the boot process, e.g. just when Finit is
switching to the final runlevel, it may take a few milliseconds for it
to actually be ready to process our request.
This patch adds poll() to both the write(REQ) and the read(RSP) steps
to prevent from getting weird errors when Finit is busy. The timeout
is currently 2 sec in both directions, which should be enough.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The bootmisc plugin creates lots of required system directories which
udev, and possibly also mdev, need to operate. E.g., a system which
has an empty tmpfs for /var need to populate that before we run.
The plugin loader handled this dependency implicitly before, loading all
plugins in alphabetical order. We should not rely on that for proper
operation.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This plugin should be able to start much earlier than on network UP,
it uses a UNIX domain socket to communicate so loopback should not be
needed.
Also, Finit supports runvels up to 9 (0 and 6 are special), so allow
dbus to run in all these runlevels. It is up to the user/OS to set
any policy for what runlevels to use.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
For commands like `initctl show foo`, initctl looks in the available/
subdirectory for `foo.conf`. This patch adds support for falling back
to return `/etc/finit.d/foo.conf` if the service doesn't exist in the
`/etc/finit.d/available/` subdirectory.
Static services, outside of the `enabled/` handling, live in the base
dirctory and this is what you expect from the tool. "Do what I mean"
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Older kernels (4.19) don't have the summary cpu.stat in the cgroup2
root, so let's ignore that problem and return zero.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
In debug mode it's highly confusing to see Finit load available/*.conf
files when you expect it to only load finit.conf and enabled/*.conf,
so let's keep the dangling symlink check to itself and actually load
and parse from enabled/ as it was intended :)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Sneaky bug, when switching between different sets of configurations, a
new instance of a previously removed svc can have its condition removed
by svc_gc() of the old instance. This patch prevents such accidents.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
More often than not, the file to write to in sysfs changes rather than
the value. This patch changes echo() into a fnwrite(), flipping what
is vsnprintf()'ed, and adds a stupid str() function that converts any
value (float/int/double/uint64_t) to a static string buffer.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The strlen() function can easiliy go out of bounds. Use memchr()
instead, we have the max buffer len as argument anyway.
Also fix call to sanitize() which used wrong length.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Replaces previous cgreaper.sh functionality for release notification and
cleanup of service groups.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Since the cgroups support in Finit is not yet officially released, we
decided to change the back-end to use cgroups v2 instead of the aging
and rather clumsy cgroups v1. Even this initial refactor is a lot
easier to read and understand, more can still be done since there's
a lot of concepts, data values and the ilk that can now be shared
between different controllers.
Still ToDo: inotify for cgroup.events to clean up leaf nodes, which
in cgroups v1 was handled by cgreaper.sh. This is fixed
in the next commit in the series.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Even systemd have collapsed a few of the cgroup controllers into a
semi-unified hierarchy and uses this approach. We just take it to
the extreme and have collapsed all of them (like cgroup v2).
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Two major bugs: `if (!cg)` and missing `strdup(path)`.
Also convert to use std hash table for lookup of previous cpu load value
for a given cgroup path. The hash table is sized after the current num.
rows on the screen -- resize currently not supported. The value given
to hcreate() should be 25% greater than the estimated num of entries,
but we take a wild guess just to make sure we don't run out of space at
runtime.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Fix obvious refactor mistake in cpu.shares assignment
- For unified memory hierarchy we need to set .use_hierarch=1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The ps command currently only lists processes in the three main control
groups: init, system, user. Kernel threads are not show at all.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
As of now, the default finit cgroup behavior is to use a unified
hierarchy of controllers under /sys/fs/cgroup/finit.
We mount cpu,cpuacct,cpuset,memory (if available) and gain the
ability to control our three major groups: init, system, user.
The default CPU share setup is ~10% for init and user, and 90% for
system. These are guaranteed CPU shares to ensure we do not starve
PID 1 or user processes. Support for configuring these limits will
be added in a later commit.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
With the new practise of keeping record of process pid files, we no
longer need to log/update when reading back the same PID we already
have on file.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The previous patch just added dynamic tracking of non-declared pid
files, so we no longer need to make stuff up.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Services that create their own PID files usually don't declare one with
Finit. This patch adds support to track those PID files anywayt at
runtime for the purpose of identifying match svc_t when a PID file is
removed, i.e. when a service exits.
- On IN_CREATE the pidfile.so plugin saves the pid file name in svc_t
- On ON_DELETE the pidfile.so plugin finds svc_t based on pid file
Quicker tracking and less dead code, win-win.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Transitioning to runlevel 0 or 6 handles graceful shutdown of any
managed run/task/sysv/services. So we can replace the old 2 sec delay
with a shorter one for any non-managed still lingering process.
Also, some minor cleanup.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
To aid with debugging, highlight if env file, binary, or both are the
missing component(s) and causing status 'missing'.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Protect against corner cases where pid conditions are not cleaned up.
We don't want such conditions to remain asserted when the process has
terminated.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When we try to start a service/run/task we call whichp() to see if the
binary exists, either tha absolute path given in the .conf file, or in
the $PATH we run with. If binary, or the env: file, doesn't exist we
now set svc_missing() state.
On `initctl reload` we unblock the service to be able to check again.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch fixes a few really hard problems wrt PID files:
1. Listening for IN_CREATE events means we get notified immediately by
the kernel when someone calls open()/fopen() on a PID file. Reading
the contents returns 0, thank you atoi() ... so we drop IN_CREATE
and instead look for IN_CLOSE_WRITE, there fixed it! Not quite ...
2. Some programs, like Zebra, and other Quagga/Frr daemons, don't
close() their PID files after creation. Instead they ftruncate()
and keep them open, and locked. Presumably to get a mechanism to
detect already running instances -- messes life up a bit for the
rest of us though. So we need to read files after IN_MODIFY too.
3. We also want to track IN_DELETE so we can deassert conditions when
services exit gracefully and clean up their PID files
The rest fo the commit is debug instrumentation changes.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
In 7447192 we dropped support for 'cond set' and 'cond clear' commands
with the motivation they were unsafe and sent the wrong message to the
user. That was true, but mostly because it was too generic and required
the user to call `initctl reload` to apply the changes.
This patch restores the behavior, albeit in a very reduced and simple
format. All conditions set with this command are constrained to the
'usr/...' namespace. No subdirectories are allowed. The argument to
the 'cond set|clear' command is disallowed if it contains '/' or '.'
but anything else is supported, for example:
initctl cond set foo:2
creates a static/oneshot condition in /run/finit/cond/usr/foo:2
These conditions are static and are fully handled by the user. The
initctl command is the recommended, and only supported, way of setting
and clearing usr conditions.
This patch also includes a new plugin, usr.so, which is a very simple
inotify plugin for the /run/finit/cond/usr/ directory. When files are
created or removed here the plugin tells the Finit condition engine to
update and trigger service changes.
For instance, the following service is not started by default at boot:
service <usr/foo> myservice -- MyService
However, as soon as `initctl cond set foo` is called, myservice starts.
Consequently, it is stopped when `initctl cond clr foo` is called.
Another major difference from the original is that this implementation
doesn't send IPC commands to create/delete the conditions. This makes
calling these new commands non-blocking so they can be used very early
in the bootstrap, by plugins, if needed.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Use _PATH_foo for all condition paths, *with* trailing /
- Read condition file first, may not exist, in which case we save time
- Change from libte makepath() to mkpath(), this changes from hard-coded
0777 perms on all cond dirs to 0755 -- possible security fix
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Provided a configuration that looks like this:
ospfd.conf:
service [2345] <!pid/zebra> log ospfd -A 127.0.0.1 -u root -g root -- OSPF daemon
zebra.conf:
service [2345] <!> log zebra -A 127.0.0.1 -u root -g root -- Zebra Routing daemon
If zebra.conf is changed, we restart it when `initctl reload` is issued.
This change ensures that ospfd is also restarted, because ospfd depends
on zebra, we must restart it too.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Check if ifname contains double periods, this should *not* be a valid
name, though eth0.10 is, et0..10 is not. Should protect better against
directory traversal attacks.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Fix ev->len validation; must check against sz read(), not total buffer
size. Also, fix off-by-one in comparison.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Fix ev->len validation; must check against sz read(), not total buffer
size. Also, fix off-by-one in comparison.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Fix ev->len validation; must check against sz read(), not total buffer
size. Also, fix off-by-one in comparison.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Check for spaces and slashes in interface name to prevent path based
attacks. Found by Coverity Scan.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>