84b277
From cad8ec5980d63253586d9f884649c45eed0667a1 Mon Sep 17 00:00:00 2001
84b277
From: Harald Hoyer <harald@redhat.com>
84b277
Date: Thu, 6 Mar 2014 16:35:02 +0100
84b277
Subject: [PATCH] systemctl: for switch-root check, if we switch to a systemd
84b277
 init
84b277
84b277
If "systemctl switch-root" is called with a specific "INIT" or
84b277
/proc/cmdline contains "init=", then systemd would not serialize
84b277
itsself.
84b277
84b277
Let systemctl check, if the new init is in the standard systemd
84b277
installation path and if so, clear the INIT parameter,
84b277
to let systemd serialize itsself.
84b277
84b277
Conflicts:
84b277
	src/systemctl/systemctl.c
84b277
84b277
(cherry picked from commit f39d4a08e746e703d562076a0f622eb91dbdcd3e)
84b277
84b277
Related: #1111199
84b277
---
84b277
 src/shared/util.h         | 13 +++++++++++++
84b277
 src/systemctl/systemctl.c | 35 ++++++++++++++++++++++++++---------
84b277
 2 files changed, 39 insertions(+), 9 deletions(-)
84b277
84b277
diff --git a/src/shared/util.h b/src/shared/util.h
84b277
index 631a385..d11fa07 100644
84b277
--- a/src/shared/util.h
84b277
+++ b/src/shared/util.h
84b277
@@ -726,6 +726,19 @@ int unlink_noerrno(const char *path);
84b277
                 _c_;                                    \
84b277
         })
84b277
 
84b277
+#define strappenda3(a, b, c)                                    \
84b277
+        ({                                                      \
84b277
+                const char *_a_ = (a), *_b_ = (b), *_c_ = (c);  \
84b277
+                char *_d_;                                      \
84b277
+                size_t _x_, _y_, _z_;                           \
84b277
+                _x_ = strlen(_a_);                              \
84b277
+                _y_ = strlen(_b_);                              \
84b277
+                _z_ = strlen(_c_);                              \
84b277
+                _d_ = alloca(_x_ + _y_ + _z_ + 1);              \
84b277
+                strcpy(stpcpy(stpcpy(_d_, _a_), _b_), _c_);     \
84b277
+                _d_;                                            \
84b277
+        })
84b277
+
84b277
 #define procfs_file_alloca(pid, field)                                  \
84b277
         ({                                                              \
84b277
                 pid_t _pid_ = (pid);                                    \
84b277
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
84b277
index c738daf..1ca4fd3 100644
84b277
--- a/src/systemctl/systemctl.c
84b277
+++ b/src/systemctl/systemctl.c
84b277
@@ -4143,9 +4143,10 @@ static int show_enviroment(DBusConnection *bus, char **args) {
84b277
 }
84b277
 
84b277
 static int switch_root(DBusConnection *bus, char **args) {
84b277
+        _cleanup_free_ char *cmdline_init = NULL;
84b277
+        const char *root, *init;
84b277
         unsigned l;
84b277
-        const char *root;
84b277
-        _cleanup_free_ char *init = NULL;
84b277
+        int r;
84b277
 
84b277
         l = strv_length(args);
84b277
         if (l < 2 || l > 3) {
84b277
@@ -4156,19 +4157,35 @@ static int switch_root(DBusConnection *bus, char **args) {
84b277
         root = args[1];
84b277
 
84b277
         if (l >= 3)
84b277
-                init = strdup(args[2]);
84b277
+                init = args[2];
84b277
         else {
84b277
-                parse_env_file("/proc/cmdline", WHITESPACE,
84b277
-                               "init", &init,
84b277
-                               NULL);
84b277
+                r = parse_env_file("/proc/cmdline", WHITESPACE,
84b277
+                                   "init", &cmdline_init,
84b277
+                                   NULL);
84b277
+                if (r < 0)
84b277
+                        log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
84b277
 
84b277
-                if (!init)
84b277
-                        init = strdup("");
84b277
+                init = cmdline_init;
84b277
         }
84b277
         if (!init)
84b277
                 return log_oom();
84b277
 
84b277
-        log_debug("switching root - root: %s; init: %s", root, init);
84b277
+        if (isempty(init))
84b277
+                init = NULL;
84b277
+
84b277
+        if (init) {
84b277
+                const char *root_systemd_path = NULL, *root_init_path = NULL;
84b277
+
84b277
+                root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
84b277
+                root_init_path = strappenda3(root, "/", init);
84b277
+
84b277
+                /* If the passed init is actually the same as the
84b277
+                 * systemd binary, then let's suppress it. */
84b277
+                if (files_same(root_init_path, root_systemd_path) > 0)
84b277
+                        init = NULL;
84b277
+        }
84b277
+
84b277
+        log_debug("Switching root - root: %s; init: %s", root, strna(init));
84b277
 
84b277
         return bus_method_call_with_reply(
84b277
                         bus,