diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml
index 5b47d752ca..e489a138d6 100644
--- a/man/systemd-stub.xml
+++ b/man/systemd-stub.xml
@@ -32,6 +32,8 @@
ESP/.../foo.efi.extra.d/*.addon.efi
ESP/.../foo.efi.extra.d/*.cred
ESP/.../foo.efi.extra.d/*.raw
+ ESP/.../foo.efi.extra.d/*.sysext.raw
+ ESP/.../foo.efi.extra.d/*.confext.raw
ESP/loader/addons/*.addon.efi
ESP/loader/credentials/*.cred
@@ -153,14 +155,28 @@
details on encrypted credentials. The generated cpio archive is measured into TPM
PCR 12 (if a TPM is present).
- Similarly, files foo.efi.extra.d/*.raw
- are packed up in a cpio archive and placed in the /.extra/sysext/
- directory in the initrd file hierarchy. This is supposed to be used to pass additional system extension
- images to the initrd. See
+ Similarly, files
+ foo.efi.extra.d/*.sysext.raw are packed up in a
+ cpio archive and placed in the /.extra/sysext/ directory in the
+ initrd file hierarchy. This is supposed to be used to pass additional system extension images to the
+ initrd. See
systemd-sysext8 for
details on system extension images. The generated cpio archive containing these
system extension images is measured into TPM PCR 13 (if a TPM is present).
+
+
+ Similarly, files
+ foo.efi.extra.d/*.confext.raw are packed up in a
+ cpio archive and placed in the /.extra/confext/ directory in
+ the initrd file hierarchy. This is supposed to be used to pass additional configuration extension
+ images to the initrd. See
+ systemd-confext8 for
+ details on configuration extension images. The generated cpio archive containing
+ these system extension images is measured into TPM PCR 12 (if a TPM is present).
+
Similarly, files
foo.efi.extra.d/*.addon.efi are loaded and verified as
PE binaries, and a .cmdline section is parsed from them. Addons are supposed to be
@@ -218,9 +234,10 @@
Also note that the Linux kernel will measure all initrds it receives into TPM PCR 9. This means
every type of initrd will be measured two or three times: the initrd embedded in the kernel image will be
- measured to PCR 4, PCR 9 and PCR 11; the initrd synthesized from credentials will be measured to both PCR
- 9 and PCR 12; the initrd synthesized from system extensions will be measured to both PCR 4 and PCR
- 9. Let's summarize the OS resources and the PCRs they are measured to:
+ measured to PCR 4, PCR 9 and PCR 11; the initrd synthesized from credentials (and the one synthesized
+ from configuration extensions) will be measured to both PCR 9 and PCR 12; the initrd synthesized from
+ system extensions will be measured to both PCR 4 and PCR 9. Let's summarize the OS resources and the PCRs
+ they are measured to:
OS Resource PCR Summary
@@ -291,6 +308,11 @@
System Extensions (synthesized initrd from companion files)
9 + 13
+
+
+ Configuration Extensions (synthesized initrd from companion files)
+ 9 + 12
+
@@ -371,13 +393,24 @@
StubPcrInitRDSysExts
- The PCR register index the systemd extensions for the initrd, which are picked up
- from the file system the kernel image is located on. Formatted as decimal ASCII string (e.g.
+ The PCR register index the system extensions for the initrd, which are picked up from
+ the file system the kernel image is located on. Formatted as decimal ASCII string (e.g.
13). This variable is set if a measurement was successfully completed, and remains
unset otherwise.
+
+
+ StubPcrInitRDConfExts
+
+ The PCR register index the configuration extensions for the initrd, which are picked
+ up from the file system the kernel image is located on. Formatted as decimal ASCII string (e.g.
+ 12). This variable is set if a measurement was successfully completed, and remains
+ unset otherwise.
+
+
+
Note that some of the variables above may also be set by the boot loader. The stub will only set
@@ -422,14 +455,23 @@
- /.extra/sysext/*.raw
- System extension image files (suffix .raw) that are placed next to
- the unified kernel image (as described above) are copied into the
+ /.extra/sysext/*.sysext.raw
+ System extension image files (suffix .sysext.raw) that are placed
+ next to the unified kernel image (as described above) are copied into the
/.extra/sysext/ directory in the initrd execution environment.
+
+ /.extra/confext/*.confext.raw
+ Configuration extension image files (suffix .confext.raw) that are
+ placed next to the unified kernel image (as described above) are copied into the
+ /.extra/confext/ directory in the initrd execution environment.
+
+
+
+
/.extra/tpm2-pcr-signature.json
The TPM2 PCR signature JSON object included in the .pcrsig PE
diff --git a/src/analyze/analyze-image-policy.c b/src/analyze/analyze-image-policy.c
index 0146b50c78..7d4f5498e8 100644
--- a/src/analyze/analyze-image-policy.c
+++ b/src/analyze/analyze-image-policy.c
@@ -94,6 +94,8 @@ int verb_image_policy(int argc, char *argv[], void *userdata) {
p = &image_policy_sysext_strict;
else if (streq(argv[i], "@confext"))
p = &image_policy_confext;
+ else if (streq(argv[i], "@confext-strict"))
+ p = &image_policy_confext_strict;
else if (streq(argv[i], "@container"))
p = &image_policy_container;
else if (streq(argv[i], "@service"))
diff --git a/src/boot/bootctl-status.c b/src/boot/bootctl-status.c
index c8041c4bd1..337b3eb4b5 100644
--- a/src/boot/bootctl-status.c
+++ b/src/boot/bootctl-status.c
@@ -374,14 +374,15 @@ int verb_status(int argc, char *argv[], void *userdata) {
uint64_t flag;
const char *name;
} stub_flags[] = {
- { EFI_STUB_FEATURE_REPORT_BOOT_PARTITION, "Stub sets ESP information" },
- { EFI_STUB_FEATURE_PICK_UP_CREDENTIALS, "Picks up credentials from boot partition" },
- { EFI_STUB_FEATURE_PICK_UP_SYSEXTS, "Picks up system extension images from boot partition" },
- { EFI_STUB_FEATURE_THREE_PCRS, "Measures kernel+command line+sysexts" },
- { EFI_STUB_FEATURE_RANDOM_SEED, "Support for passing random seed to OS" },
- { EFI_STUB_FEATURE_CMDLINE_ADDONS, "Pick up .cmdline from addons" },
- { EFI_STUB_FEATURE_CMDLINE_SMBIOS, "Pick up .cmdline from SMBIOS Type 11" },
- { EFI_STUB_FEATURE_DEVICETREE_ADDONS, "Pick up .dtb from addons" },
+ { EFI_STUB_FEATURE_REPORT_BOOT_PARTITION, "Stub sets ESP information" },
+ { EFI_STUB_FEATURE_PICK_UP_CREDENTIALS, "Picks up credentials from boot partition" },
+ { EFI_STUB_FEATURE_PICK_UP_SYSEXTS, "Picks up system extension images from boot partition" },
+ { EFI_STUB_FEATURE_PICK_UP_CONFEXTS, "Picks up configuration extension images from boot partition" },
+ { EFI_STUB_FEATURE_THREE_PCRS, "Measures kernel+command line+sysexts" },
+ { EFI_STUB_FEATURE_RANDOM_SEED, "Support for passing random seed to OS" },
+ { EFI_STUB_FEATURE_CMDLINE_ADDONS, "Pick up .cmdline from addons" },
+ { EFI_STUB_FEATURE_CMDLINE_SMBIOS, "Pick up .cmdline from SMBIOS Type 11" },
+ { EFI_STUB_FEATURE_DEVICETREE_ADDONS, "Pick up .dtb from addons" },
};
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
sd_id128_t loader_part_uuid = SD_ID128_NULL;
diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c
index 5b90e17c41..1408d74bb6 100644
--- a/src/boot/efi/cpio.c
+++ b/src/boot/efi/cpio.c
@@ -305,6 +305,7 @@ EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
const char16_t *dropin_dir,
const char16_t *match_suffix,
+ const char16_t *exclude_suffix,
const char *target_dir_prefix,
uint32_t dir_mode,
uint32_t access_mode,
@@ -367,6 +368,8 @@ EFI_STATUS pack_cpio(
continue;
if (match_suffix && !endswith_no_case(dirent->FileName, match_suffix))
continue;
+ if (exclude_suffix && endswith_no_case(dirent->FileName, exclude_suffix))
+ continue;
if (!is_ascii(dirent->FileName))
continue;
if (strlen16(dirent->FileName) > 255) /* Max filename size on Linux */
diff --git a/src/boot/efi/cpio.h b/src/boot/efi/cpio.h
index 26851e3c15..9d14fa15a2 100644
--- a/src/boot/efi/cpio.h
+++ b/src/boot/efi/cpio.h
@@ -8,6 +8,7 @@ EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
const char16_t *dropin_dir,
const char16_t *match_suffix,
+ const char16_t *exclude_suffix,
const char *target_dir_prefix,
uint32_t dir_mode,
uint32_t access_mode,
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index 7ef3e76544..58586f942f 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -91,6 +91,7 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
EFI_STUB_FEATURE_REPORT_BOOT_PARTITION | /* We set LoaderDevicePartUUID */
EFI_STUB_FEATURE_PICK_UP_CREDENTIALS | /* We pick up credentials from the boot partition */
EFI_STUB_FEATURE_PICK_UP_SYSEXTS | /* We pick up system extensions from the boot partition */
+ EFI_STUB_FEATURE_PICK_UP_CONFEXTS | /* We pick up configuration extensions from the boot partition */
EFI_STUB_FEATURE_THREE_PCRS | /* We can measure kernel image, parameters and sysext */
EFI_STUB_FEATURE_RANDOM_SEED | /* We pass a random seed to the kernel */
EFI_STUB_FEATURE_CMDLINE_ADDONS | /* We pick up .cmdline addons */
@@ -497,8 +498,8 @@ static EFI_STATUS load_addons(
}
static EFI_STATUS run(EFI_HANDLE image) {
- _cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL;
- size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
+ _cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *confext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL;
+ size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, confext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
void **dt_bases_addons_global = NULL, **dt_bases_addons_uki = NULL;
char16_t **dt_filenames_addons_global = NULL, **dt_filenames_addons_uki = NULL;
_cleanup_free_ size_t *dt_sizes_addons_global = NULL, *dt_sizes_addons_uki = NULL;
@@ -510,7 +511,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
_cleanup_free_ char16_t *cmdline = NULL, *cmdline_addons_global = NULL, *cmdline_addons_uki = NULL;
int sections_measured = -1, parameters_measured = -1;
_cleanup_free_ char *uname = NULL;
- bool sysext_measured = false, m;
+ bool sysext_measured = false, confext_measured = false, m;
uint64_t loader_features = 0;
EFI_STATUS err;
@@ -660,8 +661,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
export_variables(loaded_image);
if (pack_cpio(loaded_image,
- NULL,
+ /* dropin_dir= */ NULL,
u".cred",
+ /* exclude_suffix= */ NULL,
".extra/credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
@@ -675,6 +677,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
if (pack_cpio(loaded_image,
u"\\loader\\credentials",
u".cred",
+ /* exclude_suffix= */ NULL,
".extra/global_credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
@@ -686,8 +689,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
if (pack_cpio(loaded_image,
- NULL,
- u".raw",
+ /* dropin_dir= */ NULL,
+ u".raw", /* ideally we'd pick up only *.sysext.raw here, but for compat we pick up *.raw instead … */
+ u".confext.raw", /* … but then exclude *.confext.raw again */
".extra/sysext",
/* dir_mode= */ 0555,
/* access_mode= */ 0444,
@@ -698,6 +702,20 @@ static EFI_STATUS run(EFI_HANDLE image) {
&m) == EFI_SUCCESS)
sysext_measured = m;
+ if (pack_cpio(loaded_image,
+ /* dropin_dir= */ NULL,
+ u".confext.raw",
+ /* exclude_suffix= */ NULL,
+ ".extra/confext",
+ /* dir_mode= */ 0555,
+ /* access_mode= */ 0444,
+ /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
+ u"Configuration extension initrd",
+ &confext_initrd,
+ &confext_initrd_size,
+ &m) == EFI_SUCCESS)
+ confext_measured = m;
+
dt_size = szs[UNIFIED_SECTION_DTB];
dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_DTB] : 0;
@@ -728,6 +746,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrKernelParameters", TPM2_PCR_KERNEL_CONFIG, 0);
if (sysext_measured)
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrInitRDSysExts", TPM2_PCR_SYSEXTS, 0);
+ if (confext_measured)
+ (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrInitRDConfExts", TPM2_PCR_KERNEL_CONFIG, 0);
/* If the PCR signature was embedded in the PE image, then let's wrap it in a cpio and also pass it
* to the kernel, so that it can be read from /.extra/tpm2-pcr-signature.json. Note that this section
@@ -773,7 +793,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0;
_cleanup_pages_ Pages initrd_pages = {};
- if (credential_initrd || global_credential_initrd || sysext_initrd || pcrsig_initrd || pcrpkey_initrd) {
+ if (credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd) {
/* If we have generated initrds dynamically, let's combine them with the built-in initrd. */
err = combine_initrd(
initrd_base, initrd_size,
@@ -781,6 +801,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
credential_initrd,
global_credential_initrd,
sysext_initrd,
+ confext_initrd,
pcrsig_initrd,
pcrpkey_initrd,
},
@@ -788,10 +809,11 @@ static EFI_STATUS run(EFI_HANDLE image) {
credential_initrd_size,
global_credential_initrd_size,
sysext_initrd_size,
+ confext_initrd_size,
pcrsig_initrd_size,
pcrpkey_initrd_size,
},
- 5,
+ 6,
&initrd_pages, &initrd_size);
if (err != EFI_SUCCESS)
return err;
@@ -802,6 +824,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
credential_initrd = mfree(credential_initrd);
global_credential_initrd = mfree(global_credential_initrd);
sysext_initrd = mfree(sysext_initrd);
+ confext_initrd = mfree(confext_initrd);
pcrsig_initrd = mfree(pcrsig_initrd);
pcrpkey_initrd = mfree(pcrpkey_initrd);
}
diff --git a/src/fundamental/efivars-fundamental.h b/src/fundamental/efivars-fundamental.h
index 2d25d2248f..01b18ec241 100644
--- a/src/fundamental/efivars-fundamental.h
+++ b/src/fundamental/efivars-fundamental.h
@@ -33,6 +33,7 @@
#define EFI_STUB_FEATURE_CMDLINE_ADDONS (UINT64_C(1) << 5)
#define EFI_STUB_FEATURE_CMDLINE_SMBIOS (UINT64_C(1) << 6)
#define EFI_STUB_FEATURE_DEVICETREE_ADDONS (UINT64_C(1) << 7)
+#define EFI_STUB_FEATURE_PICK_UP_CONFEXTS (UINT64_C(1) << 8)
typedef enum SecureBootMode {
SECURE_BOOT_UNSUPPORTED,
diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c
index b3f4c9ab76..3baa84c8bd 100644
--- a/src/shared/discover-image.c
+++ b/src/shared/discover-image.c
@@ -75,15 +75,20 @@ static const char* const image_search_path[_IMAGE_CLASS_MAX] = {
"/usr/lib/confexts\0",
};
-/* Inside the initrd, use a slightly different set of search path (i.e. include .extra/sysext in extension
- * search dir) */
+/* Inside the initrd, use a slightly different set of search path (i.e. include .extra/sysext/ and
+ * .extra/confext/ in extension search dir) */
static const char* const image_search_path_initrd[_IMAGE_CLASS_MAX] = {
/* (entries that aren't listed here will get the same search path as for the non initrd-case) */
[IMAGE_SYSEXT] = "/etc/extensions\0" /* only place symlinks here */
"/run/extensions\0" /* and here too */
"/var/lib/extensions\0" /* the main place for images */
- "/.extra/sysext\0" /* put sysext picked up by systemd-stub last, since not trusted */
+ "/.extra/sysext\0", /* put sysext picked up by systemd-stub last, since not trusted */
+
+ [IMAGE_CONFEXT] = "/run/confexts\0" /* only place symlinks here */
+ "/var/lib/confexts\0" /* the main place for images */
+ "/usr/local/lib/confexts\0"
+ "/.extra/confext\0", /* put confext picked up by systemd-stub last, since not trusted */
};
static const char* image_class_suffix_table[_IMAGE_CLASS_MAX] = {
diff --git a/src/shared/image-policy.c b/src/shared/image-policy.c
index 3c3de50979..47ca62c731 100644
--- a/src/shared/image-policy.c
+++ b/src/shared/image-policy.c
@@ -726,6 +726,14 @@ const ImagePolicy image_policy_confext = {
.default_flags = PARTITION_POLICY_IGNORE,
};
+const ImagePolicy image_policy_confext_strict = {
+ .n_policies = 1,
+ .policies = {
+ { PARTITION_ROOT, PARTITION_POLICY_SIGNED|PARTITION_POLICY_ABSENT },
+ },
+ .default_flags = PARTITION_POLICY_IGNORE,
+};
+
const ImagePolicy image_policy_container = {
/* For systemd-nspawn containers we use all partitions, with the exception of swap */
.n_policies = 8,
diff --git a/src/shared/image-policy.h b/src/shared/image-policy.h
index f59c16e173..c2a0a5ac40 100644
--- a/src/shared/image-policy.h
+++ b/src/shared/image-policy.h
@@ -58,9 +58,10 @@ struct ImagePolicy {
extern const ImagePolicy image_policy_allow;
extern const ImagePolicy image_policy_deny;
extern const ImagePolicy image_policy_ignore;
-extern const ImagePolicy image_policy_sysext; /* No verity required */
-extern const ImagePolicy image_policy_sysext_strict; /* Signed verity required */
-extern const ImagePolicy image_policy_confext; /* No verity required */
+extern const ImagePolicy image_policy_sysext; /* No verity required */
+extern const ImagePolicy image_policy_sysext_strict; /* Signed verity required */
+extern const ImagePolicy image_policy_confext; /* No verity required */
+extern const ImagePolicy image_policy_confext_strict; /* Signed verity required */
extern const ImagePolicy image_policy_container;
extern const ImagePolicy image_policy_service;
extern const ImagePolicy image_policy_host;
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index fe11fe0f07..fc79370781 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -659,8 +659,16 @@ static const ImagePolicy *pick_image_policy(const Image *img) {
* picked up from an untrusted ESP. Thus, require a stricter policy by default for them. (For the
* other directories we assume the appropriate level of trust was already established already. */
- if (in_initrd() && path_startswith(img->path, "/.extra/sysext/"))
- return &image_policy_sysext_strict;
+ if (in_initrd()) {
+ if (path_startswith(img->path, "/.extra/sysext/"))
+ return &image_policy_sysext_strict;
+ if (path_startswith(img->path, "/.extra/confext/"))
+ return &image_policy_confext_strict;
+
+ /* Better safe than sorry, refuse everything else passed in via the untrusted /.extra/ dir */
+ if (path_startswith(img->path, "/.extra/"))
+ return &image_policy_deny;
+ }
return image_class_info[img->class].default_image_policy;
}
diff --git a/src/test/test-image-policy.c b/src/test/test-image-policy.c
index d9fe5562a1..1572093c9d 100644
--- a/src/test/test-image-policy.c
+++ b/src/test/test-image-policy.c
@@ -79,6 +79,7 @@ TEST_RET(test_image_policy_to_string) {
test_policy(&image_policy_sysext, "sysext");
test_policy(&image_policy_sysext_strict, "sysext-strict");
test_policy(&image_policy_confext, "confext");
+ test_policy(&image_policy_confext_strict, "confext-strict");
test_policy(&image_policy_container, "container");
test_policy(&image_policy_host, "host");
test_policy(&image_policy_service, "service");