]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/systemctl: when switching root default to /sysroot/
authorLennart Poettering <lennart@poettering.net>
Fri, 28 Apr 2023 14:56:39 +0000 (16:56 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 28 Apr 2023 22:26:20 +0000 (23:26 +0100)
We hardcode the path the initrd uses to prepare the final mount point at
so many places, let's also imply it in "systemctl switch-root" if not
specified.

This adds the fallback both to systemctl and to PID 1 (this is because
both to — different – checks on the path).

man/systemctl.xml
src/core/dbus-manager.c
src/systemctl/systemctl-switch-root.c
src/systemctl/systemctl.c
units/initrd-switch-root.service

index 639c88811097c1869185e26b18b6c61b4880ceef..009aabacb9dc92d0e1198c7a26a917416be294a1 100644 (file)
@@ -1561,19 +1561,20 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
         </varlistentry>
 
         <varlistentry>
-          <term><command>switch-root</command> <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></term>
+          <term><command>switch-root</command> <optional><replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></optional></term>
 
           <listitem>
             <para>Switches to a different root directory and executes a new system manager process below it.
             This is intended for use in the initrd, and will transition from the initrd's system manager
-            process (a.k.a. "init" process) to the main system manager process which is loaded from the
-            actual host root files system. This call takes two arguments: the directory that is to become the
-            new root directory, and the path to the new system manager binary below it to execute as PID 1.
-            If the latter is omitted or the empty string, a systemd binary will automatically be searched for
-            and used as init. If the system manager path is omitted, equal to the empty string or identical
-            to the path to the systemd binary, the state of the initrd's system manager process is passed to
-            the main system manager, which allows later introspection of the state of the services involved
-            in the initrd boot phase.</para>
+            process (a.k.a. "init" process, PID 1) to the main system manager process which is loaded from
+            the actual host root files system. This call takes two arguments: the directory that is to become
+            the new root directory, and the path to the new system manager binary below it to execute as PID
+            1.  If both are omitted or the former is an empty string it defaults to
+            <filename>/sysroot/</filename>. If the latter is omitted or is an empty string, a systemd binary
+            will automatically be searched for and used as service manager. If the system manager path is
+            omitted, equal to the empty string or identical to the path to the systemd binary, the state of
+            the initrd's system manager process is passed to the main system manager, which allows later
+            introspection of the state of the services involved in the initrd boot phase.</para>
           </listitem>
         </varlistentry>
 
index 2feec0bd7df3ba018d069e86e4913c12ac5c7380..f6c9ae69406dc63440c0baf6c7babd20f6ca089d 100644 (file)
@@ -1738,15 +1738,21 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
         if (r < 0)
                 return r;
 
-        if (!path_is_valid(root))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
-                                         "New root directory must be a valid path.");
-        if (!path_is_absolute(root))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
-                                         "New root path '%s' is not absolute.", root);
-        if (path_equal(root, "/"))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
-                                         "New root directory cannot be the old root directory.");
+        if (isempty(root))
+                /* If path is not specified, default to "/sysroot" which is what we generally expect initrds
+                 * to use */
+                root = "/sysroot";
+        else {
+                if (!path_is_valid(root))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+                                                 "New root directory must be a valid path.");
+                if (!path_is_absolute(root))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+                                                 "New root path '%s' is not absolute.", root);
+                if (path_equal(root, "/"))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+                                                 "New root directory cannot be the old root directory.");
+        }
 
         /* Safety check */
         if (isempty(init)) {
index 8cfcaf89358406a16ef48c4c26af52544948e479..b59ea701c91cfbe6a9451d7a4546de5bf15651f8 100644 (file)
@@ -42,14 +42,19 @@ int verb_switch_root(int argc, char *argv[], void *userdata) {
         if (arg_transport != BUS_TRANSPORT_LOCAL)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot switch root remotely.");
 
-        if (argc < 2 || argc > 3)
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments.");
-
-        root = argv[1];
-        if (!path_is_valid(root))
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid root path: %s", root);
-        if (!path_is_absolute(root))
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root path is not absolute: %s", root);
+        if (argc > 3)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many arguments.");
+
+        if (argc >= 2) {
+                root = argv[1];
+                if (!path_is_valid(root))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid root path: %s", root);
+                if (!path_is_absolute(root))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root path is not absolute: %s", root);
+                if (path_equal(root, "/"))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot switch to current root directory: %s", root);
+        } else
+                root = "/sysroot";
 
         if (argc >= 3)
                 init = argv[2];
index 201d64a1f999d43c57c417a5857fccff5422742e..71c068b09e19ecf4e69fd86bc2be76d284609f80 100644 (file)
@@ -243,7 +243,7 @@ static int systemctl_help(void) {
                "  reboot                              Shut down and reboot the system\n"
                "  kexec                               Shut down and reboot the system with kexec\n"
                "  exit [EXIT_CODE]                    Request user instance or container exit\n"
-               "  switch-root ROOT [INIT]             Change to a different root file system\n"
+               "  switch-root [ROOT [INIT]]           Change to a different root file system\n"
                "  suspend                             Suspend the system\n"
                "  hibernate                           Hibernate the system\n"
                "  hybrid-sleep                        Hibernate and suspend the system\n"
@@ -1199,7 +1199,7 @@ static int systemctl_main(int argc, char *argv[]) {
                 { "unmask",                2,        VERB_ANY, 0,                verb_enable                  },
                 { "link",                  2,        VERB_ANY, 0,                verb_enable                  },
                 { "revert",                2,        VERB_ANY, 0,                verb_enable                  },
-                { "switch-root",           2,        VERB_ANY, VERB_ONLINE_ONLY, verb_switch_root             },
+                { "switch-root",           VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_switch_root             },
                 { "list-dependencies",     VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_dependencies       },
                 { "set-default",           2,        2,        0,                verb_set_default             },
                 { "get-default",           VERB_ANY, 1,        0,                verb_get_default             },
index b19b7bbc21e5d49ad78eda40b01db7527b17b123..f81b47871e5463c72c60f20d589e1143a9d2329f 100644 (file)
@@ -20,4 +20,4 @@ OnFailureJobMode=replace-irreversibly
 
 [Service]
 Type=oneshot
-ExecStart=systemctl --no-block switch-root /sysroot
+ExecStart=systemctl --no-block switch-root