Skip to content

Commit

Permalink
Merge pull request #2930 from cgwalters/prepare-root-config3
Browse files Browse the repository at this point in the history
prepare-root: Introduce ostree/prepare-root.conf && sysroot.readonly improvements
  • Loading branch information
ericcurtin authored Jul 26, 2023
2 parents af52a88 + 3465626 commit 66e4255
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 9 deletions.
17 changes: 17 additions & 0 deletions man/ostree-prepare-root.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,23 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
</para>
</refsect1>

<refsect1>
<title>Configuration</title>

<para>
The <literal>/usr/lib/ostree/prepare-root.conf</literal> (or <literal>/etc/ostree/prepare-root.conf</literal>) config file is parsed by <literal>ostree-prepare-root</literal>. This file must
be present in the initramfs. The default dracut module will copy it from the real root if present.
</para>

<variablelist>
<varlistentry>
<term><varname>sysroot.readonly</varname></term>
<listitem><para>A boolean value; the default is false. If this is set to <literal>true</literal>, then the <literal>/sysroot</literal> mount point is mounted read-only.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>


<refsect1>
<title>systemd</title>

Expand Down
5 changes: 5 additions & 0 deletions src/boot/dracut/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ depends() {

install() {
dracut_install /usr/lib/ostree/ostree-prepare-root
for r in /usr/lib /etc; do
if test -f "$r/ostree/prepare-root.conf"; then
inst_simple "$r/ostree/prepare-root.conf"
fi
done
inst_simple "${systemdsystemunitdir}/ostree-prepare-root.service"
mkdir -p "${initdir}${systemdsystemconfdir}/initrd-root-fs.target.wants"
ln_r "${systemdsystemunitdir}/ostree-prepare-root.service" \
Expand Down
79 changes: 70 additions & 9 deletions src/switchroot/ostree-prepare-root.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,16 @@
#include <ostree-core.h>
#include <ostree-repo-private.h>

#include "ot-keyfile-utils.h"
#include "otcore.h"

// The path to the config file for this binary
const char *config_roots[] = { "/usr/lib", "/etc" };
#define PREPARE_ROOT_CONFIG_PATH "ostree/prepare-root.conf"

#define SYSROOT_KEY "sysroot"
#define READONLY_KEY "readonly"

// The kernel argument we support to configure composefs.
#define OT_COMPOSEFS_KARG "ot-composefs"

Expand All @@ -91,6 +99,35 @@

#include "ostree-mount-util.h"

// Load our config file; if it doesn't exist, we return an empty configuration.
// NULL will be returned if we caught an error.
static GKeyFile *
load_config (GError **error)
{
g_autoptr (GKeyFile) ret = g_key_file_new ();

for (guint i = 0; i < G_N_ELEMENTS (config_roots); i++)
{
glnx_autofd int fd = -1;
g_autofree char *path = g_build_filename (config_roots[i], PREPARE_ROOT_CONFIG_PATH, NULL);
if (!ot_openat_ignore_enoent (AT_FDCWD, path, &fd, error))
return NULL;
/* If the config file doesn't exist, that's OK */
if (fd == -1)
continue;

g_print ("Loading %s\n", path);

g_autofree char *buf = glnx_fd_readall_utf8 (fd, NULL, NULL, error);
if (!buf)
return NULL;
if (!g_key_file_load_from_data (ret, buf, -1, 0, error))
return NULL;
}

return g_steal_pointer (&ret);
}

static bool
sysroot_is_configured_ro (const char *sysroot)
{
Expand All @@ -103,7 +140,7 @@ sysroot_is_configured_ro (const char *sysroot)
return false;
}

return g_key_file_get_boolean (repo_config, "sysroot", "readonly", NULL);
return g_key_file_get_boolean (repo_config, SYSROOT_KEY, READONLY_KEY, NULL);
}

static inline char *
Expand Down Expand Up @@ -302,6 +339,25 @@ main (int argc, char *argv[])
err (EXIT_FAILURE, "usage: ostree-prepare-root SYSROOT");
root_arg = argv[1];

g_autoptr (GKeyFile) config = load_config (&error);
if (!config)
errx (EXIT_FAILURE, "Failed to parse config: %s", error->message);

gboolean sysroot_readonly = FALSE;

// We always parse the composefs config, because we want to detect and error
// out if it's enabled, but not supported at compile time.
g_autoptr (ComposefsConfig) composefs_config = load_composefs_config (&error);
if (!composefs_config)
errx (EXIT_FAILURE, "%s", error->message);

// If composefs is enabled, that also implies sysroot.readonly=true because it's
// the new default we want to use (not because it's actually required)
const bool sysroot_readonly_default = composefs_config->enabled == OT_TRISTATE_YES;
if (!ot_keyfile_get_boolean_with_default (config, SYSROOT_KEY, READONLY_KEY,
sysroot_readonly_default, &sysroot_readonly, &error))
errx (EXIT_FAILURE, "Failed to parse sysroot.readonly value: %s", error->message);

/* This is the final target where we should prepare the rootfs. The usual
* case with systemd in the initramfs is that root_mountpoint = "/sysroot".
* In the fastboot embedded case we're pid1 and will setup / ourself, and
Expand All @@ -317,10 +373,20 @@ main (int argc, char *argv[])
if (mkdirat (AT_FDCWD, OTCORE_RUN_OSTREE_PRIVATE, 0) < 0)
err (EXIT_FAILURE, "Failed to create %s", OTCORE_RUN_OSTREE_PRIVATE);

/* Query the repository configuration - this is an operating system builder
* choice. More info: https://github.com/ostreedev/ostree/pull/1767
/* Fall back to querying the repository configuration in the target disk.
* This is an operating system builder choice. More info:
* https://github.com/ostreedev/ostree/pull/1767
* However, we only do this if composefs is not enabled, because we don't
* want to parse the target root filesystem before verifying its integrity.
*/
const bool sysroot_readonly = sysroot_is_configured_ro (root_arg);
if (!sysroot_readonly && composefs_config->enabled != OT_TRISTATE_YES)
{
sysroot_readonly = sysroot_is_configured_ro (root_arg);
// Encourage porting to the new config file
if (sysroot_readonly)
g_print ("Found legacy sysroot.readonly flag, not configured in %s\n",
PREPARE_ROOT_CONFIG_PATH);
}
const bool sysroot_currently_writable = !path_is_on_readonly_fs (root_arg);
g_print ("sysroot.readonly configuration value: %d (fs writable: %d)\n", (int)sysroot_readonly,
(int)sysroot_currently_writable);
Expand All @@ -344,11 +410,6 @@ main (int argc, char *argv[])
GVariantBuilder metadata_builder;
g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}"));

// We always parse the composefs config, because we want to detect and error
// out if it's enabled, but not supported at compile time.
g_autoptr (ComposefsConfig) composefs_config = load_composefs_config (&error);
if (!composefs_config)
errx (EXIT_FAILURE, "%s", error->message);
// Tracks if we did successfully enable it at runtime
bool using_composefs = false;

Expand Down

0 comments on commit 66e4255

Please sign in to comment.