Of course, this should never happen, but let's better be safe than
sorry, and abort rather than continue when a too large memory block is
allocated, simply asa safety precaution.
An early abort is better than continuing with a likely memory corruption
later.
The problem was introduced in a37422045f:
we have a unit which has a fragment, and when we'd update it based on
/proc/self/mountinfo, we'd say that e.g. What=/dev/loop8 has origin-fragment.
This commit changes two things:
- origin-fragment is changed to origin-mountinfo-implicit
- when we stop a unit, mountinfo information is flushed and all deps based
on it are dropped.
The second step is important, because when we restart the unit, we want to
notice that we have "fresh" mountinfo information. We could keep the old info
around and solve this in a different way, but keeping stale information seems
inelegant.
Fixes#11342.
In normal use, this allow us to drop dead entries from the cache and reduces
the cache size so that we don't evict entries unnecessarily. The time limit is
there mostly to serve as a guard against malicious logging from many different
PIDs.
This is far from perfect, but should give mostly reasonable values. My
assumption is that if somebody has a few hundred MB of memory, they are
unlikely to have thousands of processes logging. A hundred would already be a
lot. So let's scale the cache size propritionally to the total memory size,
with clamping on both ends.
The formula gives 64 cache entries for each GB of RAM.
First of all let's always log where the errors happen, and not in an
upper stackframe, in all cases. Previously we'd do this somethis one way
and sometimes another, which resulted in sometimes duplicate logging and
sometimes none.
When we cannot activate something due to bad password the kernel gives
us EPERM. Let's uniformly return this EAGAIN, so tha the next password
is tried. (previously this was done in most cases but not in all)
When we get EPERM let's also explicitly indicate that this probably
means the password is simply wrong.
Fixes: #11498
When sd_device_enumerator_add_match_parent() is called
multiple times, then previously set parents are discarded.
This adds device_enumerator_add_match_parent_incremental() to make
sd-device-enumerator scan devices under all specified parents.
Note that for backward compatibility, sd_device_enumerator_add_match_parent()
and udev_enumerate_add_match_parent() still discard previous assignments.
procfs_memory_get_current is renamed to procfs_memory_get_used, because
"current" can mean anything, including total memory, used memory, and free
memory, as long as the value is up to date.
No functional change.
Previously, device_copy_properties() copies all properties to both
sd_device::properties and ::properties_db. Thus, on move uevent,
also tentative properties, e.g. DEVPATH or INTERFACE, are stored to
::properties_db, and saved to udev database.
This makes such tentative properties be copied to only ::properties,
and thus not saved to udev database.
Fixes#9426.
Fixes#3374. The problem is that we set MACPolicy=persistent (i.e. we would
like to generate persistent MAC addresses for interfaces which don't have a
fixed MAC address), but various virtual interfaces including bridges, tun/tap,
bonds, etc., do not not have the necessary ID_NET_NAME_* attributes and udev
would not assing the address and warn:
Could not generate persistent MAC address for $name: No such file or directory
Basic requirements which I think a solution for this needs to satisfy:
1. No changes to MAC address generation for those cases which are currently
handled successfully. This means that net_get_unique_predictable_data() must
keep returning the same answer, which in turn means net_get_name() must keep
returning the same answer. We can only add more things we look at with lower
priority so that we start to cover cases which were not covered before.
2. Like 1, but for IPvLL seed and DHCP IAD. This is less important, but "nice
to have".
3. Keep MACPolicy=persistent. If people don't want it, they can always apply
local configuration, but in general stable MACs are a good thing. I have never
seen anyone complain about that.
== Various approaches that have been proposed
=== https://github.com/systemd/systemd/issues/3374#issuecomment-223753264 (tomty89)
if !ID_BUS and INTERFACE, use INTERFACE
I think this almost does the good thing, but I don't see the reason to reject ID_BUS
(i.e. physical hardware). Stable MACs are very useful for physical hardware that has
no physical MAC.
=== https://github.com/systemd/systemd/issues/3374#issuecomment-224733069 (teg)
if (should_rename(device, true))
This means looking at name_assign_type. In particular for
NET_NAME_USER should_rename(..., true) returns true. It only returns false
for NET_NAME_PREDICTABLE. So this would cover stuff like br0, bond0, etc,
but would not cover lo and other devices with predictable names. That doesn't
make much sense.
But did teg mean should_rename() or !should_rename()?
=== https://github.com/systemd/systemd/issues/3374#issuecomment-234628502 (tomty89):
+ if (!should_rename(device, true))
+ return udev_device_get_sysname(device)
This covers only devices with NET_NAME_PREDICTABLE. Since the problem applies as
much to bridges and such, this isn't neough.
=== https://github.com/systemd/systemd/issues/3374#issuecomment-281745967 (grafi-tt)
+ /* if the machine doesn't provide data about the device, use the ifname specified by userspace
+ * (this is the case when the device is virtual, e.g., bridge or bond) */
+ s = udev_device_get_sysattr_value(device, "name_assign_type");
+ if (s && safe_atou(s, &type) >= 0 && type == NET_NAME_USER)
+ return udev_device_get_sysname(device);
This does not cover bond0, vnet0, tun/tap and similar.
grafi-tt also proposes patching the kernel, but *not* setting name_assign_type
seems intentional in those cases, because the device name is a result of
enumeration, not set by the userspace.
=== https://github.com/systemd/systemd/issues/3374#issuecomment-288882355 (tomty89)
(also PR #11372)
- MACAddressPolicy=persistent
This break requirement 3. above. It would solve the immediate problem, but I
think the disruption is too big.
=== This patch
This patch means that we will set a "stable" MAC for pretty much any virtual
device by default, where "stable" means keyed off the machine-id and interface
name.
It seems like a big change, but we already did this for most physical devices.
Doing it also for virtual devices doesn't seem like a big issue. It will make
the setup and monitoring of virtualized networks slightly nicer. I don't think
anyone is depending on having the MAC address changed when those devices are
destoryed and recreated. If they do, they'd have to change MACAddressPolicy=.
== Implementation
net_get_name() is called from dhcp_ident_set_iaid() so I didn't change
net_get_name() like in grafi-tt's patch, but net_get_unique_predictable_data().
net_get_unique_predictable_data() is called from get_mac() in link-config.c
and sd_ipv4ll_set_address_seed(), so both of those code paths are affected
and will now get data in some cases where they errored out previously.
The return code is changed to -ENODATA since that gives a nicer error string.
Otherwise, LIST_REMOVE() in network_free() fails.
This fixes the following assertion:
```
systemd-networkd[2595]: Bus bus-api-network: changing state UNSET → OPENING
systemd-networkd[2595]: Bus bus-api-network: changing state OPENING → AUTHENTICATING
systemd-networkd[2595]: timestamp of '/etc/systemd/network' changed
systemd-networkd[2595]: /etc/systemd/network/10-hoge.network:1: Invalid section header '[Network]Address=192.168.0.1'
systemd-networkd[2595]: /etc/systemd/network/10-hoge.network:1: Failed to parse file: Bad message
systemd-networkd[2595]: Assertion '*_head == _item' failed at ../../home/watanabe/git/systemd/src/network/networkd-network.c:378, function network_free(). Aborting.
valgrind[2595]: ==2595==
valgrind[2595]: ==2595== Process terminating with default action of signal 6 (SIGABRT): dumping core
valgrind[2595]: ==2595== at 0x4BCA53F: raise (in /usr/lib64/libc-2.28.so)
valgrind[2595]: ==2595== by 0x4BB4894: abort (in /usr/lib64/libc-2.28.so)
valgrind[2595]: ==2595== by 0x4955F09: log_assert_failed_realm (log.c:795)
valgrind[2595]: ==2595== by 0x417101: network_free (networkd-network.c:378)
valgrind[2595]: ==2595== by 0x415E99: network_freep (networkd-network.h:282)
valgrind[2595]: ==2595== by 0x416AB2: network_load_one (networkd-network.c:101)
valgrind[2595]: ==2595== by 0x416C39: network_load (networkd-network.c:293)
valgrind[2595]: ==2595== by 0x414031: manager_load_config (networkd-manager.c:1502)
valgrind[2595]: ==2595== by 0x40B258: run (networkd.c:82)
valgrind[2595]: ==2595== by 0x40B74A: main (networkd.c:117)
valgrind[2595]: ==2595==
valgrind[2595]: ==2595== HEAP SUMMARY:
valgrind[2595]: ==2595== in use at exit: 32,621 bytes in 201 blocks
valgrind[2595]: ==2595== total heap usage: 746 allocs, 545 frees, 241,027 bytes allocated
valgrind[2595]: ==2595==
valgrind[2595]: ==2595== LEAK SUMMARY:
valgrind[2595]: ==2595== definitely lost: 0 bytes in 0 blocks
valgrind[2595]: ==2595== indirectly lost: 0 bytes in 0 blocks
valgrind[2595]: ==2595== possibly lost: 0 bytes in 0 blocks
valgrind[2595]: ==2595== still reachable: 32,621 bytes in 201 blocks
valgrind[2595]: ==2595== suppressed: 0 bytes in 0 blocks
valgrind[2595]: ==2595== Reachable blocks (those to which a pointer was found) are not shown.
valgrind[2595]: ==2595== To see them, rerun with: --leak-check=full --show-leak-kinds=all
valgrind[2595]: ==2595==
valgrind[2595]: ==2595== For counts of detected and suppressed errors, rerun with: -v
valgrind[2595]: ==2595== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
systemd-coredump[2600]: Process 2595 (memcheck-amd64-) of user 192 dumped core.
```
Gentoo's Portage package manager uses a PID namespace for process
isolation and cleanup. In this namespace, PID 1 has UID=250 (portage).
Bug: https://bugs.gentoo.org/674458
Fixes: #11499
Let's return -EAGAIN so that on state change, unit_process_job tries to
add our job to run_queue again so that all the reloads that coalesced
into the installed reload (which itself merged into a running one)
inititally atleast runs *once*. This should ensure service picks up all
config changes reliably.
See the issue being fixed for a detailed explanation.