Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an ostree-admin-esp-upgrade subcommand to update the EFI System Partition #1873

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile-man.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
1 change: 1 addition & 0 deletions Makefile-ostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
1 change: 1 addition & 0 deletions Makefile-tests.am
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ _installed_or_uninstalled_test_scripts = \
tests/test-admin-deploy-karg.sh \
tests/test-admin-deploy-switch.sh \
tests/test-admin-deploy-etcmerge-cornercases.sh \
tests/test-admin-esp-upgrade.sh \
tests/test-admin-deploy-uboot.sh \
tests/test-admin-deploy-grub2.sh \
tests/test-admin-deploy-none.sh \
Expand Down
70 changes: 70 additions & 0 deletions man/ostree-admin-esp-upgrade.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<!--
Copyright 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.
-->

<refentry id="ostree">

<refentryinfo>
<title>ostree admin esp-upgrade</title>
<productname>OSTree</productname>

<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Javier</firstname>
<surname>Martinez Canillas</surname>
<email>[email protected]</email>
</author>
</authorgroup>
</refentryinfo>

<refmeta>
<refentrytitle>ostree admin esp-upgrade</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>

<refnamediv>
<refname>ostree-admin-esp-upgrade</refname>
<refpurpose>Upgrade the EFI System Partition (ESP) with files from the current deployment</refpurpose>
</refnamediv>

<refsynopsisdiv>
<cmdsynopsis>
<command>ostree admin esp-upgrade</command>
</cmdsynopsis>
</refsynopsisdiv>

<refsect1>
<title>Description</title>

<para>
Upgrade the EFI System Partition (ESP) with the files in the /usr/lib/ostree-boot/efi directory of the current deployment.
</para>
</refsect1>

<refsect1>
<title>Example</title>
<para><command>$ ostree admin esp-upgrade</command></para>
</refsect1>
</refentry>
171 changes: 6 additions & 165 deletions src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,12 @@
#include <gio/gunixoutputstream.h>
#include <glib-unix.h>
#include <sys/mount.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <linux/fs.h>
#include <err.h>

#ifdef HAVE_LIBMOUNT
#include <libmount.h>
#endif
#ifdef HAVE_LIBSYSTEMD
#include <systemd/sd-journal.h>
#endif
Expand Down Expand Up @@ -86,15 +82,6 @@ symlink_at_replace (const char *oldpath,
return TRUE;
}

static GLnxFileCopyFlags
sysroot_flags_to_copy_flags (GLnxFileCopyFlags defaults,
OstreeSysrootDebugFlags sysrootflags)
{
if (sysrootflags & OSTREE_SYSROOT_DEBUG_NO_XATTRS)
defaults |= GLNX_FILE_COPY_NOXATTRS;
return defaults;
}

/* Try a hardlink if we can, otherwise fall back to copying. Used
* right now for kernels/initramfs/device trees in /boot, where we can just
* hardlink if we're on the same partition.
Expand Down Expand Up @@ -139,101 +126,6 @@ install_into_boot (OstreeSePolicy *sepolicy,
return TRUE;
}

/* Copy ownership, mode, and xattrs from source directory to destination */
static gboolean
dirfd_copy_attributes_and_xattrs (int src_parent_dfd,
const char *src_name,
int src_dfd,
int dest_dfd,
OstreeSysrootDebugFlags flags,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GVariant) xattrs = NULL;

/* Clone all xattrs first, so we get the SELinux security context
* right. This will allow other users access if they have ACLs, but
* oh well.
*/
if (!(flags & OSTREE_SYSROOT_DEBUG_NO_XATTRS))
{
if (!glnx_dfd_name_get_all_xattrs (src_parent_dfd, src_name,
&xattrs, cancellable, error))
return FALSE;
if (!glnx_fd_set_all_xattrs (dest_dfd, xattrs,
cancellable, error))
return FALSE;
}

struct stat src_stbuf;
if (!glnx_fstat (src_dfd, &src_stbuf, error))
return FALSE;
if (fchown (dest_dfd, src_stbuf.st_uid, src_stbuf.st_gid) != 0)
return glnx_throw_errno_prefix (error, "fchown");
if (fchmod (dest_dfd, src_stbuf.st_mode) != 0)
return glnx_throw_errno_prefix (error, "fchmod");

return TRUE;
}

static gboolean
copy_dir_recurse (int src_parent_dfd,
int dest_parent_dfd,
const char *name,
OstreeSysrootDebugFlags flags,
GCancellable *cancellable,
GError **error)
{
g_auto(GLnxDirFdIterator) src_dfd_iter = { 0, };
glnx_autofd int dest_dfd = -1;
struct dirent *dent;

if (!glnx_dirfd_iterator_init_at (src_parent_dfd, name, TRUE, &src_dfd_iter, error))
return FALSE;

/* Create with mode 0700, we'll fchmod/fchown later */
if (!glnx_ensure_dir (dest_parent_dfd, name, 0700, error))
return FALSE;

if (!glnx_opendirat (dest_parent_dfd, name, TRUE, &dest_dfd, error))
return FALSE;

if (!dirfd_copy_attributes_and_xattrs (src_parent_dfd, name, src_dfd_iter.fd, dest_dfd,
flags, cancellable, error))
return FALSE;

while (TRUE)
{
struct stat child_stbuf;

if (!glnx_dirfd_iterator_next_dent (&src_dfd_iter, &dent, cancellable, error))
return FALSE;
if (dent == NULL)
break;

if (!glnx_fstatat (src_dfd_iter.fd, dent->d_name, &child_stbuf,
AT_SYMLINK_NOFOLLOW, error))
return FALSE;

if (S_ISDIR (child_stbuf.st_mode))
{
if (!copy_dir_recurse (src_dfd_iter.fd, dest_dfd, dent->d_name,
flags, cancellable, error))
return FALSE;
}
else
{
if (!glnx_file_copy_at (src_dfd_iter.fd, dent->d_name, &child_stbuf,
dest_dfd, dent->d_name,
sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags),
cancellable, error))
return FALSE;
}
}

return TRUE;
}

/* If a chain of directories is added, this function will ensure
* they're created.
*/
Expand Down Expand Up @@ -290,8 +182,8 @@ ensure_directory_from_template (int orig_etc_fd,
if (!glnx_opendirat (new_etc_fd, path, TRUE, &target_dfd, error))
return FALSE;

if (!dirfd_copy_attributes_and_xattrs (modified_etc_fd, path, src_dfd, target_dfd,
flags, cancellable, error))
if (!ot_dirfd_copy_attributes_and_xattrs (modified_etc_fd, path, src_dfd, target_dfd,
flags, cancellable, error))
return FALSE;

if (out_dfd)
Expand Down Expand Up @@ -365,15 +257,15 @@ copy_modified_config_file (int orig_etc_fd,

if (S_ISDIR (modified_stbuf.st_mode))
{
if (!copy_dir_recurse (modified_etc_fd, new_etc_fd, path, flags,
cancellable, error))
if (!ot_copy_dir_recurse (modified_etc_fd, new_etc_fd, path, flags,
cancellable, error))
return FALSE;
}
else if (S_ISLNK (modified_stbuf.st_mode) || S_ISREG (modified_stbuf.st_mode))
{
if (!glnx_file_copy_at (modified_etc_fd, path, &modified_stbuf,
new_etc_fd, path,
sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags),
ot_sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags),
cancellable, error))
return FALSE;
}
Expand Down Expand Up @@ -1979,57 +1871,6 @@ cleanup_legacy_current_symlinks (OstreeSysroot *self,
return TRUE;
}

/* Detect whether or not @path refers to a read-only mountpoint. This is
* currently just used to handle a potentially read-only /boot by transiently
* remounting it read-write. In the future we might also do this for e.g.
* /sysroot.
*/
static gboolean
is_ro_mount (const char *path)
{
#ifdef HAVE_LIBMOUNT
/* Dragging in all of this crud is apparently necessary just to determine
* whether something is a mount point.
*
* Systemd has a totally different implementation in
* src/basic/mount-util.c.
*/
struct libmnt_table *tb = mnt_new_table_from_file ("/proc/self/mountinfo");
struct libmnt_fs *fs;
struct libmnt_cache *cache;
gboolean is_mount = FALSE;
struct statvfs stvfsbuf;

if (!tb)
return FALSE;

/* to canonicalize all necessary paths */
cache = mnt_new_cache ();
mnt_table_set_cache (tb, cache);

fs = mnt_table_find_target(tb, path, MNT_ITER_BACKWARD);
is_mount = fs && mnt_fs_get_target (fs);
#ifdef HAVE_MNT_UNREF_CACHE
mnt_unref_table (tb);
mnt_unref_cache (cache);
#else
mnt_free_table (tb);
mnt_free_cache (cache);
#endif

if (!is_mount)
return FALSE;

/* We *could* parse the options, but it seems more reliable to
* introspect the actual mount at runtime.
*/
if (statvfs (path, &stvfsbuf) == 0)
return (stvfsbuf.f_flag & ST_RDONLY) != 0;

#endif
return FALSE;
}

/**
* ostree_sysroot_write_deployments:
* @self: Sysroot
Expand Down Expand Up @@ -2331,7 +2172,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
{
gboolean boot_was_ro_mount = FALSE;
if (self->booted_deployment)
boot_was_ro_mount = is_ro_mount ("/boot");
boot_was_ro_mount = ot_is_ro_mount ("/boot");

g_debug ("boot is ro: %s", boot_was_ro_mount ? "yes" : "no");

Expand Down
13 changes: 0 additions & 13 deletions src/libostree/ostree-sysroot-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,6 @@

G_BEGIN_DECLS

typedef enum {

/* Don't flag deployments as immutable. */
OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS = 1 << 0,
/* See https://github.com/ostreedev/ostree/pull/759 */
OSTREE_SYSROOT_DEBUG_NO_XATTRS = 1 << 1,
/* https://github.com/ostreedev/ostree/pull/1049 */
OSTREE_SYSROOT_DEBUG_TEST_FIFREEZE = 1 << 2,
/* This is a temporary flag until we fully drop the explicit `systemctl start
* ostree-finalize-staged.service` so that tests can exercise the new path unit. */
OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH = 1 << 3,
} OstreeSysrootDebugFlags;

/**
* OstreeSysroot:
* Internal struct
Expand Down
Loading