From 33832de101e9f133cdf9b7321f6f8976a3ddf8d4 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 14 Jun 2019 12:12:44 +0200 Subject: [PATCH] admin: Add an esp-upgrade subcommand The files in the EFI System Partition (ESP) are never updated by OSTree so users will always have the same ESP that was created during installation. This happens because the ESP uses a vfat filesystem, which doesn't support symbolic links so the update can't be atomic and part of the transaction. But since the ESP contains the bootloader components (shim, grub, etc) and other important EFI binaries like the ones needed for firmware updates, it should be a way to update the ESP with the latest version of the binaries. These components are stored in the /usr/lib/ostree-boot/efi directory of a deployment due rpm-ostree replacing the /boot path to /usr/lib/ostree-boot. Add a ostree-admin-esp-upgrade subcommand, that just copies the content of /usr/lib/ostree-boot/efi to /boot/efi, so users can update the ESP and get the latest version of the files that are present in the booted deployment. Closes: #1649 --- Makefile-man.am | 2 +- Makefile-ostree.am | 1 + man/ostree-admin-esp-upgrade.xml | 70 +++++++++++++++ src/ostree/ot-admin-builtin-esp-upgrade.c | 102 ++++++++++++++++++++++ src/ostree/ot-admin-builtins.h | 1 + src/ostree/ot-builtin-admin.c | 3 + 6 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 man/ostree-admin-esp-upgrade.xml create mode 100644 src/ostree/ot-admin-builtin-esp-upgrade.c diff --git a/Makefile-man.am b/Makefile-man.am index 8ccbba8c6e..fee5b89721 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -26,7 +26,7 @@ ostree-admin-config-diff.1 ostree-admin-deploy.1 \ ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-os-init.1 \ ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \ ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \ -ostree-admin-pin.1 \ +ostree-admin-pin.1 ostree-admin-esp-upgrade.1 \ ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \ ostree-commit.1 ostree-create-usb.1 ostree-export.1 ostree-gpg-sign.1 \ ostree-config.1 ostree-diff.1 ostree-find-remotes.1 ostree-fsck.1 \ diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 8d352e38fd..7ae761eb3b 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -79,6 +79,7 @@ ostree_SOURCES += \ src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-switch.c \ src/ostree/ot-admin-builtin-pin.c \ + src/ostree/ot-admin-builtin-esp-upgrade.c \ src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-unlock.c \ src/ostree/ot-admin-builtins.h \ diff --git a/man/ostree-admin-esp-upgrade.xml b/man/ostree-admin-esp-upgrade.xml new file mode 100644 index 0000000000..ef6c79ed6d --- /dev/null +++ b/man/ostree-admin-esp-upgrade.xml @@ -0,0 +1,70 @@ + + + + + + + + + ostree admin esp-upgrade + OSTree + + + + Developer + Javier + Martinez Canillas + javierm@redhat.com + + + + + + ostree admin esp-upgrade + 1 + + + + ostree-admin-esp-upgrade + Upgrade the EFI System Partition (ESP) with files from the current deployment + + + + + ostree admin esp-upgrade + + + + + Description + + + Upgrade the EFI System Partition (ESP) with the files in the /usr/lib/ostree-boot/efi/ directory of the current deployment. + + + + + Example + $ ostree admin esp-upgrade + + diff --git a/src/ostree/ot-admin-builtin-esp-upgrade.c b/src/ostree/ot-admin-builtin-esp-upgrade.c new file mode 100644 index 0000000000..94f6a2c6dc --- /dev/null +++ b/src/ostree/ot-admin-builtin-esp-upgrade.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 Red Hat, Inc. + * + * SPDX-License-Identifier: LGPL-2.0+ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Javier Martinez Canillas + */ + +#include "config.h" + +#include "ostree-sysroot-private.h" +#include "ot-main.h" +#include "ot-admin-builtins.h" +#include "ot-admin-functions.h" +#include "otutil.h" + +static GOptionEntry options[] = { + { NULL } +}; + +gboolean +ot_admin_builtin_esp_upgrade (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) +{ + g_autoptr(GOptionContext) context = g_option_context_new (""); + + g_autoptr(OstreeSysroot) sysroot = NULL; + if (!ostree_admin_option_context_parse (context, options, &argc, &argv, + OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED, + invocation, &sysroot, cancellable, error)) + return FALSE; + + g_autoptr(OstreeRepo) repo = NULL; + if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) + return FALSE; + + g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot); + OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); + + g_autoptr(OstreeDeployment) pending_deployment = NULL; + g_autoptr(OstreeDeployment) rollback_deployment = NULL; + if (booted_deployment) + ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment, + &rollback_deployment); + + if (deployments->len == 0) + { + g_print ("No deployments.\n"); + return TRUE; + } + + struct stat stbuf; + + if (!glnx_fstatat_allow_noent (sysroot->sysroot_fd, "/sys/firmware/efi", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + + if (errno == ENOENT) + { + g_print ("Not an EFI installation.\n"); + return TRUE; + } + + if (!ot_is_rw_mount ("/boot/efi")) + { + g_print ("Only ESP mounted in /boot/efi is supported.\n"); + return TRUE; + } + + g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (sysroot, booted_deployment); + g_autofree char *new_esp_path = g_strdup_printf ("%s/usr/lib/ostree-boot", deployment_path); + + GLNX_AUTO_PREFIX_ERROR ("During copy files to the ESP", error); + glnx_autofd int old_esp_fd = -1; + if (!glnx_opendirat (sysroot->sysroot_fd, "/boot", TRUE, &old_esp_fd, error)) + return FALSE; + + glnx_autofd int new_esp_fd = -1; + if (!glnx_opendirat (sysroot->sysroot_fd, new_esp_path, TRUE, &new_esp_fd, error)) + return FALSE; + + /* The ESP filesystem is vfat so don't attempt to copy ownership, mode, and xattrs */ + const OstreeSysrootDebugFlags flags = sysroot->debug_flags | OSTREE_SYSROOT_DEBUG_NO_XATTRS; + + if (!ot_copy_dir_recurse (new_esp_fd, old_esp_fd, "efi", flags , cancellable, error)) + return FALSE; + + return TRUE; +} diff --git a/src/ostree/ot-admin-builtins.h b/src/ostree/ot-admin-builtins.h index d88fc0b907..5efb7101b0 100644 --- a/src/ostree/ot-admin-builtins.h +++ b/src/ostree/ot-admin-builtins.h @@ -40,6 +40,7 @@ BUILTINPROTO(undeploy); BUILTINPROTO(deploy); BUILTINPROTO(cleanup); BUILTINPROTO(pin); +BUILTINPROTO(esp_upgrade); BUILTINPROTO(finalize_staged); BUILTINPROTO(unlock); BUILTINPROTO(status); diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c index 9f1a61562a..0de2ac7199 100644 --- a/src/ostree/ot-builtin-admin.c +++ b/src/ostree/ot-builtin-admin.c @@ -57,6 +57,9 @@ static OstreeCommand admin_subcommands[] = { { "pin", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_pin, "Change the \"pinning\" state of a deployment" }, + { "esp-upgrade", OSTREE_BUILTIN_FLAG_NO_REPO, + ot_admin_builtin_esp_upgrade, + "Upgrade the ESP with the files on the current deployment" }, { "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_set_origin, "Set Origin and create a new origin file" },