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 ostree admin post-copy command #3094

Merged
merged 1 commit into from
Nov 14, 2023
Merged
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
6 changes: 3 additions & 3 deletions Makefile-libostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ endif # USE_GPGME
symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym

# Uncomment this include when adding new development symbols.
#if BUILDOPT_IS_DEVEL_BUILD
#symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym
#endif
if BUILDOPT_IS_DEVEL_BUILD
symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym
endif

# http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html
wl_versionscript_arg = -Wl,--version-script=
Expand Down
2 changes: 1 addition & 1 deletion Makefile-man.am
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ ostree-admin-config-diff.1 ostree-admin-deploy.1 \
ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-stateroot-init.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-set-default.1 \
ostree-admin-pin.1 ostree-admin-post-copy.1 ostree-admin-set-default.1 \
ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \
ostree-commit.1 ostree-create-usb.1 ostree-export.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 @@ -81,6 +81,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-post-copy.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 apidoc/ostree-sections.txt
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ ostree_sysroot_lock_async
ostree_sysroot_lock_finish
ostree_sysroot_unlock
ostree_sysroot_unload
ostree_sysroot_update_post_copy
ostree_sysroot_set_mount_namespace_in_use
ostree_sysroot_is_booted
ostree_sysroot_get_fd
Expand Down
4 changes: 4 additions & 0 deletions man/index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
<refentrytitle>ostree-admin-pin</refentrytitle><manvolnum>1</manvolnum>
</citerefentry></primaryie></indexentry>

<indexentry><primaryie><citerefentry>
<refentrytitle>ostree-admin-post-copy</refentrytitle><manvolnum>1</manvolnum>
</citerefentry></primaryie></indexentry>

<indexentry><primaryie><citerefentry>
<refentrytitle>ostree-admin-set-origin</refentrytitle><manvolnum>1</manvolnum>
</citerefentry></primaryie></indexentry>
Expand Down
79 changes: 79 additions & 0 deletions man/ostree-admin-post-copy.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?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 2023 Alexande Larsson <alexl@redhat.com>

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, see <https://www.gnu.org/licenses/>.
-->

<refentry id="ostree">

<refentryinfo>
<title>ostree admin post-copy</title>
<productname>OSTree</productname>

<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Colin</firstname>
<surname>Walters</surname>
<email>walters@verbum.org</email>
</author>
</authorgroup>
</refentryinfo>

<refmeta>
<refentrytitle>ostree admin post-copy</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>

<refnamediv>
<refname>ostree-admin-post-copy</refname>
<refpurpose>Fix up sysroot after a (file based) copy</refpurpose>
</refnamediv>

<refsynopsisdiv>
<cmdsynopsis>
<command>ostree admin post-copy</command> <arg choice="opt" rep="repeat">OPTIONS</arg>
</cmdsynopsis>
</refsynopsisdiv>

<refsect1>
<title>Description</title>

<para>
Applies any fixes to a sysroot that are needed after having copyed it file by file.
This includes enabling fs-verity to any files that lack it, which can happen if
you copy a file.
</para>
</refsect1>

<refsect1>
<title>Options</title>

<variablelist>
<varlistentry>
<term><option>--sysroot</option>="PATH"</term>

<listitem><para>
Path to the system to use rather than the current one.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>
1 change: 1 addition & 0 deletions man/ostree-admin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
<listitem><para><command>instutil</command></para></listitem>
<listitem><para><command>os-init</command></para></listitem>
<listitem><para><command>pin</command></para></listitem>
<listitem><para><command>post-copy</command></para></listitem>
<listitem><para><command>set-origin</command></para></listitem>
<listitem><para><command>status</command></para></listitem>
<listitem><para><command>switch</command></para></listitem>
Expand Down
5 changes: 5 additions & 0 deletions src/libostree/libostree-devel.sym
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ global:
someostree_symbol_deleteme;
} LIBOSTREE_2021.$LASTSTABLE;
*/

LIBOSTREE_2023.11 {
global:
ostree_sysroot_update_post_copy;
} LIBOSTREE_2023.4;
3 changes: 3 additions & 0 deletions src/libostree/ostree-repo-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,9 @@ gboolean _ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fs
gboolean _ostree_tmpf_fsverity (OstreeRepo *self, GLnxTmpfile *tmpf, GBytes *signature,
GError **error);

gboolean _ostree_ensure_fsverity (OstreeRepo *self, gboolean allow_enoent, int dirfd,
const char *path, gboolean *supported, GError **error);

gboolean _ostree_repo_verify_bindings (const char *collection_id, const char *ref_name,
GVariant *commit, GError **error);

Expand Down
77 changes: 58 additions & 19 deletions src/libostree/ostree-repo-verity.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,28 +102,14 @@ _ostree_repo_parse_fsverity_config (OstreeRepo *self, GError **error)
return TRUE;
}

/* Wrapper around the fsverity ioctl, compressing the result to
* "success, unsupported or error". This is used for /boot where
* we enable verity if supported.
* */
gboolean
_ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fsverity_requested,
GBytes *signature, gboolean *supported, GError **error)
static gboolean
_ostree_fsverity_enable (int fd, gboolean allow_existing, gboolean *supported, GBytes *signature,
GError **error)
{
/* Set this by default to simplify the code below */
if (supported)
*supported = FALSE;

if (fsverity_requested == _OSTREE_FEATURE_NO)
return TRUE;

#ifdef HAVE_LINUX_FSVERITY_H
GLNX_AUTO_PREFIX_ERROR ("fsverity", error);

/* fs-verity requires a read-only file descriptor */
if (!glnx_tmpfile_reopen_rdonly (tmpf, error))
return FALSE;

struct fsverity_enable_arg arg = {
0,
};
Expand All @@ -135,21 +121,50 @@ _ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fsverity_re
arg.sig_size = signature ? g_bytes_get_size (signature) : 0;
arg.sig_ptr = signature ? (guint64)g_bytes_get_data (signature, NULL) : 0;

if (ioctl (tmpf->fd, FS_IOC_ENABLE_VERITY, &arg) < 0)
if (ioctl (fd, FS_IOC_ENABLE_VERITY, &arg) < 0)
{
switch (errno)
{
case ENOTTY:
case EOPNOTSUPP:
return TRUE;
default:
return glnx_throw_errno_prefix (error, "ioctl(FS_IOC_ENABLE_VERITY)");
if (errno != EEXIST || !allow_existing)
return glnx_throw_errno_prefix (error, "ioctl(FS_IOC_ENABLE_VERITY)");
}
}

if (supported)
*supported = TRUE;
#endif

return TRUE;
}

/* Wrapper around the fsverity ioctl, compressing the result to
* "success, unsupported or error". This is used for /boot where
* we enable verity if supported.
* */
gboolean
_ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fsverity_requested,
GBytes *signature, gboolean *supported, GError **error)
{
if (fsverity_requested == _OSTREE_FEATURE_NO)
{
if (supported)
*supported = FALSE;
return TRUE;
}

GLNX_AUTO_PREFIX_ERROR ("fsverity", error);

/* fs-verity requires a read-only file descriptor */
if (!glnx_tmpfile_reopen_rdonly (tmpf, error))
return FALSE;

if (!_ostree_fsverity_enable (tmpf->fd, FALSE, supported, signature, error))
return FALSE;

return TRUE;
}

Expand Down Expand Up @@ -206,3 +221,27 @@ _ostree_tmpf_fsverity (OstreeRepo *self, GLnxTmpfile *tmpf, GBytes *signature, G
#endif
return TRUE;
}

gboolean
_ostree_ensure_fsverity (OstreeRepo *self, gboolean allow_enoent, int dirfd, const char *path,
gboolean *supported, GError **error)
{
glnx_autofd int fd = -1;

if (!ot_openat_ignore_enoent (dirfd, path, &fd, error))
return FALSE;

if (fd == -1 && !allow_enoent)
return glnx_throw (error, "Unexpectedly missing file '%s', can't enable fs-verity", path);

if (fd != -1)
{
if (!_ostree_fsverity_enable (fd, TRUE, supported, NULL, error))
return FALSE;

if (!supported && self->fs_verity_wanted == _OSTREE_FEATURE_YES)
return glnx_throw (error, "fsverity required but filesystem does not support it");
}

return TRUE;
}
67 changes: 67 additions & 0 deletions src/libostree/ostree-sysroot-cleanup.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@

#include "config.h"

#include "ostree-core-private.h"
#include "ostree-linuxfsutil.h"
#include "ostree-repo-private.h"
#include "otcore.h"
#include "otutil.h"

#include "ostree-sysroot-private.h"
Expand Down Expand Up @@ -573,3 +575,68 @@ _ostree_sysroot_cleanup_internal (OstreeSysroot *self, gboolean do_prune_repo,

return TRUE;
}

/**
* ostree_sysroot_update_post_copy:
* @self: Sysroot
* @error: Error
*
* Update a sysroot as needed after having copied it into place using file-level
* operations. This enables options like fs-verity on the required files that may
* have been lost during the copy.
*
* Since: 2023.11
*/
gboolean
ostree_sysroot_update_post_copy (OstreeSysroot *self, GCancellable *cancellable, GError **error)
{
OstreeRepo *repo = ostree_sysroot_repo (self);

if (repo->fs_verity_wanted == _OSTREE_FEATURE_NO)
return TRUE;

g_autoptr (GHashTable) objects
= ostree_repo_list_objects_set (repo, OSTREE_REPO_LIST_OBJECTS_LOOSE, cancellable, error);
if (objects == NULL)
return FALSE;

GLNX_HASH_TABLE_FOREACH (objects, GVariant *, key)
{
const char *checksum;
OstreeObjectType objtype;

ostree_object_name_deserialize (key, &checksum, &objtype);

char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
_ostree_loose_path (loose_path_buf, checksum, objtype, repo->mode);

gboolean supported;
if (!_ostree_ensure_fsverity (repo, FALSE, repo->objects_dir_fd, loose_path_buf, &supported,
error))
return FALSE;

if (!supported)
break; /* If not supported, skip rest */
}

g_autoptr (GPtrArray) all_deployment_dirs = NULL;
if (!list_all_deployment_directories (self, &all_deployment_dirs, cancellable, error))
return FALSE;
g_assert (all_deployment_dirs); /* Pacify static analysis */
for (guint i = 0; i < all_deployment_dirs->len; i++)
{
OstreeDeployment *deployment = all_deployment_dirs->pdata[i];
g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment);

g_autofree char *cfs_file = g_build_filename (deployment_path, OSTREE_COMPOSEFS_NAME, NULL);

gboolean supported;
if (!_ostree_ensure_fsverity (repo, TRUE, self->sysroot_fd, cfs_file, &supported, error))
return FALSE;

if (!supported)
break; /* If not supported, skip rest */
}

return TRUE;
}
4 changes: 4 additions & 0 deletions src/libostree/ostree-sysroot.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ void ostree_sysroot_query_deployments_for (OstreeSysroot *self, const char *osna
_OSTREE_PUBLIC
OstreeDeployment *ostree_sysroot_get_merge_deployment (OstreeSysroot *self, const char *osname);

_OSTREE_PUBLIC
gboolean ostree_sysroot_update_post_copy (OstreeSysroot *self, GCancellable *cancellable,
GError **error);

_OSTREE_PUBLIC
GKeyFile *ostree_sysroot_origin_new_from_refspec (OstreeSysroot *self, const char *refspec);

Expand Down
Loading
Loading