The kernel sometimes sends uevents in a random order, so previously the
received events were not sorted by their seqnum. We determine which
event is ready for processing by using the assumption that queued events
are sorted by their seqnum. Let's sort the received events before queue
them, to make events processed in a correct ordering.
If DefaultDependencies=no, /var/ may not be mounted yet when the service
is being started. Previously, In such case, if the service has
PrivateTmp=disconnected, the service manager created /var/tmp/ on the
root filesystem and mounted the disconnected private tmpfs there. That
poluted the root filesystem and disturbed gpt-auto-generator on next
boot, as /var/ would not be empty anymore. See issue #37258.
This changes PrivateTmp=disconnected as the following:
- If DefaultDependencies=no and RootDirectory=/RootImage= are not set,
then a private tmpfs is mounted _only_ on /tmp/, and set $TMPDIR=/tmp
environment variable to suggest the service to use /tmp/.
- If DefaultDependencies=yes and RootDirectory=/RootImage= are not set,
then implies RequiresMountsFor=/var/, though that is typically
redundant, but anyway. Hence, we can safely mount /var/tmp/.
- Otherwise, i.e. when one of RootDirectory=/RootImage= is set, behaves
as the same as the previous, as the private root filesystem for the
service is explicitly prepared by the service manager, and we can
safely mount a private tmpfs on /var/tmp/ without any extra
dependencies.
Fixes#37258.
Co-authored-by: Mike Yuan <me@yhndnzj.com>
When the unit is new, then mount_setup_new_unit() adds the unit to the
load queue, and the same dependencies will be anyway added.
When the unit already exists but previously failed to be loaded, then
mount_setup_existing_unit() also adds the unit to the load queue.
Hence it is not necessary to regenerate dependencies here now.
So, we need to regenerate dependencies only when things changed and
the unit has been already loaded.
No functional changes, just optimization.
Unfortunately, the kernel may send events in a random order:
```
[ 25.769624] systemd-udevd[194]: sdi7: Device is queued (SEQNUM=2843, ACTION=add)
[ 25.769893] systemd-udevd[194]: sda5: Device is queued (SEQNUM=2842, ACTION=add)
[ 25.770517] systemd-udevd[194]: sdi8: Device is queued (SEQNUM=2844, ACTION=add)
```
As you can see, udevd receives the event with SEQNUM=2843 earlier than
one with SEQNUM=2842.
Let's make queued events sorted, as our logic of determining which event
is ready for being processed assumes that queued events are sorted.
See event_build_dependencies().
Also, refuse to queue an event if another event with the same seqnum is
already queued.
Previously, when an event for block device is queued or an inotify event
for a block device is triggered, all queued events were checked by
event_queue_assume_block_device_unlocked(), and its cost may be huge
on early boot stage.
This makes locked events are managed in separated prioq and hashmap,
to reduce the cost of event_queue_assume_block_device_unlocked(),
which is now renamed to manager_requeue_locked_events_by_device().
This also changes the clockid of timer events for requeueing and
timeout of retry from CLOCK_BOOTTIME to CLOCK_MONOTONIC. Otherwise,
if the system suspend while an event is locked, the event may be
requeued immediately after come back from the suspend and timed out.
The timeout event sources are enabled only when the event is being
processed by a worker, hence they are not necessary to be owned by the
event.
No effective functional change, just refactoring.
Note, BPF_PROG_TYPE_CGROUP_DEVICE is supported since kernel v4.15.
As our baseline on the kernel is v5.4, we can assume the bpf type is
always supported.
Note, BPF_PROG_TYPE_CGROUP_SKB is supported since kernel v4.10, and
BPF_F_ALLOW_MULTI and program name is supported since kernel v4.15.
As our baseline on the kernel is v5.4, we can assume that the type,
flag, and naming is supported when bpf_program_supported() succeeds.
BPF_PROG_TYPE_CGROUP_SKB is supported since kernel v4.10
(0e33661de493db325435d565a4a722120ae4cbf3) and
BPF_PROG_TYPE_CGROUP_SOCK_ADDR is supported since kernel v4.17
(4fbac77d2d092b475dda9eea66da674369665427).
Our baseline on the kernel is v5.4. The check is not necessary.
After 3988e2489a, the function is a simple
wrapper of bpf_dlopen() with logging. Let's introduce dlopen_bpf_full()
that takes log level, and replace cgroup_bpf_supported() with it.
When the flag is set, even if the specified UID/GID does not exist,
create a synthetic user record for the UID/GID.
Currently, only system UID/GID are supported.
Follow-up for 940441b44c.
With the commit, User=/Group=root was refused and warned that the root
is not a system user. Typically it is not necessary to specify such, but
let's not log confusing warning and honor the setting.
The buffer will be used by a library outside of our code base,
and may not be initialized even on success. Let's initialize
them for safety.
Hopefully fixes the following fuzzer warning:
```
==2039==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7f9ad8be3ae6 in _nss_files_getsgnam_r (/lib/x86_64-linux-gnu/libnss_files.so.2+0x8ae6) (BuildId: 013bf05b4846ebbdbebdb05585acc9726c2fabce)
#1 0x7f9ad93e5902 in getsgnam_r (/lib/x86_64-linux-gnu/libc.so.6+0x126902) (BuildId: 0323ab4806bee6f846d9ad4bccfc29afdca49a58)
#2 0x7f9ad9b98153 in nss_sgrp_for_group /work/build/../../src/systemd/src/shared/user-record-nss.c:357:21
#3 0x7f9ad9b98926 in nss_group_record_by_gid /work/build/../../src/systemd/src/shared/user-record-nss.c:431:21
#4 0x7f9ad9bcebd7 in groupdb_by_gid_fallbacks /work/build/../../src/systemd/src/shared/userdb.c:1372:29
Uninitialized value was created by a heap allocation
#0 0x556fd5294302 in malloc /src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:1021:3
#1 0x7f9ad9b9811d in nss_sgrp_for_group /work/build/../../src/systemd/src/shared/user-record-nss.c:353:23
#2 0x7f9ad9b98926 in nss_group_record_by_gid /work/build/../../src/systemd/src/shared/user-record-nss.c:431:21
#3 0x7f9ad9bcebd7 in groupdb_by_gid_fallbacks /work/build/../../src/systemd/src/shared/userdb.c:1372:29
```
Otherwise, initrd-cleanup.service requests isolation thus the socket
is stopped before switching root, and several early events after
switching root may be lost.
Continuation of #36734
Apparently I was wrong about everything under `/proc/` being seq_file,
but at least there're some more to convert and we can leverage our
helper func while doing so.
Currently, if systemd-networkd-wait-online is started with --dns, and
systemd-resolved is not running, it will exit with an error right away.
Similarly, if systemd-resolved is restarted while waiting for DNS
configuration, systemd-networkd-wait-online will not attempt to
re-connect, and will potentially never see subsequent DNS
configurations.
Improve this by adding socket units for the systemd-resolved varlink
servers, and re-establish the connection in systemd-networkd-wait-online
when we receive `SD_VARLINK_ERROR_DISCONNECTED`.
A host can send Router Advertisements (RAs) without acting as a router.
In such cases, the lifetime of the RA header should be zero, but may
contain several options, and clients can configure addresses, routes,
and so on with the message. The host may (should?) send Neighbor
Announcements (NAs) without the router flag in that case.
So, when a NA without the router flag is received, let's not drop
configurations based on the previous RA options, but only drop the
default gateway configured based on the RA header.
See RFC 4861 Neighbor Discovery in IPv6, section 6.3.4:
https://www.rfc-editor.org/rfc/rfc4861#section-6.3.4:~:text=%2D%20The%20IsRouter%20flag,as%20a%20host.
> - The IsRouter flag in the cache entry MUST be set based on the Router
> flag in the received advertisement. In those cases where the IsRouter
> flag changes from TRUE to FALSE as a result of this update, the node
> MUST remove that router from the Default Router List and update the
> Destination Cache entries for all destinations using that neighbor as
> a router as specified in Section 7.3.3. This is needed to detect when
> a node that is used as a router stops forwarding packets due to being
> configured as a host.
Fixes a regression caused by 87a33c0740 (v256).
Fixes#37198.
This is analogous to #36123, but for Tun/Tap interfaces created by
systemd-networkd.
If a regular user account want to control a Tun/Tap interface, then
assign the interface to a system group, e.g., vpn, and add the user
to the group.
Closes#37279.
and ignore the settings if we cannot find the specified user/group.
This also replaces get_user_creds()/get_group_creds() with
userdb_by_name()/groupdb_by_name().
When a [SR-IOV] section has no setting, e.g.
```ini
[SR-IOV]
VirtualFunction=0
```
then the kernel previously replied -EINVAL, as we send a rtnl message
with an empty IFLA_VF_INFO container.
See See do_setvfinfo() in net/core/rtnetlink.c of the kernel.
When a [SR-IOV] section that has an unsupported settings by the
interface driver, then previously the kernel partially applied
settings and returned -EOPNOTSUPP. E.f.
```ini
[SR-IOV]
VirtualFunction=0
LinkState=auto
Trust=true
MACAddress=02:01:00:3e:61:34
```
and the interface does not support configuring the link state, then
the MAC address is assigned, but the trust is not applied:
```
enp3s0f0: Failed to configure SR-IOV virtual function 0, ignoring: Operation not supported
vf 0 link/ether 02:01:00:3e:61:34 brd ff:ff:ff:ff:ff:ff, spoof checking on, link-state auto, trust off
```
To fix such issues, this makes networkd/udevd send each attribute
for VF one-by-one.
Fixes#37257 and #37275.
The configuration can easily fail when the target virtual function
does not exist, and there is nothing networkd can do in such case.
Also, it is overkill to make the physical interface entered to the
failed state in such case. Let's warn but ignore the failure.
The header requires struct sockaddr declared. So, otherwise, we need to
include sys/socket.h earlier than linux/vm_sockets.h.
Let's make the header includable at any place.
Follow-up for 511619087b.
Notable changes are
- SIGTERM is the highest among others, to make not udevd queue too
many events, as we need to serialize them anyway.
- device monitor has the second highest priority, to make 'remove'
uevents received earlier than IN_IGNORED inotify events. Otherwise,
after IN_IGNORED is received, if there is no queued event,
/run/udev/queue file will be removed by the post-event source of the
inotify event, and 'udevadm settle' or friends may wrongly finish,
even we will soon queue 'remove' uevents for the device.
This change should fix the recent instability of TEST-64-UDEV-STORAGE.
For other changes, see the comments in the code.
Note, it should be safe even if we synthesize no event, e.g. when the
device has been already removed. In such case, the post event after
SIGCHLD will remove the file.
This is mostly a paranoia, but if we failed to create /run/udev/queue
for some reasons on queueing an event, previously we would never create
the file until once the queue became empty. This makes in such case we
try to create the file again when queueing the next event.
RFC 5227 specifies randomized intervals to avoid that a large number of
hosts powered up at the same time send their message simultaneously.
Performing the conflict detection takes a variable time between 4 and 7
seconds from the beginning to the first announcement, as shown by the
following diagram where P indicates a probe and A an announcement:
```
time(s) 0 1 2 3 4 5 6 7 8 9
+---+---+---+---+---+---+---+---+---+
SHORTEST P P P A A
LONGEST P P P A A
```
The host can't use the address until the first announcement is sent. 7
seconds is a very long time on modern computers especially considering
the fact that the round-trip time on current LAN technologies is at most
few milliseconds. Section 2.2 of the RFC addresses this matter and hints
that a future standard will adjust those timeouts; however that standard
doesn't exist yet.
Make the timeout configurable via a new
"IPv4DuplicateAddressDetectionTimeoutSec=" option. The intervals defined
in the RFC are then scaled proportionally so that the duration of the
conflict detection takes at most the given value. Interval happening
after the first announcement are not scaled, as recommended by the RFC.
Also reduce the default value from 7s to 200ms, which is a more suitable
value for today's technology.