Commit Graph
31 Commits
Author SHA1 Message Date
Lennart Poettering 03d808c9f6 efi-loader: when detecting if we are booted in UKI measured boot mode, imply a check for TPM2
We simply don't carry any userspace support for TPM1.2 in our tree, and
we shouldn't given it's too weak by today's standards. Hence, if we
check if we are booted in UKI measured boot mode, don't just check if we
are booted in EFI, but also check that we have a TPM2 chip (as opposed
to none or only a TPM1.2 chip).

This is an alternative to #30652 but more comprehensive (and simpler),
since it covers all invocations of efi_measured_uki().

Fixes: #30650
Replaces: #30652
2024-01-02 17:48:53 +01:00
Lennart Poettering c24f9f5371 efi-loader: add caching to efi_measured_uki()
EFI variable access is slow, hence let's avoid it if there's no need.
Let's cache the result of efi_measured_uki() so that we don't have to go
to the EFI variables each time.

This only caches in the yes/no case. If we encounter an error we don't
cache, so that we go to disk again.

This should optimize things a bit given we now have a bunch of services
which are conditioned with this at boot.
2023-09-27 12:14:56 +02:00
Lennart Poettering be8f478c0f efi-loader: rename efi_stub_measured() → efi_measured_uki()
Let's say "uki" rather than "stub", since that is just too generic, and
we shouldn't limit us to our own stub anyway, but generally define a
concept of a "measured UKI", which is a UKI that measures its part to
PCR 11.

This is mostly preparation for exposing this check to the user via
ConditionSecurity=.
2023-09-27 11:51:13 +02:00
Lennart Poettering e0e1f4f7a2 fundamental: rename tpm-pcr.h → tpm2-pcr.h
I always found it confusing that most of our TPM related definitions are
in tpm2-util.h, but the PCR names in tpm-pcr.h, without the "2". Let's
fix that and make this systematic, in particular as the definitions in
the file all start with TPM2_ already.

No code flow changes, just some renaming.
2023-08-24 13:40:37 +02:00
Lennart Poettering 2099cd6289 tpm2: unify symbolic name infra for PCRs
We so far maintained two places for symboic names for PCRs. One in
tpm2-util.h and one in tpm-pcr.h.

Let's unify this into one, i.e. move the full list from tpm2-util.h into
tpm-pcr.h, replacing the short list placed so far there.

Systematically prefix the definitions with TPM2_ or tpm2_, to follow how
we do this for all other defines in this context.

No change in behaviour, just unification of tables.
2023-08-24 13:40:37 +02:00
Lennart Poettering e503019bc7 tree-wide: when in doubt use greek small letter mu rather than micro symbol
Doesn't really matter since the two unicode symbols are supposedly
equivalent, but let's better follow the unicode recommendations to
prefer greek small letter mu, as per:

https://www.unicode.org/reports/tr25
2023-06-14 10:23:56 +02:00
Zbigniew Jędrzejewski-Szmek 2f6c52b919 shared/efi-loader: fix compilation with !ENABLE_EFI, improve messages
When compiled without ENABLE_EFI, efi_stub_measured() was not defined, so
compilation would fail. But it's not enough to add a stub that returns
-EOPNOTSUPP. We call this function in various places and usually print the error
at warning or error level, so we'd print a confusing message. We also can't add
a stub that always returns 0, because then we'd print a message like "Kernel
stub did not measure", which would be confusing too. Adding special handling for
-EOPNOTSUPP in every caller is also unattractive. So instead efi_stub_measured()
is reworked to log the warning or error internally, and such logging is removed
from the callers, and a stub is added that logs a custom message.
2023-01-24 23:07:21 +00:00
Lennart Poettering 6c51b49ce0 tpm2: add common helper for checking if we are running on UKI with TPM measurements
Let's introduce a common implementation of a function that checks
whether we are booted on a kernel with systemd-stub that has TPM PCR
measurements enabled. Do our own userspace measurements only if we
detect that.

PCRs are scarce and most likely there are projects which already make
use of them in other ways. Hence, instead of blindly stepping into their
territory let's conditionalize things so that people have to explicitly
buy into our PCR assignments before we start measuring things into them.
Specifically bind everything to an UKI that reported measurements.

This was previously already implemented in systemd-pcrphase, but with
this change we expand this to all tools that process PCR measurement
settings.

The env var to override the check is renamed to SYSTEMD_FORCE_MEASURE,
to make it more generic (since we'll use it at multiple places now).
This is not a compat break, since the original env var for that was not
included in any stable release yet.
2023-01-17 09:42:16 +01:00
Jan Janssen 9cf6c94eba efivars: Parse into unsigned
The format specifiers for UUID parsing use %x, which expects unsigned.
2022-08-30 12:03:33 +02:00
Lennart Poettering 6977ea9975 bootctl: show stub feature set in status output 2022-08-02 10:28:49 +02:00
Yu Watanabe 8603a229e9 efi-loader: drop harmful assertion
This fixes a bug introduced by 7be4b23649.

The function `efi_loader_get_device_part_uuid()` handles NULL
gracefully, and it is called with NULL in gpt-auto-generator.

Fixes #22862.
2022-03-25 14:29:44 +09:00
Lennart Poettering 7be4b23649 efi-loader: split efi-api.[ch] from efi-loader.[ch]
Some refactoring: split efi-loader.[ch] in two: isolate the calls that
implement out boot loader interface spec, and those which implement
access to upstream UEFI firmware features.

They are quite different in nature and behaviour, and even semantically
it makes to keep these two separate. At the very least because the
previous name "efi-loader.[ch]" suggests all was about loader-specific
APIs, but much of it is generic uefi stuff...

While we are at it, I renamed a bunch of return parameters to follow our
usual ret_xyz naming. But besides renaming no real code changes.
2022-03-24 15:21:09 +01:00
Zbigniew Jędrzejewski-Szmek af3b864d76 Define FOREACH_DIRENT through FOREACH_DIRENT_ALL
As in the previous commit, 'de' is used as the iterator variable name.
2021-12-15 22:50:00 +01:00
Zbigniew Jędrzejewski-Szmek c67bd42b71 Inline some inerator variables 2021-06-15 22:01:42 +02:00
Zbigniew Jędrzejewski-Szmek e6f055cbc4 basic/efivars: replace dynanamic creation of efivar names with static strings
Creating those string dynamically at runtime is slow and unnecessary.
Let's use static strings with a bit of macro magic and the let the compiler
coalesce as much as possible.

$ size build/src/shared/libsystemd-shared-248.so{.old,}
   text	   data	    bss	    dec	    hex	filename
2813453	  94572	   4584	2912609	 2c7161	build/src/shared/libsystemd-shared-248.so.old
2812309	  94564	   4584	2911457	 2c6ce1	build/src/shared/libsystemd-shared-248.so

A nice side-effect is that the same form is used everywhere, so it's easier to
figure out all variables that are used, and where each specific variable is
used.

C.f. 2b0445262a.

Note: 'const char *foo = alloca(…);' seems OK. Our coding style document and
alloca(3) only warn against using alloca() in function invocations. Declaring
both stack variable and alloca at the same time should be fine: no matter in
which order they happen, i.e. if the pointer variable is above the contents,
or the contents are above the pointer, or even if the pointer is elided by the
compiler, everything should be fine.
2021-06-15 22:01:42 +02:00
Lennart Poettering 319a4f4bc4 alloc-util: simplify GREEDY_REALLOC() logic by relying on malloc_usable_size()
We recently started making more use of malloc_usable_size() and rely on
it (see the string_erase() story). Given that we don't really support
sytems where malloc_usable_size() cannot be trusted beyond statistics
anyway, let's go fully in and rework GREEDY_REALLOC() on top of it:
instead of passing around and maintaining the currenly allocated size
everywhere, let's just derive it automatically from
malloc_usable_size().

I am mostly after this for the simplicity this brings. It also brings
minor efficiency improvements I guess, but things become so much nicer
to look at if we can avoid these allocation size variables everywhere.

Note that the malloc_usable_size() man page says relying on it wasn't
"good programming practice", but I think it does this for reasons that
don't apply here: the greedy realloc logic specifically doesn't rely on
the returned extra size, beyond the fact that it is equal or larger than
what was requested.

(This commit was supposed to be a quick patch btw, but apparently we use
the greedy realloc stuff quite a bit across the codebase, so this ends
up touching *a*lot* of code.)
2021-05-19 16:42:37 +02:00
Lennart Poettering f470d234d3 efi-loader: make efi_loader_entry_name_valid() check a bit stricter
Previously we'd just check if the ID was no-empty an no longer than
FILENAME_MAX. The latter was probably a mistake, given the comment next
to it. Instead of fixing that to check for NAME_MAX let's instead  just
switch over to filename_is_valid() which odes a similar check, plus a
some minor additional checks. After all we do want that valid EFI boot
menu entry ids are usable as filenames.
2021-03-08 22:47:41 +01:00
Lennart Poettering d0ddaf587f efi-loader: add efi_has_tpm2() helper
The helper checks if the UEFI firmware is hooked up to a TPM2 chip. This
is useful to know in trusted boot scenarios, in particular during early
boot in auto-enroll scenarios where we want to know whether TPM2 is
available or not, and the Linux drivers are not loaded yet, and where it
might or not be worth waiting for it.
2021-02-11 23:10:07 +01:00
Yu Watanabe db9ecf0501 license: LGPL-2.1+ -> LGPL-2.1-or-later 2020-11-09 13:23:58 +09:00
Luca Boccassi 7143b95552 efi: define cache functions inside EFI_ENABLE ifdef
../src/shared/efi-loader.c:738:5: error: redefinition of 'efi_loader_get_config_timeout_one_shot'
 int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../src/shared/efi-loader.c:9:
../src/shared/efi-loader.h:85:19: note: previous definition of 'efi_loader_get_config_timeout_one_shot' was here
 static inline int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/shared/efi-loader.c:776:5: error: redefinition of 'efi_loader_update_entry_one_shot_cache'
 int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat) {
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../src/shared/efi-loader.c:9:
../src/shared/efi-loader.h:89:19: note: previous definition of 'efi_loader_update_entry_one_shot_cache' was here
 static inline int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat) {
2020-06-26 22:34:22 +02:00
Lennart Poettering af2697e83d logind: also cache LoaderEntryOneShot EFI variable
With this we are now caching all EFI variables that we expose as
property in logind. Thus a client invoking GetAllProperties() should
only trgger a single read of each variable, but never repeated ones.

Obsoletes: #16190
Fixes: #14828
2020-06-26 10:43:42 +02:00
Lennart Poettering e8df4eee65 efi-loader: cache LoaderConfigTimeoutOneShot too
The data from this EFI variable is exposed as dbus property, and gdbus
clients are happy to issue GetAllProperties() as if it was free. Hence
make sure it's actually free and cache LoaderConfigTimeoutOneShot, since
it's easy.
2020-06-26 10:43:42 +02:00
Lennart Poettering c37070c85a efi: cache OsIndications too 2020-05-29 15:41:43 +02:00
Lennart Poettering 9e5230aad9 efi: cache OsIndicationsSupported
As suggested by:

https://github.com/systemd/systemd/issues/14828#issuecomment-634202054
2020-05-29 15:41:06 +02:00
Lennart Poettering 5c25f42322 efi: avoid weirdly double }} by indenting differently 2020-05-29 15:41:03 +02:00
Zbigniew Jędrzejewski-Szmek dde5c821bf shared/efi-loader: remove check that uses absolute tick value
sd-boot uses rdtsc to set those timestamps. There is no guarantee that the tsc
has any particular absolute value.

On my VM:
$ head /sys/firmware/efi/efivars/LoaderTime*
==> /sys/firmware/efi/efivars/LoaderTimeExecUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4397904074
==> /sys/firmware/efi/efivars/LoaderTimeInitUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4396386839
==> /sys/firmware/efi/efivars/LoaderTimeMenuUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4396392521

$ build/test-boot-timestamps
...
LoaderTimeExecUSec=4396386839 too large, refusing.
Failed to read EFI loader data: Input/output error
Assertion 'q >= 0' failed at src/test/test-boot-timestamps.c:84, function main(). Aborting.

(with patch)
$ build/test-boot-timestamps
...
EFI Loader: start=1h 13min 16.386s exit=1h 13min 17.904s duration=1.517s
Firmware began 1h 13min 17.904074s before kernel.
Loader began 1.517235s before kernel.
Firmware began Tue 2020-05-26 11:04:13 CEST.
Loader began Tue 2020-05-26 12:17:30 CEST.
Kernel began Tue 2020-05-26 12:17:31 CEST.
2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 0da965037e Add yet another tiny helper to manipulate flags 2020-04-10 16:40:48 +02:00
Arian van Putten c7d26acce6 Disable reading SystemdOptions EFI Var when in SecureBoot mode
In SecureBoot mode this is probably not what you want. As your cmdline
is cryptographically signed like when using Type #2 EFI Unified Kernel
Images (https://systemd.io/BOOT_LOADER_SPECIFICATION/) The user's
intention is then that the cmdline should not be modified.  You want to
make sure that the system starts up as exactly specified in the signed
artifact.
2020-01-16 18:46:56 +01:00
Zbigniew Jędrzejewski-Szmek a97abb30e7 shared/efi-loader: add some debugging statements
Should make it easier to figure out why some operations fail...
2019-12-15 21:06:42 +01:00
Yu Watanabe 8e1e87a5de tree-wide: drop double newline 2019-11-04 00:30:32 +09:00
Zbigniew Jędrzejewski-Szmek 0bb2f0f10e util-lib: split shared/efivars into basic/efivars and shared/efi-loader
I want to use efivars.[ch] in proc-cmdline.c, but most of the efivars stuff is
not needed in basic/. Move the file from shared/ to basic/, but then move back
most of the higher-level functions to the new shared/efi-loader.c file.
2019-09-16 18:08:53 +02:00