ipv6_is_supported only tells us the kernel has IPv6, not that
it's usable. ipv6_is_enabled also checks the sysctl that turns
it off, so we stop resolving addresses we can't use.
Our first resolve happens way before sockets.target, and
systemd-resolved-varlink.socket has no ordering of its own, so there's
nothing making sure the socket is listening by then. Without this the
connect fails and we quietly fall back to getaddrinfo(), which is exactly
the case the varlink path is there for.
Order after both the service and the socket since either one is enough
on its own but neither covers every install situation. For example
resolved binds the socket itself when nothing hands it one, and on
systems where only the socket is enabled the service isn't started at
boot at all.
With DNSSEC on, resolved can't validate anything until the clock is
right, and without an RTC the only thing that fixes the clock is talking
to the NTP servers we're trying to resolve. On glibc the timesyncd unit
sets SYSTEMD_NSS_RESOLVE_VALIDATE=0 and nss-resolve turns that into a
per-query flag, which breaks the chicken/egg. musl (and other systems
not using nss-resolve) have no NSS, so nothing reads it there and we're
stuck.
So talk to resolved directly when it's there, and pass
SD_RESOLVED_NO_VALIDATE until we've synced the clock ourselves.
NTP-related lookups after that are validated normally, which is better
than what we get from nss. If resolved isn't around we just keep using
getaddrinfo().
The reply handler duplicates the tail of the getaddrinfo handler, since
the two differ in how they report failures. Varlink discards what the
callback returns, so it has to move on to the next host itself.
This also drops SYSTEMD_NSS_RESOLVE_VALIDATE=0 from the unit because
nss-resolve talks to resolved over the same socket we do, so the
getaddrinfo() path is only ever taken when resolved is unreachable, and
then nothing validates anyway.
This adds a new function, acquire_inhibit_lock, that takes a logind
inhibitor lock for the duration of the PAM session. The lock fd is
stored in PAM data with pam_cleanup_close. In pam_sm_close_session, the
lock is released explicitly by passing NULL to pam_set_data, which
triggers the registered cleanup function immediately rather than waiting
for pam_end.
The inhibit type and reason string can also be configured via the
XDG_SESSION_INHIBIT and XDG_SESSION_INHIBIT_WHY environment variables,
which take precedence over the module arguments.
Fixes: #20654
This adds two new module arguments to parse_argv:
1) inhibit= takes a colon-separated list of inhibitor lock types to acquire
2) inhibit-why= takes an optional human-readable reason string.
Both are currently parsed but are unused until a later commit.
This cleans up the fallback Boot#### entry that was registered on
install. The logic cleaning up variables was moved from verb_remove into
a new remove_variables function, which mirrors the install side.
This adds a second install_boot_option call to register a Boot#### entry
pointing at systemd-boot-fallback{arch}.efi, and place it immediately
after the primary entry in BootOrder.
The fallback file does not exist on the ESP on first install and is
only created on first update when the existing primary binary is
rotated to the fallback path. We register the variable anyway, so
that the entry exists in the BootOrder once the fallback file shows up.
Until then, firmware that reaches the fallback entry will fail to
load it and fall through to the next entry in BootOrder, which is
fine. install_boot_option gains a require_existing parameter so the
existing early return on a missing ESP path can be skipped for the
fallback, where a missing path is expected.
This also does a bit of refactoring by splitting the bottom part of
run_install() into a new install_variables() function that handles
registering both the primary and fallback entries.
When a primary sd-boot binary already exists on the ESP and is being
updated, it is copied to systemd-boot-fallback{arch}.efi before installing
the new version. This gives firmware a fallback Boot#### entry pointing
to the previous binary in case the new one fails to load.
The fallback is preserved (not overwritten) when its product and version
match the currently booted bootloader (read from the LoaderInfo EFI
variable), since that means it already holds the known good binary that
booted this session. In all other cases it is overwritten with the current
primary, when no fallback exists yet, when LoaderInfo is unavailable, or
when the fallback's product or version differs from what booted.
This also moves the version_check() call up so its result determines
both the rotation decision and the main copy, and avoids a duplicate
check (and duplicate "Skipping..." log) when the binary is already
current.
This adds an after_slot parameter that, when not set to UINT16_MAX,
requests that the new slot be placed immediately after the given slot in
BootOrder. When after_slot is set and the new slot already exists in
BootOrder, it will leave its position alone. This is so that if a user
reorders it, we don't stomp on their changes.
This moves creation of the EFI boot option description out of
install_boot_option and into the caller, and adds a ret_slot output
parameter for capturing the assigned BootOrder slot. This allows reusing
the function for installing variables with different descriptions.
remove_variables looks up the EFI boot entry by matching both the path
and the partition UUID and it wasn't actually removing any entries
because verb_remove was passing SD_ID128_NULL, so the lookup never
matched and Boot#### entries were left behind on uninstall.
Fixes 38433a6
Some devices (e.g. android phones running pmOS) cannot have their OEM
partition table altered without breaking the firmware, so the distros's
partitions live inside a nested GPT carved into one of the OEM
partitions. Exposing these subpartitions requires wrapping the outer
partition in a loop device with partscan enabled, since the kernel does
not go into nested partition tables.
systemd already detects this case in udev-builtin-blkid
(ID_PART_GPT_AUTO_ROOT_DISK_NEEDS_LOOP) and acts on with
systemd-loop@.service, but this fails towards the end.
loop_device_make_internal has an optimization where if the input is
already a block device with a matching sector size, it skips creating
a loop and just hands back the original fd. That's fine for whole disks
but wrong for partitions, which don't support partscan, so this causes
dissect_image to fail with EPROTONOSUPPORT.
This patch changes the behavior to only take the shortcut when the input
is a whole disk, or when partscan was not requested.
Co-Authored-By: Clayton Craft <clayton@craftyguy.net>
When running `updatectl update` since f0b2ea63, Install() was called
with the version resolved by Acquire() rather than the originally
requested (empty) version, causing the stricter update-to-version polkit
action to be used instead of the update polkit action.
This isn't a failure we care about, and it's somewhat alarming to see a
red error message flash up on the display when booting, so this just
simply returns EFI_SUCCESS and skips printing the "error" altogether.
Firmware may not have loaded a devicetree, for example if the device
shipped with windows and exclusively supports ACPI.
We should always load the specified devicetree regardless of firmware
state to enable booting on platforms where Linux only supports DT.
Note: in _cleanup, the orig. config is NULL in this case, and passing
NULL to InstallConfigurationTable is permitted by the EFI spec.
See: https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.htmlFixes#24059
Co-authored-by: Daniel Thompson <daniel.thompson@linaro.org>