We use it for more than just pipe() arrays. For example also for
socketpair(). Hence let's give it a generic name.
Also add EBADF_TRIPLET to mirror this for things like
stdin/stdout/stderr arrays, which we use a bunch of times.
This makes sure unit_watch_pid() and unit_unwatch_pid() will track
processes by pidfd if supported. Also ports over some related code.
Should not really change behaviour.
Note that this does *not* add support waiting for POLLIN on the pidfds
as additional exit notification. This is left for a later commit (this
commit is already large enough), in particular as that would add new
logic and not just convert existing logic.
New directive `NFTSet=` provides a method for integrating dynamic cgroup IDs
into firewall rules with NFT sets. The benefit of using this setting is to be
able to use control group as a selector in firewall rules easily and this in
turn allows more fine grained filtering. Also, NFT rules for cgroup matching
use numeric cgroup IDs, which change every time a service is restarted, making
them hard to use in systemd environment.
This option expects a whitespace separated list of NFT set definitions. Each
definition consists of a colon-separated tuple of source type (only "cgroup"),
NFT address family (one of "arp", "bridge", "inet", "ip", "ip6", or "netdev"),
table name and set name. The names of tables and sets must conform to lexical
restrictions of NFT table names. The type of the element used in the NFT filter
must be "cgroupsv2". When a control group for a unit is realized, the cgroup ID
will be appended to the NFT sets and it will be be removed when the control
group is removed. systemd only inserts elements to (or removes from) the sets,
so the related NFT rules, tables and sets must be prepared elsewhere in
advance. Failures to manage the sets will be ignored.
If the firewall rules are reinstalled so that the contents of NFT sets are
destroyed, command systemctl daemon-reload can be used to refill the sets.
Example:
```
table inet filter {
...
set timesyncd {
type cgroupsv2
}
chain ntp_output {
socket cgroupv2 != @timesyncd counter drop
accept
}
...
}
```
/etc/systemd/system/systemd-timesyncd.service.d/override.conf
```
[Service]
NFTSet=cgroup:inet:filter:timesyncd
```
```
$ sudo nft list set inet filter timesyncd
table inet filter {
set timesyncd {
type cgroupsv2
elements = { "system.slice/systemd-timesyncd.service" }
}
}
```
In the only two codepaths we reach this place we know that cfd is
already invalidated. In the Accept=yes case there's already a
TAKE_FD() a few lines further up, and in the Accept=no case there is no
connection fd anyway.
This ports over unit_main_pid() + unit_control_pid() to return PidRef*
pointers (which also means the underlying UnitVTable function pointers
are changed accordingly).
This then uses te functions to simplify the unit_kill() call, by
avoiding the kill() vtable indirection and instead just suing
unit_main_pid() and unit_control_pid() directly.
This adds a new "PollLimit" pair of settings to .socket units, very
similar to existing "TriggerLimit" logic. The differences are:
* PollLimit focusses on the polling on the sockets, and pauses that
temporarily if a ratelimit on that is reached. TriggerLimit otoh
focusses on the triggering effect of socket units, and stops
triggering once the ratelimit is hit.
* While the trigger limit being hit is an action that causes the socket
unit to fail the polling limit being reached will just temporarily
disable polling on the socket fd, and it is resumed once the ratelimit
interval is over.
* When a socket unit operates on multiple socket fds (e,g, ListenStream=
on both some ipv6 and an ipv4 address or so). Then the PollLimit will
be specific to each fd, while the trigger limit is specific to the
whole unit.
Implementation-wise this is mostly a wrapper around sd-event's
sd_event_source_set_ratelimit(), which exposes the desired behaviour
directly.
Usecase for all of this: socket services which when overloaded with
connections should just slow down reception of it, but not fail
persistently.
Let's stop manually destroying the timers when we fail to spawn a child.
We don't do this in any of the similar codepaths in any of the unit
types, only in two specific ones in socket/swap. Destroying the timer is
unnecessary, since this is done anyway in the _set_state() call of each
unit type if not appropriate, and every failure path here runs through
that anyway.
This brings all these similar codepaths into sync.
This adds a new structure UnitDefaults which embedds the various default
settings for units we maintain. We so far maintained two sets of
variables for this, one in main.c as static variables and one in the
Manager structure. This moves them into a common structure.
This is most just search/replace, i.e. very dumb refactoring.
The fact that we now use a common structure for this allows us further
refactorings later.
Inspired by the discussions on #27890
This is supposed to be a help for compilers to apply optimizations on
functions where they can't determine whether they are const/pure on
their own. For static, local functions the compiler can do this on its
own easily however, hence the decoration with pure/const is just noise.
Let's drop it, and let the compiler to its thing better.
(Use it for exported functions, since compilers can't 'reach-over' into
other modules to determine if they are pure, except if LTO is used)
Given that ERRNO_IS_DISCONNECT() also matches positive values,
make sure this macro is not called with arguments that do not have
errno semantics.
In this case the arguments passed to ERRNO_IS_DISCONNECT() are the
values returned by instance_from_socket(), socket_load_service_unit(),
and service_set_socket_fd() which are not expected to return any
positive values, but let's be consistent anyway and move
ERRNO_IS_DISCONNECT() invocations to the branches where the return
values are known to be negative.
As it says on the tin, configures the unit to survive a soft reboot.
Currently all the following options have to be set by hand:
Conflicts=reboot.target kexec.target poweroff.target halt.target
Before=reboot.target kexec.target poweroff.target halt.target
After=sysinit.target basic.target
DefaultDependencies=no
IgnoreOnIsolate=yes
This is not very user friendly. If new default dependencies are added,
or new shutdown/reboot types, they also have to be added manually.
The new option is much simpler, easy to find, and does the right thing
by default.
Given that ERRNO_IS_DISCONNECT() also matches positive values,
make sure this macro is not called with arguments that do not have
errno semantics.
In this case the argument passed to ERRNO_IS_DISCONNECT() is the value
returned by socket_acquire_peer() which can legitimately return 1
without errno semantics, so fix this by moving ERRNO_IS_DISCONNECT()
invocation to the branch where the return value is known to be negative.
This reverts commit e019ea738d.
In the new approach, a lock on /dev/console will be used. This lock will solve
the issue for services which run in early boot. Services which run later are
ordered after sysinit.target, so they'll run much later anyway so this
automatic dependency is not useful. Let's remove it again to make the code
simpler.
Apparently there are two µ symbols, accept both when parsing.
One is the greek small letter mu (μ) the other is the micro sign (µ).
Unicode recommendation considers both equivalent, and says use of greek
small letter mu is preferred. See:
https://www.unicode.org/reports/tr25
Hence accept both when parsing.
Inspired by: #28029
This is a rework of #24764 by Cristian Rodríguez
<crodriguez@owncloud.com>, which stalled.
Instead of assigning -1 we'll use a macro defined to INT_MAX however.
==1==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 17 byte(s) in 1 object(s) allocated from:
#0 0x7fc096c7243b in strdup (/lib64/libasan.so.8+0x7243b)
#1 0x7fc095db3899 in bus_socket_set_transient_property ../src/core/dbus-socket.c:386
#2 0x7fc095db5140 in bus_socket_set_property ../src/core/dbus-socket.c:460
#3 0x7fc095dd20f1 in bus_unit_set_properties ../src/core/dbus-unit.c:2473
#4 0x7fc095d87d53 in transient_unit_from_message ../src/core/dbus-manager.c:1025
#5 0x7fc095d8872f in method_start_transient_unit ../src/core/dbus-manager.c:1112
#6 0x7fc0944ddf4f in method_callbacks_run ../src/libsystemd/sd-bus/bus-objects.c:406
#7 0x7fc0944e7854 in object_find_and_run ../src/libsystemd/sd-bus/bus-objects.c:1319
#8 0x7fc0944e8f03 in bus_process_object ../src/libsystemd/sd-bus/bus-objects.c:1439
#9 0x7fc09454ad78 in process_message ../src/libsystemd/sd-bus/sd-bus.c:3011
#10 0x7fc09454b302 in process_running ../src/libsystemd/sd-bus/sd-bus.c:3053
#11 0x7fc09454e158 in bus_process_internal ../src/libsystemd/sd-bus/sd-bus.c:3273
#12 0x7fc09454e2f2 in sd_bus_process ../src/libsystemd/sd-bus/sd-bus.c:3300
#13 0x7fc094551a59 in io_callback ../src/libsystemd/sd-bus/sd-bus.c:3642
#14 0x7fc094727830 in source_dispatch ../src/libsystemd/sd-event/sd-event.c:4187
#15 0x7fc094731009 in sd_event_dispatch ../src/libsystemd/sd-event/sd-event.c:4808
#16 0x7fc094732124 in sd_event_run ../src/libsystemd/sd-event/sd-event.c:4869
#17 0x7fc095f7af9f in manager_loop ../src/core/manager.c:3242
#18 0x41cc7c in invoke_main_loop ../src/core/main.c:1937
#19 0x4252e0 in main ../src/core/main.c:3072
#20 0x7fc092a4a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)
SUMMARY: AddressSanitizer: 17 byte(s) leaked in 1 allocation(s).
The goal of this change is to delay getty services until after
systemd-vconsole-setup has finished. systemd-vconsole-setup starts loadkeys,
and it seems that when loadkeys is interrupted by the TTY hangup call we do
when starting tty services [1], so that loadkeys starts getting EIO from the
ioctl("/dev/tty1", KDSKBENT) syscall it does.
Fixes#26908.
[1] https://github.com/legionus/kbd/issues/92#issuecomment-1554451788
Initially I wanted to add ordering dependencies to individual units, but
TTYVHangup= can be added to other various external units too. The solution with
an implicit dependency should cover those cases too.
Let's be more accurate about what this function does: it checks whether
the underlying reported inode is the same. Internally, this already uses
a better named stat_inode_same() call, hence let's similarly name the
wrapping function following the same logic.
Similar for files_same_at() and path_equal_or_same_files().
No code changes, just some renaming.
Just to match service_release_stdio_fd() and service_release_fd_store()
in the name, since they do similar things.
This follows the concept that we "release" resources, and this is all
generically wrapped in "service_release_resources()".
When a service deactivates and is then automatically restarted via
Restart= we currently quickly transition through
SERVICE_DEAD/SERVICE_FAILED. Which is weird given it's not the
normal ("permanent") dead/failed state, but a transitory one we
immediately leave from again. We do this so that software that looks for
failures/successes can take notice, even if we restart as a consequence
of the deactivation.
Let's clean this up a bit: let's introduce two new states:
SERVICE_DEAD_BEFORE_AUTO_RESTART and SERVICE_FAILED_BEFORE_AUTO_RESTART
that are used for the transitory states. Both the SERVICE_DEAD and
SERVICE_DEAD_BEFORE_AUTO_RESTART will map to the high-level
UNIT_INACTIVE state though. (and similar for the respective failed
states). This means the high-level state machine won't change by this,
only the low-level one.
This clearly seperates the substates, which makes the state engine
cleaner, and allows clients to follow precisely whether we are in a
transitory dead/failed state, or a permanent one, by looking at the
service substate. Moreover it allows us to remove the 'n_keep_fd_store'
which so far we used to ensure the fdstore was not released during this
transitory dead/failed state but only during the permanent one. Since we
can now distinguish these states properly we can just use that.
This has been bugging me for a while. Let's clean this up.
Note that the unit restart logic is already nicely covered in the
testsiute, hence this adds no new tests for that.
And yes, this could be considered a compat break, but sofar we took the
liberty to make changes to the low-level state machine (i.e. SERVICE_xyz
states, sometimes called "substates") without considering this a bad
breakage – the high-level state machine (i.e. UNIT_xyz states) should
be considered API that cannot be changed.
Currently, exec runtimes can be shared between units (using
JoinsNamespaceOf=). Let's introduce a concept of a private exec
runtime that isn't shared with JoinsNamespaceOf=. The existing
ExecRuntime struct is renamed to ExecRuntimeShared and becomes a
private member of the new private ExecRuntime.