Skip to content

Commit

Permalink
Always generate composefs blob, don't enable runtime by default
Browse files Browse the repository at this point in the history
Followup to 9a0acd7

Basically our composefs enablement flag has long had a tension between
trying to do two things:

- Enable generating the composefs blob (at deployment time)
- Enable at runtime in prepare-root

And we've hit issues in "ratcheting" enabling composefs
across upgrades because of this.

This change builds on the previous one, and now it's really
simple to talk about:

- If composefs is enabled at build time, we *always*
  generate a composefs blob at deplyment time
- Configuring the prepare-root config now mostly
  only affects the runtime state.

There is one detail though: in order to handle the
verity requirement at deploy time, we do still parse
the config then.

But for the basic "is composefs enabled at all at runtime"
that is now fully keyed off the config, not the build time
or (worse) whether the deployment happened to have a composefs
blob.

For users who want composefs on, they need to do so in the base
image configuration.

Signed-off-by: Colin Walters <walters@verbum.org>
  • Loading branch information
cgwalters committed Jan 9, 2025
1 parent ce4e49e commit 43a8d2b
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 45 deletions.
22 changes: 10 additions & 12 deletions docs/composefs.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,20 @@ At the current time, integration of composefs and ostree is experimental.

### Enabling composefs (unsigned)

When building a disk image *or* to transition an existing system, run:
If ostree is compiled with composefs support, then a composefs file
corresponding to the deployment tree will be generated by default.

The `ostree-prepare-root` binary will look for `ostree/prepare-root.conf` in `/etc` and
`/usr/lib` in the initramfs. Using that configuration file you can enable composefs.
This configuration will enable an "unsigned" mode, which does not require fsverity,
but does make the system more resilient to accidental mutation.

```
ostree config --repo=/ostree/repo set ex-integrity.composefs true
[composefs]
enabled = yes
```

This will ensure that any future deployments (e.g. created by `ostree admin upgrade`)
have a `.ostree.cfs` file in the deployment directory which is a mountable
composefs metadata file, with a "backing store" directory that is
shared with the current `/ostree/repo/objects`.

### composefs configuration

The `ostree-prepare-root` binary will look for `ostree/prepare-root.conf` in `/etc` and
`/usr/lib` in the initramfs. Using that configuration file you can enable composefs,
and specify an Ed25519 public key to validate the booted commit.
You can also specify an Ed25519 public key to validate the booted commit.

See the manpage for `ostree-prepare-root` for details of how to configure it.

Expand Down
7 changes: 6 additions & 1 deletion man/ostree-prepare-root.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,12 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
the integrity of its backing OSTree object is validated by the digest stored in the image.
Additionally, if set to <literal>signed</literal>, boot will fail if the image cannot be
validated by a public key.
Setting this to <literal>maybe</literal> is currently equivalent to <literal>no</literal>.
Setting this to <literal>maybe</literal> will cause composefs to be used at runtime only
if the deployment has a composefs generated, which causes unpredicable and confusing semantics
and is not recommended. In practice with the <emphasis>current</emphasis> version of ostree,
in the case where composefs is enabled at build time for both the version that made the
deployment (often an older OS version), this will be equivalent to <literal>yes</literal>.
But in general one either wants composefs or not, so choose an explicit value for that.
</para></listitem>
</varlistentry>
<varlistentry>
Expand Down
49 changes: 22 additions & 27 deletions src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,33 +669,28 @@ checkout_deployment_tree (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploy
guint64 composefs_start_time = 0;
guint64 composefs_end_time = 0;
#ifdef HAVE_COMPOSEFS
if (composefs_enabled != OT_TRISTATE_NO)
{
composefs_start_time = g_get_monotonic_time ();
// TODO: Clean up our mess around composefs/fsverity...we have duplication
// between the repo config and the sysroot config, *and* we need to better
// handle skew between repo config and repo state (e.g. "post-copy" should
// support transitioning verity on and off in general).
// For now we configure things such that the fsverity digest is only added
// if present on disk in the unsigned case, and in the signed case unconditionally
// require it.
g_auto (GVariantBuilder) cfs_checkout_opts_builder
= G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
guint32 composefs_requested = 1;
if (composefs_config->require_verity)
composefs_requested = 2;
g_variant_builder_add (&cfs_checkout_opts_builder, "{sv}", "verity",
g_variant_new_uint32 (composefs_requested));
g_debug ("composefs requested: %u", composefs_requested);
g_autoptr (GVariant) cfs_checkout_opts
= g_variant_ref_sink (g_variant_builder_end (&cfs_checkout_opts_builder));
if (!ostree_repo_checkout_composefs (repo, cfs_checkout_opts, ret_deployment_dfd,
OSTREE_COMPOSEFS_NAME, csum, cancellable, error))
return FALSE;
composefs_end_time = g_get_monotonic_time ();
}
else
g_debug ("not using composefs");
composefs_start_time = g_get_monotonic_time ();
// TODO: Clean up our mess around composefs/fsverity...we have duplication
// between the repo config and the sysroot config, *and* we need to better
// handle skew between repo config and repo state (e.g. "post-copy" should
// support transitioning verity on and off in general).
// For now we configure things such that the fsverity digest is only added
// if present on disk in the unsigned case, and in the signed case unconditionally
// require it.
g_auto (GVariantBuilder) cfs_checkout_opts_builder
= G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
guint32 composefs_requested = 1;
if (composefs_config->require_verity)
composefs_requested = 2;
g_variant_builder_add (&cfs_checkout_opts_builder, "{sv}", "verity",
g_variant_new_uint32 (composefs_requested));
g_debug ("composefs requested: %u", composefs_requested);
g_autoptr (GVariant) cfs_checkout_opts
= g_variant_ref_sink (g_variant_builder_end (&cfs_checkout_opts_builder));
if (!ostree_repo_checkout_composefs (repo, cfs_checkout_opts, ret_deployment_dfd,
OSTREE_COMPOSEFS_NAME, csum, cancellable, error))
return FALSE;
composefs_end_time = g_get_monotonic_time ();
#else
if (composefs_enabled == OT_TRISTATE_YES)
return glnx_throw (error, "composefs: enabled at runtime, but support is not compiled in");
Expand Down
2 changes: 1 addition & 1 deletion src/libotcore/otcore-prepare-root.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ otcore_load_composefs_config (const char *cmdline, GKeyFile *config, gboolean lo
}
else if (!ot_keyfile_get_tristate_with_default (config, OTCORE_PREPARE_ROOT_COMPOSEFS_KEY,
OTCORE_PREPARE_ROOT_ENABLED_KEY,
OT_TRISTATE_MAYBE, &ret->enabled, error))
OT_TRISTATE_NO, &ret->enabled, error))
return NULL;

// Look for a key - we default to the initramfs binding path.
Expand Down
9 changes: 5 additions & 4 deletions tests/test-admin-deploy-composefs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ cd -
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.composefs -b testos/buildmain/x86_64-runtime osdata
${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime

# We generate the blob now, even if it's explicitly runtime disabled
${CMD_PREFIX} ostree admin deploy --os=testos --karg=root=LABEL=foo --karg=testkarg=1 testos:testos/buildmain/x86_64-runtime
if test -f sysroot/ostree/deploy/testos/deploy/*.0/.ostree.cfs; then
fatal "found composefs unexpectedly"
fi
cfs_count=$(ls sysroot/ostree/deploy/testos/deploy/*.0/.ostree.cfs | wc -l)
assert_streq "${cfs_count}" "1"

# check explicit enablement
cd osdata
Expand All @@ -55,7 +55,8 @@ ${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-str
${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime

${CMD_PREFIX} ostree admin deploy --os=testos --karg=root=LABEL=foo --karg=testkarg=1 testos:testos/buildmain/x86_64-runtime
ls sysroot/ostree/deploy/testos/deploy/*.0/.ostree.cfs
cfs_count=$(ls sysroot/ostree/deploy/testos/deploy/*.0/.ostree.cfs | wc -l)
assert_streq "${cfs_count}" "2"

tap_ok composefs

Expand Down

0 comments on commit 43a8d2b

Please sign in to comment.