chiark / gitweb /
nspawn: move container into its own name=systemd cgroup
[elogind.git] / src / nspawn.c
index 7cefd3debd9cb09be9f61349df21ccbd605bbb19..94e03b58dcce9ade1cbbd8e8e5a1fd2203ffca5c 100644 (file)
@@ -37,6 +37,8 @@
 #include "log.h"
 #include "util.h"
 #include "missing.h"
+#include "cgroup-util.h"
+#include "sd-daemon.h"
 
 static char *arg_directory = NULL;
 
@@ -101,16 +103,20 @@ static int mount_all(const char *dest) {
                 const char *type;
                 const char *options;
                 unsigned long flags;
+                bool fatal;
         } MountPoint;
 
         static const MountPoint mount_table[] = {
-                { "proc",      "/proc",     "proc",   NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV },
-                { "/proc/sys", "/proc/sys", "bind",   NULL,        MS_BIND },                      /* Bind mount first */
-                { "/proc/sys", "/proc/sys", "bind",   NULL,        MS_BIND|MS_RDONLY|MS_REMOUNT }, /* Then, make it r/o */
-                { "sysfs",     "/sys",      "sysfs",  NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY },
-                { "tmpfs",     "/dev",      "tmpfs",  "mode=755",  MS_NOSUID },
-                { "/dev/pts",  "/dev/pts",  "bind",   NULL,        MS_BIND },
-                { "tmpfs",     "/dev/.run", "tmpfs",  "mode=755",  MS_NOSUID|MS_NOEXEC|MS_NODEV },
+                { "proc",      "/proc",     "proc",      NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
+                { "/proc/sys", "/proc/sys", "bind",      NULL,        MS_BIND, true },                      /* Bind mount first */
+                { "/proc/sys", "/proc/sys", "bind",      NULL,        MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
+                { "sysfs",     "/sys",      "sysfs",     NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true },
+                { "tmpfs",     "/dev",      "tmpfs",     "mode=755",  MS_NOSUID, true },
+                { "/dev/pts",  "/dev/pts",  "bind",      NULL,        MS_BIND, true },
+                { "tmpfs",     "/dev/.run", "tmpfs",     "mode=755",  MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
+#ifdef HAVE_SELINUX
+                { "selinux",   "/selinux",  "selinuxfs", NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false },
+#endif
         };
 
         unsigned k;
@@ -145,7 +151,8 @@ static int mount_all(const char *dest) {
                           where,
                           mount_table[k].type,
                           mount_table[k].flags,
-                          mount_table[k].options) < 0) {
+                          mount_table[k].options) < 0 &&
+                    mount_table[k].fatal) {
 
                         log_error("mount(%s) failed: %m", where);
 
@@ -342,7 +349,8 @@ static int is_os_tree(const char *path) {
 
 int main(int argc, char *argv[]) {
         pid_t pid = 0;
-        int r = EXIT_FAILURE;
+        int r = EXIT_FAILURE, k;
+        char *oldcg = NULL, *newcg = NULL;
 
         log_parse_environment();
         log_open();
@@ -371,6 +379,11 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        if (sd_booted() <= 0) {
+                log_error("Not running on a systemd system.");
+                goto finish;
+        }
+
         if (path_equal(arg_directory, "/")) {
                 log_error("Spawning container on root directory not supported.");
                 goto finish;
@@ -383,6 +396,21 @@ int main(int argc, char *argv[]) {
 
         log_info("Spawning namespace container on %s.", arg_directory);
 
+        if ((k = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &oldcg)) < 0) {
+                log_error("Failed to determine current cgroup: %s", strerror(-k));
+                goto finish;
+        }
+
+        if (asprintf(&newcg, "%s/nspawn-%lu", oldcg, (unsigned long) getpid()) < 0) {
+                log_error("Failed to allocate cgroup path.");
+                goto finish;
+        }
+
+        if ((k = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, newcg, 0)) < 0)  {
+                log_error("Failed to create cgroup: %s", strerror(-k));
+                goto finish;
+        }
+
         if ((pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS, NULL)) < 0) {
                 log_error("clone() failed: %m");
                 goto finish;
@@ -448,10 +476,15 @@ int main(int argc, char *argv[]) {
                 r = EXIT_FAILURE;
 
 finish:
-        free(arg_directory);
+        if (oldcg)
+                cg_attach(SYSTEMD_CGROUP_CONTROLLER, oldcg, 0);
+
+        if (newcg)
+                cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
 
-        if (pid > 0)
-                kill(pid, SIGTERM);
+        free(arg_directory);
+        free(oldcg);
+        free(newcg);
 
         return r;
 }