From: Lennart Poettering Date: Fri, 21 Feb 2025 16:23:22 +0000 (+0100) Subject: gpt-auto-generator: if root=gpt-auto-force is specified ignore factory reset state X-Git-Tag: v258-rc1~1176^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1c0b8270f4050955c2cb8ca377d63aaaad0c08dc;p=thirdparty%2Fsystemd.git gpt-auto-generator: if root=gpt-auto-force is specified ignore factory reset state --- diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml index 69788baab45..d3724e7e9dd 100644 --- a/man/systemd-gpt-auto-generator.xml +++ b/man/systemd-gpt-auto-generator.xml @@ -322,16 +322,20 @@ rootflags= When root= is used with the special value - gpt-auto, full automatic discovery of the root - partition based on the GPT partition type is enabled. Any other value disables this - logic. + gpt-auto, full automatic discovery of the root partition based on the GPT + partition type is enabled. Use of the root partition is delayed until factory reset mode is left, in + case it is enabled during the current boot. See Factory + Reset for more information on that. If gpt-auto-force is specified + automatic discovery of the root partition is enabled, ignoring any factory reset mode. Any other + value disables this logic. If root= is not specified at all on the kernel command line automatic - discovery of the root partition via the boot loader reported ESP is also enabled, however in this - case discovery based on the loopback block device .lo_name field is not enabled. + discovery of the root partition via the ESP reported by the boot loader is also enabled (taking + factory reset state into account), however in this case discovery based on the loopback block device + .lo_name field is not enabled. - The rootfstype= and rootflags= are used to select the - file system type and options when the root file system is automatically discovered. + The rootfstype= and rootflags= options are used to select + the file system type and options when the root file system is automatically discovered. diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 6693333c4b1..7e85d476e4d 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -1119,7 +1119,7 @@ static bool validate_root_or_usr_mount_source(const char *what, const char *swit return false; } - if (streq(what, "gpt-auto")) { + if (STR_IN_SET(what, "gpt-auto", "gpt-auto-force")) { /* This is handled by gpt-auto-generator */ log_debug("Skipping %s directory handling, as gpt-auto was requested.", switch_name); return false; diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 1b59fecf9e8..6c2fbe17815 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -17,6 +17,7 @@ #include "dissect-image.h" #include "dropin.h" #include "efi-loader.h" +#include "factory-reset.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" @@ -37,9 +38,16 @@ #include "unit-name.h" #include "virt.h" +typedef enum GptAutoRoot { + GPT_AUTO_ROOT_UNSPECIFIED, /* no root= specified */ + GPT_AUTO_ROOT_OFF, /* root= set to something else */ + GPT_AUTO_ROOT_ON, /* root= set explicitly to "gpt-auto" */ + GPT_AUTO_ROOT_FORCE, /* root= set explicitly to "gpt-auto-force" → ignores factory reset mode */ +} GptAutoRoot; + static const char *arg_dest = NULL; static bool arg_enabled = true; -static int arg_root_enabled = -1; /* tristate */ +static GptAutoRoot arg_auto_root = GPT_AUTO_ROOT_UNSPECIFIED; static bool arg_swap_enabled = true; static char *arg_root_fstype = NULL; static char *arg_root_options = NULL; @@ -47,7 +55,6 @@ static int arg_root_rw = -1; static ImagePolicy *arg_image_policy = NULL; STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); - STATIC_DESTRUCTOR_REGISTER(arg_root_fstype, freep); STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep); @@ -661,7 +668,19 @@ static int add_root_cryptsetup(void) { /* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which * sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */ - return add_cryptsetup("root", "/dev/gpt-auto-root-luks", arg_root_options, /* rw= */ true, /* require= */ false, /* measure= */ true, NULL); + const char *bdev = "/dev/gpt-auto-root-luks"; + + if (arg_auto_root == GPT_AUTO_ROOT_FORCE) { + /* Similar logic as in add_root_mount(), see below */ + FactoryResetMode f = factory_reset_mode(); + if (f < 0) + log_warning_errno(f, "Failed to determine whether we are in factory reset mode, assuming not: %m"); + + if (IN_SET(f, FACTORY_RESET_ON, FACTORY_RESET_COMPLETE)) + bdev = "/dev/gpt-auto-root-luks-ignore-factory-reset"; + } + + return add_cryptsetup("root", bdev, arg_root_options, /* rw= */ true, /* require= */ false, /* measure= */ true, NULL); #else return 0; #endif @@ -674,11 +693,11 @@ static int add_root_mount(void) { int r; /* Explicitly disabled? Then exit immediately */ - if (arg_root_enabled == 0) + if (arg_auto_root == GPT_AUTO_ROOT_OFF) return 0; /* Neither explicitly enabled nor disabled? Then decide based on the EFI partition variables to be set */ - if (arg_root_enabled < 0) { + if (arg_auto_root == GPT_AUTO_ROOT_UNSPECIFIED) { if (!is_efi_boot()) { log_debug("Not an EFI boot, not creating root mount."); return 0; @@ -695,10 +714,27 @@ static int add_root_mount(void) { } /* OK, we shall look for a root device, so let's wait for a root device to show up. A udev rule will - * create the link for us under the right name. */ + * create the link for us under the right name. + * + * There are two distinct names: the /dev/gpt-auto-root-ignore-factory-reset symlink is created for + * the root partition if factory reset mode is enabled or complete, and the /dev/gpt-auto-root + * symlink is only created if factory reset mode is off or already complete (thus taking factory + * reset state into account). In scenarios where the root disk is partially reformatted during + * factory reset the latter is the link to use, otherwise the former (so that we don't accidentally + * mount a root partition too early that is about to be wiped and replaced by another one). */ + + const char *bdev = "/dev/gpt-auto-root"; + if (arg_auto_root == GPT_AUTO_ROOT_FORCE) { + FactoryResetMode f = factory_reset_mode(); + if (f < 0) + log_warning_errno(f, "Failed to determine whether we are in factory reset mode, assuming not: %m"); + + if (IN_SET(f, FACTORY_RESET_ON, FACTORY_RESET_COMPLETE)) + bdev = "/dev/gpt-auto-root-ignore-factory-reset"; + } if (in_initrd()) { - r = generator_write_initrd_root_device_deps(arg_dest, "/dev/gpt-auto-root"); + r = generator_write_initrd_root_device_deps(arg_dest, bdev); if (r < 0) return 0; @@ -727,7 +763,7 @@ static int add_root_mount(void) { return add_mount( "root", - "/dev/gpt-auto-root", + bdev, in_initrd() ? "/sysroot" : "/", arg_root_fstype, /* rw= */ arg_root_rw > 0, @@ -909,15 +945,18 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (proc_cmdline_value_missing(key, value)) return 0; - /* Disable root disk logic if there's a root= value - * specified (unless it happens to be "gpt-auto") */ + /* Disable root disk logic if there's a root= value specified (unless it happens to be + * "gpt-auto" or "gpt-auto-force") */ if (streq(value, "gpt-auto")) { - arg_root_enabled = true; - log_debug("Enabling root partition auto-detection, root= is explicitly set to 'gpt_auto'."); + arg_auto_root = GPT_AUTO_ROOT_ON; + log_debug("Enabling root partition auto-detection (respecting factory reset mode), root= is explicitly set to 'gpt-auto'."); + } else if (streq(value, "gpt-auto-force")) { + arg_auto_root = GPT_AUTO_ROOT_FORCE; + log_debug("Enabling root partition auto-detection (ignoring factory reset mode), root= is explicitly set to 'gpt-auto-force'."); } else { - arg_root_enabled = false; - log_debug("Disabling root partition auto-detection, root= is neither unset, nor set to 'gpt-auto'."); + arg_auto_root = GPT_AUTO_ROOT_OFF; + log_debug("Disabling root partition auto-detection, root= is neither unset, nor set to 'gpt-auto' or 'gpt-auto-force'."); } } else if (streq(key, "roothash")) { @@ -927,7 +966,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat /* Disable root disk logic if there's roothash= defined (i.e. verity enabled) */ - arg_root_enabled = false; + arg_auto_root = GPT_AUTO_ROOT_OFF; log_debug("Disabling root partition auto-detection, roothash= is set."); } else if (streq(key, "rootfstype")) {