| <?xml version='1.0'?> <!--*-nxml-*--> |
| <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" |
| "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
| <!-- SPDX-License-Identifier: LGPL-2.1-or-later --> |
| |
| <refentry id="systemd-stub" conditional='HAVE_GNU_EFI' |
| xmlns:xi="http://www.w3.org/2001/XInclude"> |
| <refentryinfo> |
| <title>systemd-stub</title> |
| <productname>systemd</productname> |
| </refentryinfo> |
| |
| <refmeta> |
| <refentrytitle>systemd-stub</refentrytitle> |
| <manvolnum>7</manvolnum> |
| </refmeta> |
| |
| <refnamediv> |
| <refname>systemd-stub</refname> |
| <refname>sd-stub</refname> |
| <refname>linuxx64.efi.stub</refname> |
| <refname>linuxia32.efi.stub</refname> |
| <refname>linuxaa64.efi.stub</refname> |
| <refpurpose>A simple UEFI kernel boot stub</refpurpose> |
| </refnamediv> |
| |
| <refsynopsisdiv> |
| <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>Description</title> |
| |
| <para><command>systemd-stub</command> (stored in per-architecture files |
| <filename>linuxx64.efi.stub</filename>, <filename>linuxia32.efi.stub</filename>, |
| <filename>linuxaa64.efi.stub</filename> on disk) is a simple UEFI boot stub. An UEFI boot stub is |
| attached to a Linux kernel binary image, and is a piece of code that runs in the UEFI firmware |
| environment before transitioning into the Linux kernel environment. The UEFI boot stub ensures a Linux |
| kernel is executable as regular UEFI binary, and is able to do various preparations before switching the |
| system into the Linux world.</para> |
| |
| <para>The UEFI boot stub looks for various resources for the kernel invocation inside the UEFI PE binary |
| itself. This allows combining various resources inside a single PE binary image (usually called "Unified |
| Kernel Image", or "UKI" for short), which may then be signed via UEFI SecureBoot as a whole, covering all |
| individual resources at once. Specifically it may include:</para> |
| |
| <itemizedlist> |
| <listitem><para>The ELF Linux kernel images will be looked for in the <literal>.linux</literal> PE |
| section of the executed image.</para></listitem> |
| |
| <listitem><para>OS release information, i.e. the |
| <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file of |
| the OS the kernel belongs to, in the <literal>.osrel</literal> PE section.</para></listitem> |
| |
| <listitem><para>The initrd will be loaded from the <literal>.initrd</literal> PE section. |
| </para></listitem> |
| |
| <listitem><para>A compiled binary DeviceTree will be looked for in the <literal>.dtb</literal> PE |
| section.</para></listitem> |
| |
| <listitem><para>The kernel command line to pass to the invoked kernel will be looked for in the |
| <literal>.cmdline</literal> PE section.</para></listitem> |
| |
| <listitem><para>A boot splash (in Windows <filename>.BMP</filename> format) to show on screen before |
| invoking the kernel will be looked for in the <literal>.splash</literal> PE section.</para></listitem> |
| |
| <listitem><para>A set of cryptographic signatures for expected TPM2 PCR values when this kernel is |
| booted, in JSON format, in the <literal>.pcrsig</literal> section. This is useful for implementing TPM2 |
| policies that bind disk encryption and similar to kernels that are signed by a specific |
| key.</para></listitem> |
| |
| <listitem><para>A public key in PEM format matching this TPM2 PCR signature data in the |
| <literal>.pcrpkey</literal> section.</para></listitem> |
| </itemizedlist> |
| |
| <para>If UEFI SecureBoot is enabled and the <literal>.cmdline</literal> section is present in the executed |
| image, any attempts to override the kernel command line by passing one as invocation parameters to the |
| EFI binary are ignored. Thus, in order to allow overriding the kernel command line, either disable UEFI |
| SecureBoot, or don't include a kernel command line PE section in the kernel image file. If a command line |
| is accepted via EFI invocation parameters to the EFI binary it is measured into TPM PCR 12 (if a TPM is |
| present).</para> |
| |
| <para>If a DeviceTree is embedded in the <literal>.dtb</literal> section, it replaces an existing |
| DeviceTree in the corresponding EFI configuration table. systemd-stub will ask the firmware via the |
| <literal>EFI_DT_FIXUP_PROTOCOL</literal> for hardware specific fixups to the DeviceTree.</para> |
| |
| <para>The contents of seven of these eight PE sections are measured into TPM PCR 11, that is otherwise |
| not used. Thus, it can be pre-calculated without too much effort. The <literal>.pcrsig</literal> section |
| is not included in this PCR measurement, since it's supposed to contain signatures for the expected |
| results for these measurements, i.e. of the outputs of the measurement operation, and thus cannot also be |
| input to it.</para> |
| |
| <para>When <literal>.pcrsig</literal> and/or <literal>.pcrpkey</literal> are present in a unified kernel |
| image their contents are passed to the booted kernel in an synthetic initrd cpio archive that places them in the |
| <filename>/.extra/tpm2-pcr-signature.json</filename> and |
| <filename>/.extra/tpm2-pcr-public-key.pem</filename> files. Typically, a |
| <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> line then |
| ensures they are copied into <filename>/run/systemd/tpm2-pcr-signature.json</filename> and |
| <filename>/run/systemd/tpm2-pcr-public-key.pem</filename> where they remain accessible even after the |
| system transitions out of the initrd environment into the host file system. Tools such |
| <citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, |
| <citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry> |
| and <citerefentry><refentrytitle>systemd-creds</refentrytitle><manvolnum>1</manvolnum></citerefentry> |
| will automatically use files present under these paths to unlock protected resources (encrypted storage |
| or credentials) or bind encryption to booted kernels.</para> |
| </refsect1> |
| |
| <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 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 |
| 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> |
| 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, |
| authenticated credentials for use with <varname>LoadCredentialEncrypted=</varname> in the UEFI System |
| Partition. See |
| <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> |
| and |
| <citerefentry><refentrytitle>systemd-creds</refentrytitle><manvolnum>1</manvolnum></citerefentry> |
| for |
| details on encrypted credentials. The generated <command>cpio</command> archive is measured into TPM |
| PCR 12 (if a TPM is present).</para></listitem> |
| |
| <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 13 (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 12 (if a TPM is present)</para></listitem> |
| </itemizedlist> |
| |
| <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 |
| <citerefentry><refentrytitle>systemd-creds</refentrytitle><manvolnum>1</manvolnum></citerefentry> for |
| details); in case of the system extension images by using signed Verity images.</para> |
| </refsect1> |
| |
| <refsect1> |
| <title>TPM PCR Notes</title> |
| |
| <para>Note that when a unified kernel using <command>systemd-stub</command> is invoked the firmware will |
| measure it as a whole to TPM PCR 4, covering all embedded resources, such as the stub code itself, the |
| core kernel, the embedded initrd and kernel command line (see above for a full list).</para> |
| |
| <para>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:</para> |
| |
| <table> |
| <title>OS Resource PCR Summary</title> |
| |
| <tgroup cols='2' align='left' colsep='1' rowsep='1'> |
| <colspec colname="pcr" /> |
| <colspec colname="definition" /> |
| |
| <thead> |
| <row> |
| <entry>OS Resource</entry> |
| <entry>Measurement PCR</entry> |
| </row> |
| </thead> |
| |
| <tbody> |
| <row> |
| <entry><command>systemd-stub</command> code (the entry point of the unified PE binary)</entry> |
| <entry>4</entry> |
| </row> |
| |
| <row> |
| <entry>Core kernel code (embedded in unified PE binary)</entry> |
| <entry>4 + 11</entry> |
| </row> |
| |
| <row> |
| <entry>OS release information (embedded in the unified PE binary)</entry> |
| <entry>4 + 11</entry> |
| </row> |
| |
| <row> |
| <entry>Main initrd (embedded in unified PE binary)</entry> |
| <entry>4 + 9 + 11</entry> |
| </row> |
| |
| <row> |
| <entry>Default kernel command line (embedded in unified PE binary)</entry> |
| <entry>4 + 11</entry> |
| </row> |
| |
| <row> |
| <entry>Overridden kernel command line</entry> |
| <entry>12</entry> |
| </row> |
| |
| <row> |
| <entry>Boot splash (embedded in the unified PE binary)</entry> |
| <entry>4 + 11</entry> |
| </row> |
| |
| <row> |
| <entry>TPM2 PCR signature JSON (embedded in unified PE binary, synthesized into initrd)</entry> |
| <entry>4 + 9</entry> |
| </row> |
| |
| <row> |
| <entry>TPM2 PCR PEM public key (embedded in unified PE binary, synthesized into initrd)</entry> |
| <entry>4 + 9 + 11</entry> |
| </row> |
| |
| <row> |
| <entry>Credentials (synthesized initrd from companion files)</entry> |
| <entry>9 + 12</entry> |
| </row> |
| |
| <row> |
| <entry>System Extensions (synthesized initrd from companion files)</entry> |
| <entry>9 + 13</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| </refsect1> |
| |
| <refsect1> |
| <title>EFI Variables</title> |
| |
| <para>The following EFI variables are defined, set and read by <command>systemd-stub</command>, under the |
| vendor UUID <literal>4a67b082-0a4c-41cf-b6c7-440b29bb8c4f</literal>, for communication between the boot |
| stub and the OS:</para> |
| |
| <variablelist class='efi-variables'> |
| <varlistentry> |
| <term><varname>LoaderDevicePartUUID</varname></term> |
| |
| <listitem><para>Contains the partition UUID of the EFI System Partition the EFI image was run |
| from. <citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry> |
| uses this information to automatically find the disk booted from, in order to discover various other |
| partitions on the same disk automatically.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><varname>LoaderFirmwareInfo</varname></term> |
| <term><varname>LoaderFirmwareType</varname></term> |
| |
| <listitem><para>Brief firmware information. Use |
| <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> to view this |
| data.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><varname>LoaderImageIdentifier</varname></term> |
| |
| <listitem><para>The path of EFI executable, relative to the EFI System Partition's root |
| directory. Use |
| <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> to view |
| this data.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><varname>StubInfo</varname></term> |
| |
| <listitem><para>Brief stub information. Use |
| <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> to view |
| this data.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><varname>StubPcrKernelImage</varname></term> |
| |
| <listitem><para>The PCR register index the kernel image, initrd image, boot splash, devicetree |
| database, and the embedded command line are measured into, formatted as decimal ASCII string (e.g. |
| <literal>11</literal>). This variable is set if a measurement was successfully completed, and remains |
| unset otherwise.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><varname>StubPcrKernelParameters</varname></term> |
| |
| <listitem><para>The PCR register index the kernel command line and credentials are measured into, |
| formatted as decimal ASCII string (e.g. <literal>12</literal>). This variable is set if a measurement |
| was successfully completed, and remains unset otherwise.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><varname>StubPcrInitRDSysExts</varname></term> |
| |
| <listitem><para>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. |
| <literal>13</literal>). This variable is set if a measurement was successfully completed, and remains |
| unset otherwise.</para></listitem> |
| </varlistentry> |
| </variablelist> |
| |
| <para>Note that some of the variables above may also be set by the boot loader. The stub will only set |
| them if they aren't set already. Some of these variables are defined by the <ulink |
| url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>.</para> |
| </refsect1> |
| |
| <refsect1> |
| <title>initrd Resources</title> |
| |
| <para>The following resources are passed as initrd cpio archives to the booted kernel, and thus make up |
| the initial file system hierarchy in the initrd execution environment:</para> |
| |
| <variablelist> |
| <varlistentry> |
| <term><filename>/</filename></term> |
| |
| <listitem><para>The main initrd from the <literal>.initrd</literal> PE section of the unified kernel image.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><filename>/.extra/credentials/*.cred</filename></term> |
| <listitem><para>Credential files (suffix <literal>.cred</literal>) that are placed next to the |
| unified kernel image (as described above) are copied into the |
| <filename>/.extra/credentials/</filename> directory in the initrd execution |
| environment.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><filename>/.extra/global_credentials/*.cred</filename></term> |
| <listitem><para>Similar, credential files in the <filename>/loader/credentials/</filename> directory |
| in the file system the unified kernel image is placed in are copied into the |
| <filename>/.extra/global_credentials/</filename> directory in the initrd execution |
| environment.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><filename>/.extra/sysext/*.raw</filename></term> |
| <listitem><para>System extension image files (suffix <literal>.raw</literal>) that are placed next to |
| the unified kernel image (as described above) are copied into the |
| <filename>/.extra/sysext/</filename> directory in the initrd execution environment.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><filename>/.extra/tpm2-pcr-signature.json</filename></term> |
| <listitem><para>The TPM2 PCR signature JSON object included in the <literal>.pcrsig</literal> PE |
| section of the unified kernel image is copied into the |
| <filename>/.extra/tpm2-pcr-signature.json</filename> file in the initrd execution |
| environment.</para></listitem> |
| </varlistentry> |
| |
| <varlistentry> |
| <term><filename>/.extra/tpm2-pcr-pkey.pem</filename></term> |
| <listitem><para>The PEM public key included in the <literal>.pcrpkey</literal> PE section of the |
| unified kernel image is copied into the <filename>/.extra/tpm2-pcr-public-key.pem</filename> file in |
| the initrd execution environment.</para></listitem> |
| </varlistentry> |
| </variablelist> |
| |
| <para>Note that all these files are located in the <literal>tmpfs</literal> file system the kernel sets |
| up for the initrd file hierarchy and are thus lost when the system transitions from the initrd execution |
| environment into the host file system. If these resources shall be kept around over this transition they |
| need to be copied to a place that survives the transition first, for example via a suitable |
| <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> line. By |
| default, this is done for the TPM2 PCR signature and public key files.</para> |
| </refsect1> |
| |
| <refsect1> |
| <title>Assembling Kernel Images</title> |
| |
| <para>In order to assemble a bootable Unified Kernel Image from various components as described above, use |
| <citerefentry><refentrytitle>ukify</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para> |
| </refsect1> |
| |
| <refsect1> |
| <title>See Also</title> |
| <para> |
| <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>, |
| <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>, |
| <citerefentry><refentrytitle>systemd-creds</refentrytitle><manvolnum>1</manvolnum></citerefentry>, |
| <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>, |
| <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot Loader Specification</ulink>, |
| <ulink url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>, |
| <citerefentry><refentrytitle>ukify</refentrytitle><manvolnum>1</manvolnum></citerefentry>, |
| <citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry> |
| </para> |
| </refsect1> |
| </refentry> |