To prevent situations like in #17602 from happening, let's drop
direct recursive template dependencies. These will almost certainly
lead to infinite recursion so let's drop them immediately to avoid
instantiating potentially thousands of irrelevant units.
Example of a template that would lead to infinite recursion which
is caught by this check:
notify@.service:
```
[Unit]
Wants=notify@%n.service
```
Add special case optimization for a single exception fd. It's a
pretty common case in our codebase, and the optimization is simple
and means we don't need to copy/sort the exception array, so do it.
Detection of VirtualBox is accomplished in the existing code by *either* `innotek GmbH`
or `Oracle Corporation` existing in any of:
- /sys/class/dmi/id/product_name
- /sys/class/dmi/id/sys_vendor
- /sys/class/dmi/id/board_vendor
- /sys/class/dmi/id/bios_vendor
With Oracle's physical servers, both `/sys/class/dmi/id/sys_vendor` and
`/sys/class/dmi/id/board_vendor` contain `Oracle Corporation`, so those
servers are detected as `oracle` (VirtualBox).
VirtualBox has the following values in the latest versions:
- /sys/class/dmi/id/product_name: `VirtualBox`
- /sys/class/dmi/id/sys_vendor: `innotek GmbH`
- /sys/class/dmi/id/board_vendor: `Oracle Corporation`
- /sys/class/dmi/id/bios_vendor: `innotek GmbH`
Presumably the existing check for `innotek GmbH` is meant to detect
older versions of VirtualBox, while changing the second checked value
from `Oracle Corporation` to `VirtualBox` will reliably detect later and future
versions.
Apparently memory sanitizer doesn't grok getdents64() properly. Let's
address that by explicitly marken memory initialized by getdents64() as
unpoisoned.
That way we have a single syscall only for it, instead of the multiple
readdir() and friends do. And we can operate entirely on the stack, no
malloc() implicit.
We already have a similar loop twice, let's make it easier to read via
an iteration macro.
(The new macro is a bit more careful even, as it verifies the full
dirent fits into the remaining buffer when returning it)
That way we can fail earlier if the specified fd is not actually a
directory.
(Also, it's not exactly according to standards to open things without
either O_RDONLY/O_RDWR...)
In order to minimize EFI variable NVRAM wear, do not rewrite variables
if they are already in the wanted state (i.e. same data and attributes).
This allows e.g. performing repeat calls of "bootctl install" (which
always rewrites the EFI boot entry) without consuming EFI NVRAM write
cycles.
We are using this for creating userns namespaces, and we really
shouldn't try to sync there. Moreover the use of free() in shutdown code
doesn't need it anyway, since it just sync()ed right before anyway. Only
the third user of freeze() we have actually needs the syc(), hence do it
there and nowhere else.
This returns a namespace fd, and takes a uidmap/gidmap as string. This
is split out out mount-util.c's remount_idmap() logic, so that we can
allocate a userns independently.
This adds a tiny shortcut to fd_reopen(): if we are about to reopen the
fd via O_DIRECTORY then we know it#s a directory and we might as well
reopen it via opening "." using the fd as "at fd" in openat().
This has the benefit that we don't need /proc/self/fd/ around for this
special case: fewer sources of errors.
Let's define two helpers strdupa_safe() + strndupa_safe() which do the
same as their non-safe counterparts, except that they abort if called
with allocations larger than ALLOCA_MAX.
This should ensure that all our alloca() based allocations are subject
to this limit.
afaics glibc offers three alloca() based APIs: alloca() itself,
strndupa() + strdupa(). With this we have now replacements for all of
them, that take the limit into account.
This is like alloca(), but does two things:
1. Verifies the allocation is smaller than ALLOCA_MAX
2. Ensures we allocate at least one byte
This was previously done manually in all invocations. This adds a handy
helper that does that implicitly.
This is a debugging feature. It's sometimes incredibly useful to be able
to run a second instance of homed that operates on another dir than
/home/.
Specifically, if you build homed from the source tree you can now run an
instance of it pretty reasonably directly from the build tree via:
sudo SYSTEMD_HOME_DEBUG_SUFFIX=foo SYSTEMD_HOMEWORK_PATH=$(pwd)/build/systemd-homework SYSTEMD_HOME_ROOT=/home/foo ./build/systemd-homed
And then talk to it via
sudo SYSTEMD_HOME_DEBUG_SUFFIX=foo homectl …
(you might need to tweak your dbus policy for this to work fully though)
Currently, when Xen PV domains are nested within a hypervisor which is
detected through CPUID (such as VMware), the detected hypervisor might
not be Xen, because we don't check for Xen until after the CPUID check.
This change moves the Xen check before CPUID checks to fix the issue,
and moves Dom0 checking to detect_vm_xen so that we keep ignoring Xen
when we are in Dom0.
Let's use the underlying Linux API directly, instead of
opendir()/readdir(). This makes it possible for us to do a single memory
allocation for all directory entries in common cases, instead of one for
each entry.
glibc 2.30 (Aug 2019) added a wrapper for getdents64(). For older
versions let's define our own.
(This syscall exists since Linux 2.4, hence should be safe to use for
us)