Given how long it took to come to a conclusion of the discussions around
https://github.com/systemd/systemd/issues/35026, let's add a comment
that makes this easier to grok for the next time this comes up.
Follow-up for: 6e207b370e
Outside of x86, some machines (e.g. Apple silicon, AMD Opteron A1100)
have physical memory mapped above 4GiB, meaning this allocation will
fail, causing the entire boot process to fail on these machines.
This commit makes it so that the below-4GB address space allocation
requirement is only set on x86 platforms, and not on other platforms
(that don't have the specific Linux x86 boot protocol), thereby fixing
boot on those that have no memory mapped below 4GiB in their address
space.
Tested on an Apple silicon M1 laptop and an AMD x86_64 desktop tower.
Fixes: #35026
I very much dislike the approach in which we were mixing Linux and UEFI C code
in the same subdirectory. No code was shared between two environments. This
layout was created in e7dd673d1e, with the
justification of "being more consistent with the rest of systemd", but I don't
see how it's supposed to be so.
Originally, when the C code was just a single bootctl.c file, this wasn't so
bad. But over time the userspace code grew quite a bit. With the moves done in
previuos commits, the intermediate subdirectory is now empty except for the
efi/ subdir, and this additional subdirectory level doesn't have a good
justification. The components is called "systemd-boot", not "systemd-efi", and
we can remove one level of indentation.
We have other subdirectories with just a single C file. And I expect
that systemd-measure will only grow over time, adding new functionality.
It's nicer to give its own subdirectory to maintain consistent structure.
Currently in mkosi and ukify we use sbsigntools to do secure boot
signing. This has multiple issues:
- sbsigntools is practically unmaintained, sbvarsign is completely
broken with the latest gnu-efi when built without -fshort-wchar and
upstream has completely ignored my bug report about this.
- sbsigntools only supports openssl engines and not the new providers
API.
- sbsigntools doesn't allow us to cache hardware token pins in the
kernel keyring like we do nowadays when we sign stuff ourselves in
systemd-repart or systemd-measure
There are alternative tools like sbctl and pesign but these do not
support caching hardware token pins in the kernel keyring either.
To get around the issues with sbsigntools, let's introduce our own
tool systemd-sbsign to do secure boot signing. This allows us to
take advantage of our own openssl infra so that hardware token pins
are cached in the kernel keyring as expected and we get openssl
provider support as well.
We used both, in fact "Devicetree" was more common. But we have a general rule
that we capitalize all words in names and also we have a DeviceTree=
configuration setting, which we cannot change. If we use two different
spelllings, this will make it harder for people to use the correct one in
config files. So use the "DeviceTree" spelling everywhere.
Currently in mkosi and ukify we use sbsigntools to do secure boot
signing. This has multiple issues:
- sbsigntools is practically unmaintained, sbvarsign is completely
broken with the latest gnu-efi when built without -fshort-wchar and
upstream has completely ignored my bug report about this.
- sbsigntools only supports openssl engines and not the new providers
API.
- sbsigntools doesn't allow us to cache hardware token pins in the
kernel keyring like we do nowadays when we sign stuff ourselves in
systemd-repart or systemd-measure
There are alternative tools like sbctl and pesign but these do not
support caching hardware token pins in the kernel keyring either.
To get around the issues with sbsigntools, let's introduce our own
tool systemd-sbsign to do secure boot signing. This allows us to
take advantage of our own openssl infra so that hardware token pins
are cached in the kernel keyring as expected and we get openssl
provider support as well.
.dtbauto section contains DT blobs, just like .dtb, the difference is
that multiple .dtbauto sections are allowed to be in a UKI and only one
is selected automatically
Temporarily drop an assert_cc() check in systemd-measure to make it compilable before the next commit
While for engines we have ENGINE_ctrl() to set the UI method for the
second PIN prompt, for openssl providers we don't have such a feature
which means we get the default openssl UI for the second pin prompt.
Instead, let's set the default UI method which does get used for the
second pin prompt by the pkcs11 provider.
In mkosi, we want to support signing via a hardware token. We already
support this in systemd-repart and systemd-measure. However, if the
hardware token is protected by a pin, the pin is asked as many as 20
times when building an image as the pin is not cached and thus requested
again for every operation.
Let's introduce a custom openssl ui when we use engines and providers
and plug systemd-ask-password into the process. With systemd-ask-password,
the pin can be cached in the kernel keyring, allowing us to reuse it without
querying the user again every time to enter the pin.
We use the private key URI as the keyring identifier so that the cached pin
can be shared across multiple tools.
Note that if the private key is pin protected, openssl will prompt both when
loading the private key using the pkcs11 engine and when actually signing the
roothash. To make sure our custom UI is used when signing the roothash, we have
to also configure it with ENGINE_ctrl() which takes a non-owning pointer to
the UI_METHOD object and its userdata object which we have to keep alive so we
introduce a new AskPasswordUserInterface struct which we use to keep both objects
alive together with the EVP_PKEY object.
Because the AskPasswordRequest struct stores non-owning pointers to its fields,
we change repart to store the private key URI as a global variable again instead
of the EVP_PKEY object so that we can use the private key argument as the keyring
field of the AskPasswordRequest instance without running into lifetime issues.
The names of these conflict with macros from efi.h that we'll move
to efi-fundamental.h in a later commit. Let's avoid the conflict by
getting rid of these helpers. Arguably this also improves readability
by clearly indicating we're passing arbitrary strings and not constants
to the macros when we invoke them.
Those text sections had a trailing NUL byte. It's debatable whether this is a
good idea or not. Correctly written consumers will look at the section size so
they wouldn't need this. Shim doesn't use a trailing NUL, so let's follow suit.
Fixes https://github.com/systemd/systemd/issues/33731.
898e9edc46 reworked this code, but didn't actually
change the logic. We have always been appending the trailing zero by using a
NUL-terminated string as the section contents. (I checked this with v253.18
from before the elf2efi rework.)
.sdmagic contains a string like "#### LoaderInfo: systemd-boot 257~devel ####",
which changes with each version, so previous versions would compare unequal
anyway, so we don't need to worry about backwards compatibility.
We often used a pattern like if (!FLAGS_SET(flags, SD_JSON_FORMAT_OFF)),
which is rather verbose and also contains a double negative, which we try
to avoid. Add a little helper to avoid an explicit bit check.
This change clarifies an aditional thing: in some cases we treated
SD_JSON_FORMAT_OFF as a flag (flags & SD_JSON_FORMAT_OFF), while in other cases
we treated it as an independent enum value (flags == SD_JSON_FORMAT_OFF).
In the first form, flags like SD_JSON_FORMAT_SSE do _not_ turn the json
output on, while in the second form they do. Let's use the first form
everywhere.
No functional change intended.
Initially I wasn't sure if this helper should be made public or just internal,
but it seems such a common pattern that if we expose the flags, we might just
as well expose it too, to make life easier for any consumers.
Same change as https://github.com/systemd/systemd/pull/34583 but for
systemd-measure. Otherwise we end up with PCR policy digest mismatches
as systemd-stub will measure the full virtual size of the kernel image
after it has been loaded while systemd-measure will disregard the extra
size introduced by SizeOfImage.
While ideally the stub would only measure the data that's actually on
disk and not the uninitialized data introduced by VirtualSize > SizeOfRawData,
we want newer systemd-measure to work with older stubs so we have to fix
systemd-measure and can't fix this in the stub.
We do half a validation currently ourselves (i.e. check the header fits
into the rest of the data), and leave the other half to the
caller (i.e. check the table fits into the rest of the data).
get_smbios_table() is changed to accept the minimum object size and
validates it before returning a table.
Based on a discussion with @anonymix007.