<para><filename>/usr/lib/systemd/boot/efi/linuxx64.efi.stub</filename></para>
<para><filename>/usr/lib/systemd/boot/efi/linuxia32.efi.stub</filename></para>
<para><filename>/usr/lib/systemd/boot/efi/linuxaa64.efi.stub</filename></para>
+ <para><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.cred</filename></para>
+ <para><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.raw</filename></para>
+ <para><filename><replaceable>ESP</replaceable>/loader/credentials/*.cred</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Companion Files</title>
<para>The <command>systemd-stub</command> UEFI boot stub automatically collects two types of auxiliary
- companion files optionally placed in a drop-in directory next to the EFI binary and dynamically generates
- <command>cpio</command> initrd archives from them, and passes them to the kernel. Specifically:</para>
+ companion files optionally placed in drop-in directories on the same partition as the EFI binary,
+ dynamically generates <command>cpio</command> initrd archives from them, and passes them to the kernel.
+ Specifically:</para>
<itemizedlist>
- <listitem><para>For a kernel binary called <filename><replaceable>foo</replaceable>.efi</filename> it
+ <listitem><para>For a kernel binary called <filename><replaceable>foo</replaceable>.efi</filename>, it
will look for files with the <filename>.cred</filename> suffix in a directory named
- <filename><replaceable>foo</replaceable>.efi.extra.d/</filename>, next to it. A <command>cpio</command>
+ <filename><replaceable>foo</replaceable>.efi.extra.d/</filename> next to it. A <command>cpio</command>
archive is generated from all files found that way, placing them in the
<filename>/.extra/credentials/</filename> directory of the initrd file hierarchy. The main initrd may
then access them in this directory. This is supposed to be used to store auxiliary, encrypted,
details on encrypted credentials. The generated <command>cpio</command> archive is measured into TPM
PCR 4 (if a TPM is present)</para></listitem>
- <listitem><para>Similar, files <filename><replaceable>foo</replaceable>.efi.extra.d/*.raw</filename>
- are packed up as <command>cpio</command> archive and placed in the <filename>/.extra/sysext/</filename>
+ <listitem><para>Similarly, files <filename><replaceable>foo</replaceable>.efi.extra.d/*.raw</filename>
+ are packed up in a <command>cpio</command> archive and placed in the <filename>/.extra/sysext/</filename>
directory in the initrd file hierarchy. This is supposed to be used to pass additional system extension
images to the initrd. See
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details on system extension images. The generated <command>cpio</command> archive containing these
system extension images is measured into TPM PCR 8 (if a TPM is present).</para></listitem>
+
+ <listitem><para>Files <filename>/loader/credentials/*.cred</filename> are packed up in a
+ <command>cpio</command> archive and placed in the <filename>/.extra/global_credentials/</filename>
+ directory of the initrd file hierarchy. This is supposed to be used to pass additional credentials to
+ the initrd, regardless of the kernel being booted. The generated <command>cpio</command> archive is
+ measured into TPM PCR 4 (if a TPM is present)</para></listitem>
</itemizedlist>
- <para>Both mechanisms may be used to parameterize and extend trusted (i.e. signed), immutable initrd
+ <para>These mechanisms may be used to parameterize and extend trusted (i.e. signed), immutable initrd
images in a reasonably safe way: all data they contain is measured into TPM PCRs. On access they should be
further validated: in case of the credentials case by encrypting/authenticating them via TPM, as exposed
by <command>systemd-creds encrypt -T</command> (see
#include "measure.h"
#include "util.h"
-#define EXTRA_DIR_SUFFIX L".extra.d"
-
static CHAR8* write_cpio_word(CHAR8 *p, UINT32 v) {
static const char hex[] = "0123456789abcdef";
EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE *loaded_image,
+ const CHAR16 *dropin_dir,
const CHAR16 *match_suffix,
const CHAR8 *target_dir_prefix,
UINT32 dir_mode,
_cleanup_(FileHandleClosep) EFI_FILE_HANDLE root = NULL, extra_dir = NULL;
UINTN dirent_size = 0, buffer_size = 0, n_items = 0, n_allocated = 0;
- _cleanup_freepool_ CHAR16 *extra_dir_path = NULL;
+ _cleanup_freepool_ CHAR16 *rel_dropin_dir = NULL;
_cleanup_freepool_ EFI_FILE_INFO *dirent = NULL;
_cleanup_(strv_freep) CHAR16 **items = NULL;
_cleanup_freepool_ void *buffer = NULL;
if (!root)
return log_error_status_stall(EFI_LOAD_ERROR, L"Unable to open root directory.");
- extra_dir_path = xpool_print(L"%D" EXTRA_DIR_SUFFIX, loaded_image->FilePath);
- err = open_directory(root, extra_dir_path, &extra_dir);
+ if (!dropin_dir)
+ dropin_dir = rel_dropin_dir = xpool_print(L"%D.extra.d", loaded_image->FilePath);
+
+ err = open_directory(root, dropin_dir, &extra_dir);
if (err == EFI_NOT_FOUND) {
/* No extra subdir, that's totally OK */
*ret_buffer = NULL;
EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE *loaded_image,
+ const CHAR16 *dropin_dir,
const CHAR16 *match_suffix,
const CHAR8 *target_dir_prefix,
UINT32 dir_mode,
UINT32 access_mode,
- UINTN pcr,
+ UINTN tpm_pcr,
const CHAR16 *tpm_description,
void **ret_buffer,
UINTN *ret_buffer_size);
+
static EFI_STATUS combine_initrd(
EFI_PHYSICAL_ADDRESS initrd_base, UINTN initrd_size,
const void *credential_initrd, UINTN credential_initrd_size,
+ const void *global_credential_initrd, UINTN global_credential_initrd_size,
const void *sysext_initrd, UINTN sysext_initrd_size,
EFI_PHYSICAL_ADDRESS *ret_initrd_base, UINTN *ret_initrd_size) {
assert(ret_initrd_base);
assert(ret_initrd_size);
- /* Combines three initrds into one, by simple concatenation in memory */
+ /* Combines four initrds into one, by simple concatenation in memory */
n = ALIGN_TO(initrd_size, 4); /* main initrd might not be padded yet */
if (credential_initrd) {
n += credential_initrd_size;
}
+ if (global_credential_initrd) {
+ if (n > UINTN_MAX - global_credential_initrd_size)
+ return EFI_OUT_OF_RESOURCES;
+
+ n += global_credential_initrd_size;
+ }
if (sysext_initrd) {
if (n > UINTN_MAX - sysext_initrd_size)
return EFI_OUT_OF_RESOURCES;
p += credential_initrd_size;
}
+ if (global_credential_initrd) {
+ CopyMem(p, global_credential_initrd, global_credential_initrd_size);
+ p += global_credential_initrd_size;
+ }
+
if (sysext_initrd) {
CopyMem(p, sysext_initrd, sysext_initrd_size);
p += sysext_initrd_size;
};
UINTN cmdline_len = 0, linux_size, initrd_size, dt_size;
- UINTN credential_initrd_size = 0, sysext_initrd_size = 0;
- _cleanup_freepool_ void *credential_initrd = NULL, *sysext_initrd = NULL;
+ UINTN credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0;
+ _cleanup_freepool_ void *credential_initrd = NULL, *global_credential_initrd = NULL;
+ _cleanup_freepool_ void *sysext_initrd = NULL;
EFI_PHYSICAL_ADDRESS linux_base, initrd_base, dt_base;
_cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {};
EFI_LOADED_IMAGE *loaded_image;
export_variables(loaded_image);
(void) pack_cpio(loaded_image,
+ NULL,
L".cred",
(const CHAR8*) ".extra/credentials",
/* dir_mode= */ 0500,
&credential_initrd_size);
(void) pack_cpio(loaded_image,
+ L"\\loader\\credentials",
+ L".cred",
+ (const CHAR8*) ".extra/global_credentials",
+ /* dir_mode= */ 0500,
+ /* access_mode= */ 0400,
+ /* tpm_pcr= */ TPM_PCR_INDEX_KERNEL_PARAMETERS,
+ L"Global credentials initrd",
+ &global_credential_initrd,
+ &global_credential_initrd_size);
+
+ (void) pack_cpio(loaded_image,
+ NULL,
L".raw",
(const CHAR8*) ".extra/sysext",
/* dir_mode= */ 0555,
dt_size = szs[SECTION_DTB];
dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_DTB] : 0;
- if (credential_initrd || sysext_initrd) {
+ if (credential_initrd || global_credential_initrd || sysext_initrd) {
/* If we have generated initrds dynamically, let's combine them with the built-in initrd. */
err = combine_initrd(
initrd_base, initrd_size,
credential_initrd, credential_initrd_size,
+ global_credential_initrd, global_credential_initrd_size,
sysext_initrd, sysext_initrd_size,
&initrd_base, &initrd_size);
if (EFI_ERROR(err))
return err;
/* Given these might be large let's free them explicitly, quickly. */
- if (credential_initrd) {
- FreePool(credential_initrd);
- credential_initrd = NULL;
- }
-
- if (sysext_initrd) {
- FreePool(sysext_initrd);
- sysext_initrd = NULL;
- }
+ credential_initrd = mfree(credential_initrd);
+ global_credential_initrd = mfree(global_credential_initrd);
+ sysext_initrd = mfree(sysext_initrd);
}
if (dt_size > 0) {