This patch is a refactor of the prototype sys condition plugin. It
moves most of the logic to monitor kernel events into a keventd that,
currently only, sets and clears the sys/pwr/ac condition. The sys
plugin itself is now only a monitor of conditions and ensures Finit
follows them. This is a lot more secure and moves (at least one piece
of) netlink processing out from PID 1.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The udevd, dbus, bundled watchdog, and others were started without a
valid cgroup. This is a workaround to ensure they are assigned one.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Handle EAGAIN properly, for both regular and resync flow, on any error
in the regular flow (unless ENOBUFS) we want to check for nl_ifdown on
any of the successfully parsed messages.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch adds support for calling recv() repeatedly to get the netlink
response from the kernel. As a result, the recv() buffer can be reduced
down to 4k again.
Both the regular flow and the resync flow now follow the exact same code
path, except for the ENOBUFS handling. If we get ENOBUFS in resync, we
are screwed anyway.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
For RTM_GETLINK we need a `struct ifinfomsg`, not `struct rtmsg`,
otherwise the kernel will get 8 extra bytes and complain about it.
This patch makes sure to set the correct iface change mask as well, and
increases the debug logs a bit to get a fix on sizes used. We increase
the recv() buffer 8k -> 64k to make sure we can get all data in one big
swoop. Plan is to refactor this mess in a later commit.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This is a major redesign of the netlink plugin to be able to handle
ENOBUFS¹ properly. Pending verification, this change replaces the patch
to increase socket buffer size, which in real life turned out to be
insufficient.
When nl_callback() calls recv() and it fails with ENOBUFS, we consider
our cache of the kernel state invalid and thus:
1. deassert all net/ conditions
2. open a new (temporary) netlink socket
3. send RTM_GETLINK and re-assert all interfaces using nl_link()
4. send RTM_GETROUTE and re-assert all routes with nl_route()
Like before, the kernel will not send us a RTM_DELROUTE when it removes
the default route, so we still have to track this ourselves. This patch
also refactors that functionality to only resync routes when the ifindex
associated previosly with the default route goes down or is removed.
The previous change that added nl_default() to recheck, has been dropped
to instead reuse the standard nl_route() callback.
___
¹ see netlink(7) for details.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch fixes the problem with Linux not sending netlink route change
notifications when interfaces for these routes goes down. When an iface
goes down we now send a route request to the kernel and check the return
message, if no default route is found we deassert net/default/route.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Coverity suggests validating against only a set of known characters.
However, the kernel allows just about all characters in an interface
name. This version of valdiate_ifname() is blatantly stolen, more
or less, from linux/net/core/dev.c
https://code.woboq.org/linux/linux/net/core/dev.c.html#1020
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
These plugins should not run in rescue mode, because the system may be
in a very bad state and we do not want to make the situation any worse
than it already is.
Essentially, only services in rescue.conf should run in rescue mode.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
If we get a notification and the service dies immediately, and also
removes its pid file, we need to take corrective action.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Before this patch bootclean() ran first in setup() which caused to to
remove the entire /var/run/finit directory, and other files as well,
created earlier. Only possible fix is to split clean and setup in
two and make sure to call clean as soon as we've mounted everything.
Note: this introduces a new behavior, and anyone hooking into the
same point to do good-stuff(tm) may be affected by this.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Initial refactor of the tty implementation to use the service/run/task
general backend. This enables all the features of services also for
ttys, except logging because it makes no sense.
Work in progress:
- plugins/tty.c does not work anymore, could possibly be removed in
favor of usinga (a new) condition instead (if-tty-exists)
- fallback tty does not work anymore, should we remove it, or can we
handle it as an optional built-in with (a new) condition?
- @console does not work anymore, needs to generate N cloned services
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Since the introduction of the iwatch framework we can now safely free
the memory allocated by realpath() and prevent leaks in a more elegant
way than before.
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>
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>
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>
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>
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>
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>
This is a major refactor to use the same construct as in the pidfile.so
plugin to parse kernel inotify events for when TTYs are added removed
from the system.
Found by Coverity Scan.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>