diff --git a/man/ostree-prepare-root.xml b/man/ostree-prepare-root.xml
index 8a682e7315..dfcac7109b 100644
--- a/man/ostree-prepare-root.xml
+++ b/man/ostree-prepare-root.xml
@@ -163,6 +163,11 @@ License along with this library. If not, see .
This accepts the same values as composefs.enabled above, and overrides the config file (if present).
For example, specifying ostree.prepare-root.composefs=0 will disable composefs, even if it is enabled by default in the initrd config.
+
+ ostree.prepare-root.readonly
+ This accepts the same values as sysroot.readonly above, and overrides the config file (if present).
+ For example, specifying ostree.prepare-root.readonly=0 will disable mounting /sysroot read-only, even if it is enabled by default in the initrd config.
+
diff --git a/src/libotcore/otcore-prepare-root.c b/src/libotcore/otcore-prepare-root.c
index e0a1641a8f..963feaed50 100644
--- a/src/libotcore/otcore-prepare-root.c
+++ b/src/libotcore/otcore-prepare-root.c
@@ -26,6 +26,8 @@
#define BINDING_KEYPATH "/etc/ostree/initramfs-root-binding.key"
// The kernel argument to configure composefs
#define CMDLINE_KEY_COMPOSEFS "ostree.prepare-root.composefs"
+// The kernel argument to configure sysroot.readonly
+#define CMDLINE_KEY_READONLY "ostree.prepare-root.readonly"
static bool
proc_cmdline_has_key_starting_with (const char *cmdline, const char *key)
@@ -239,3 +241,36 @@ otcore_load_composefs_config (const char *cmdline, GKeyFile *config, gboolean lo
return g_steal_pointer (&ret);
}
+
+gboolean
+otcore_load_sysroot_readonly (const char *cmdline, GKeyFile *config,
+ const ComposefsConfig *composefs_config,
+ gboolean *sysroot_readonly, GError **error)
+{
+ g_assert (cmdline);
+ g_assert (config);
+ g_assert (composefs_config);
+ g_assert (sysroot_readonly);
+
+ GLNX_AUTO_PREFIX_ERROR ("Loading sysroot readonly config", error);
+
+ g_autofree char *readonly_cmdline =
+ otcore_find_proc_cmdline_key (cmdline, CMDLINE_KEY_READONLY);
+ if (readonly_cmdline)
+ {
+ if (!_ostree_parse_boolean(readonly_cmdline, sysroot_readonly, error))
+ return glnx_prefix_error (error, "handling karg" CMDLINE_KEY_READONLY);
+
+ return TRUE;
+ }
+
+ // 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 gboolean sysroot_readonly_default = composefs_config->enabled == OT_TRISTATE_YES;
+ if (!ot_keyfile_get_boolean_with_default (config, OTCORE_PREPARE_ROOT_SYSROOT_KEY,
+ OTCORE_PREPARE_ROOT_READONLY_KEY,
+ sysroot_readonly_default, sysroot_readonly, error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/libotcore/otcore.h b/src/libotcore/otcore.h
index 6e1d510329..9a57913ebd 100644
--- a/src/libotcore/otcore.h
+++ b/src/libotcore/otcore.h
@@ -61,6 +61,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ComposefsConfig, otcore_free_composefs_config)
ComposefsConfig *otcore_load_composefs_config (const char *cmdline, GKeyFile *config,
gboolean load_keys, GError **error);
+gboolean otcore_load_sysroot_readonly (const char *cmdline, GKeyFile *config,
+ const ComposefsConfig *composefs_config,
+ gboolean *sysroot_readonly, GError **error);
// Our directory with transient state (eventually /run/ostree-booted should be a link to
// /run/ostree/booted)
@@ -86,6 +89,9 @@ ComposefsConfig *otcore_load_composefs_config (const char *cmdline, GKeyFile *co
// EROFS mount if we somehow leaked it (but it *should* be unmounted always).
#define OSTREE_COMPOSEFS_LOWERMNT OTCORE_RUN_OSTREE_PRIVATE "/cfsroot-lower"
+#define OTCORE_PREPARE_ROOT_SYSROOT_KEY "sysroot"
+#define OTCORE_PREPARE_ROOT_READONLY_KEY "readonly"
+
#define OTCORE_PREPARE_ROOT_COMPOSEFS_KEY "composefs"
#define OTCORE_PREPARE_ROOT_ENABLED_KEY "enabled"
#define OTCORE_PREPARE_ROOT_KEYPATH_KEY "keypath"
diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c
index 7754673eeb..37910e73d9 100644
--- a/src/switchroot/ostree-prepare-root.c
+++ b/src/switchroot/ostree-prepare-root.c
@@ -76,9 +76,6 @@
#include "ot-keyfile-utils.h"
#include "otcore.h"
-#define SYSROOT_KEY "sysroot"
-#define READONLY_KEY "readonly"
-
/* This key configures the / mount in the deployment root */
#define ROOT_KEY "root"
#define ETC_KEY "etc"
@@ -109,7 +106,8 @@ sysroot_is_configured_ro (const char *sysroot)
return false;
}
- return g_key_file_get_boolean (repo_config, SYSROOT_KEY, READONLY_KEY, NULL);
+ return g_key_file_get_boolean (repo_config, OTCORE_PREPARE_ROOT_SYSROOT_KEY,
+ OTCORE_PREPARE_ROOT_READONLY_KEY, NULL);
}
static char *
@@ -280,7 +278,6 @@ main (int argc, char *argv[])
if (!config)
errx (EXIT_FAILURE, "Failed to parse config: %s", error->message);
- gboolean sysroot_readonly = FALSE;
gboolean root_transient = FALSE;
if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, TRANSIENT_KEY, FALSE, &root_transient,
@@ -294,12 +291,10 @@ main (int argc, char *argv[])
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);
+ gboolean sysroot_readonly;
+ if (!otcore_load_sysroot_readonly (kernel_cmdline, config, composefs_config, &sysroot_readonly,
+ &error))
+ errx (EXIT_FAILURE, "%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".