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