mirror of
https://github.com/systemd/systemd
synced 2024-11-02 19:41:12 +00:00
stub: Load credentials from \loader\credentials\*.cred
Some types of credentials that a user would want to pass into the initrd do not depend on the specific kernel/initrd version. For instance, this can include SSH keys, rootfs encryption keys, dm-integrity keys, and so on. This introduces a directory where such credentials can be placed so that any kernel image will load them
This commit is contained in:
parent
bf3f4d16d6
commit
f3b6f33387
4 changed files with 60 additions and 26 deletions
|
@ -27,6 +27,9 @@
|
|||
<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>
|
||||
|
@ -78,13 +81,14 @@
|
|||
<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,
|
||||
|
@ -94,16 +98,22 @@
|
|||
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
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#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";
|
||||
|
||||
|
@ -308,6 +306,7 @@ static EFI_STATUS pack_cpio_trailer(
|
|||
|
||||
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,
|
||||
|
@ -319,7 +318,7 @@ EFI_STATUS pack_cpio(
|
|||
|
||||
_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;
|
||||
|
@ -335,8 +334,10 @@ EFI_STATUS pack_cpio(
|
|||
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;
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ _used_ _section_(".sdmagic") static const char magic[] = "#### LoaderInfo: syste
|
|||
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) {
|
||||
|
||||
|
@ -31,7 +32,7 @@ static EFI_STATUS combine_initrd(
|
|||
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) {
|
||||
|
@ -40,6 +41,12 @@ static EFI_STATUS combine_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;
|
||||
|
@ -76,6 +83,11 @@ static EFI_STATUS combine_initrd(
|
|||
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;
|
||||
|
@ -156,8 +168,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|||
};
|
||||
|
||||
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;
|
||||
|
@ -213,6 +226,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|||
export_variables(loaded_image);
|
||||
|
||||
(void) pack_cpio(loaded_image,
|
||||
NULL,
|
||||
L".cred",
|
||||
(const CHAR8*) ".extra/credentials",
|
||||
/* dir_mode= */ 0500,
|
||||
|
@ -223,6 +237,18 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|||
&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,
|
||||
|
@ -241,26 +267,21 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|||
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) {
|
||||
|
|
Loading…
Reference in a new issue