Skip to content

Commit

Permalink
deploy: Handle efi blobs
Browse files Browse the repository at this point in the history
We can now deploy our custom initramfs + kernel efi blobs.

This will only happen when we're running in a PAYG system
(ie: the kernel cmdline contains eospayg) or when we set
the env var OSTREE_DEPLOY_PAYG to force PAYG deployment
during image build.

https://phabricator.endlessm.com/T27521

Rebase 2020.8 (T31593): Fix conflicts from upstream overlay_initrds
  feature and dropping flags argument to install_into_boot(). Added a
  couple more `!payg` to ensure other boot artifacts aren't installed.
  • Loading branch information
Derek Foreman authored and dbnicholson committed Mar 19, 2021
1 parent 052f2fd commit 09b24be
Showing 1 changed file with 99 additions and 30 deletions.
129 changes: 99 additions & 30 deletions src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,8 @@ typedef struct {
char *initramfs_namever;
char *devicetree_srcpath;
char *devicetree_namever;
char *efi_blob_srcpath;
char *efi_blob_namever;
char *bootcsum;
} OstreeKernelLayout;
static void
Expand All @@ -1069,6 +1071,8 @@ _ostree_kernel_layout_free (OstreeKernelLayout *layout)
g_free (layout->initramfs_namever);
g_free (layout->devicetree_srcpath);
g_free (layout->devicetree_namever);
g_free (layout->efi_blob_srcpath);
g_free (layout->efi_blob_namever);
g_free (layout->bootcsum);
g_free (layout);
}
Expand Down Expand Up @@ -1232,6 +1236,15 @@ get_kernel_from_tree_usrlib_modules (OstreeSysroot *sysroot,
g_clear_object (&in);
glnx_close_fd (&fd);

if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "payg-image.efi", &fd, error))
return FALSE;
if (fd != -1)
{
ret_layout->efi_blob_srcpath = g_strdup ("payg-image.efi");
ret_layout->efi_blob_namever = g_strdup_printf ("payg-image-%s.efi", kver);
}
glnx_close_fd (&fd);

/* And finally, look for any HMAC file. This is needed for FIPS mode on some distros. */
if (!glnx_fstatat_allow_noent (ret_layout->boot_dfd, ".vmlinuz.hmac", NULL, 0, error))
return FALSE;
Expand Down Expand Up @@ -1793,6 +1806,26 @@ parse_os_release (const char *contents,
return ret;
}

static gboolean
is_payg_deployment(GCancellable *cancellable)
{
g_autoptr(GFile) cmdline_file = g_file_new_for_path ("/proc/cmdline");
g_autofree char *cmdline = NULL;
gsize cmdline_len;

if (g_getenv ("OSTREE_DEPLOY_PAYG"))
return TRUE;

if (!g_file_load_contents (cmdline_file, cancellable,
&cmdline, &cmdline_len, NULL, NULL))
return FALSE;

if (g_strstr_len (cmdline, cmdline_len, "eospayg"))
return TRUE;

return FALSE;
}

/* Given @deployment, prepare it to be booted; basically copying its
* kernel/initramfs into /boot/ostree (if needed) and writing out an entry in
* /boot/loader/entries.
Expand All @@ -1808,6 +1841,8 @@ install_deployment_kernel (OstreeSysroot *sysroot,
GError **error)

{
gboolean payg;

GLNX_AUTO_PREFIX_ERROR ("Installing kernel", error);
OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment);
g_autofree char *deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, deployment);
Expand Down Expand Up @@ -1848,24 +1883,46 @@ install_deployment_kernel (OstreeSysroot *sysroot,
if (!glnx_shutil_mkdir_p_at (boot_dfd, bootconfdir, 0775, cancellable, error))
return FALSE;

struct stat stbuf;
/* If this is a payg deployment, we want the efi blob and nothing else */
payg = kernel_layout->efi_blob_srcpath && is_payg_deployment(cancellable);
/* If we're updating an old loader entry that doesn't use efi blobs
* keep it the way it was. */
payg = payg && !ostree_bootconfig_parser_get (bootconfig, "linux");
if (payg)
{
g_assert (kernel_layout->efi_blob_namever);
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->efi_blob_namever, &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
{
if (!install_into_boot (repo, sepolicy, kernel_layout->boot_dfd, kernel_layout->efi_blob_srcpath,
bootcsum_dfd, kernel_layout->efi_blob_namever,
cancellable, error))
return FALSE;
}
}

/* Install (hardlink/copy) the kernel into /boot/ostree/osname-${bootcsum} if
* it doesn't exist already.
*/
struct stat stbuf;
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->kernel_namever, &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
if (!payg)
{
if (!install_into_boot (repo, sepolicy, kernel_layout->boot_dfd, kernel_layout->kernel_srcpath,
bootcsum_dfd, kernel_layout->kernel_namever,
cancellable, error))
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->kernel_namever, &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
{
if (!install_into_boot (repo, sepolicy, kernel_layout->boot_dfd, kernel_layout->kernel_srcpath,
bootcsum_dfd, kernel_layout->kernel_namever,
cancellable, error))
return FALSE;
}
}

/* If we have an initramfs, then install it into
* /boot/ostree/osname-${bootcsum} if it doesn't exist already.
*/
if (kernel_layout->initramfs_srcpath)
if (kernel_layout->initramfs_srcpath && !payg)
{
g_assert (kernel_layout->initramfs_namever);
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->initramfs_namever, &stbuf, 0, error))
Expand All @@ -1879,7 +1936,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
}
}

if (kernel_layout->devicetree_srcpath)
if (kernel_layout->devicetree_srcpath && !payg)
{
/* If devicetree_namever is set a single device tree is deployed */
if (kernel_layout->devicetree_namever)
Expand All @@ -1902,7 +1959,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
}
}

if (kernel_layout->kernel_hmac_srcpath)
if (kernel_layout->kernel_hmac_srcpath && !payg)
{
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->kernel_hmac_namever, &stbuf, 0, error))
return FALSE;
Expand All @@ -1916,7 +1973,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
}

g_autoptr(GPtrArray) overlay_initrds = NULL;
for (char **it = _ostree_deployment_get_overlay_initrds (deployment); it && *it; it++)
for (char **it = _ostree_deployment_get_overlay_initrds (deployment); !payg && it && *it; it++)
{
char *checksum = *it;

Expand Down Expand Up @@ -2024,39 +2081,45 @@ install_deployment_kernel (OstreeSysroot *sysroot,

g_autofree char *version_key = g_strdup_printf ("%d", n_deployments - ostree_deployment_get_index (deployment));
ostree_bootconfig_parser_set (bootconfig, OSTREE_COMMIT_META_KEY_VERSION, version_key);
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->kernel_namever, NULL);
ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath);

if (!payg)
{
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->kernel_namever, NULL);
ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath);
}

val = ostree_bootconfig_parser_get (bootconfig, "options");
g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_from_string (val);

if (kernel_layout->initramfs_namever)
if (!payg)
{
g_autofree char * initrd_boot_relpath =
g_strconcat ("/", bootcsumdir, "/", kernel_layout->initramfs_namever, NULL);
ostree_bootconfig_parser_set (bootconfig, "initrd", initrd_boot_relpath);
if (kernel_layout->initramfs_namever)
{
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->initramfs_namever, NULL);
ostree_bootconfig_parser_set (bootconfig, "initrd", boot_relpath);

if (overlay_initrds)
if (overlay_initrds)
{
g_ptr_array_add (overlay_initrds, NULL);
ostree_bootconfig_parser_set_overlay_initrds (bootconfig, (char**)overlay_initrds->pdata);
}
}
else
{
g_ptr_array_add (overlay_initrds, NULL);
ostree_bootconfig_parser_set_overlay_initrds (bootconfig, (char**)overlay_initrds->pdata);
g_autofree char *prepare_root_arg = NULL;
prepare_root_arg = g_strdup_printf ("init=/ostree/boot.%d/%s/%s/%d/usr/lib/ostree/ostree-prepare-root",
new_bootversion, osname, bootcsum,
ostree_deployment_get_bootserial (deployment));
ostree_kernel_args_replace_take (kargs, g_steal_pointer (&prepare_root_arg));
}
}
else
{
g_autofree char *prepare_root_arg = NULL;
prepare_root_arg = g_strdup_printf ("init=/ostree/boot.%d/%s/%s/%d/usr/lib/ostree/ostree-prepare-root",
new_bootversion, osname, bootcsum,
ostree_deployment_get_bootserial (deployment));
ostree_kernel_args_replace_take (kargs, g_steal_pointer (&prepare_root_arg));
}

if (kernel_layout->devicetree_namever)
if (kernel_layout->devicetree_namever && !payg)
{
g_autofree char * dt_boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL);
ostree_bootconfig_parser_set (bootconfig, "devicetree", dt_boot_relpath);
}
else if (kernel_layout->devicetree_srcpath)
else if (kernel_layout->devicetree_srcpath && !payg)
{
/* If devicetree_srcpath is set but devicetree_namever is NULL, then we
* want to point to a whole directory of device trees.
Expand All @@ -2066,6 +2129,12 @@ install_deployment_kernel (OstreeSysroot *sysroot,
ostree_bootconfig_parser_set (bootconfig, "fdtdir", dt_boot_relpath);
}

if (payg)
{
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->efi_blob_namever, NULL);
ostree_bootconfig_parser_set (bootconfig, "efi", boot_relpath);
}

/* Note this is parsed in ostree-impl-system-generator.c */
g_autofree char *ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d",
new_bootversion, osname, bootcsum,
Expand Down

0 comments on commit 09b24be

Please sign in to comment.