chiark / gitweb /
util: fix tty_is_vc_resolve() in a container where /sys/class/tty/console/active...
[elogind.git] / src / nspawn / nspawn.c
index ce727b6e1d8b3d663855a19a69fac4e52c8e2d2b..50f2c5911100acfd70c83fd4b45c649e397aea09 100644 (file)
@@ -101,8 +101,9 @@ static int parse_argv(int argc, char *argv[]) {
 
                 case 'D':
                         free(arg_directory);
-                        if (!(arg_directory = strdup(optarg))) {
-                                log_error("Failed to duplicate root directory.");
+                        arg_directory = canonicalize_file_name(optarg);
+                        if (!arg_directory) {
+                                log_error("Failed to canonicalize root directory.");
                                 return -ENOMEM;
                         }
 
@@ -394,6 +395,13 @@ static int setup_kmsg(const char *dest, int kmsg_socket) {
 
         u = umask(0000);
 
+        /* We create the kmsg FIFO as /dev/kmsg, but immediately
+         * delete it after bind mounting it to /proc/kmsg. While FIFOs
+         * on the reading side behave very similar to /proc/kmsg,
+         * their writing side behaves differently from /dev/kmsg in
+         * that writing blocks when nothing is reading. In order to
+         * avoid any problems with containers deadlocking due to this
+         * we simply make /dev/kmsg unavailable to the container. */
         if (asprintf(&from, "%s/dev/kmsg", dest) < 0) {
                 log_error("Out of memory");
                 r = -ENOMEM;
@@ -456,6 +464,9 @@ static int setup_kmsg(const char *dest, int kmsg_socket) {
                 goto finish;
         }
 
+        /* And now make the FIFO unavailable as /dev/kmsg... */
+        unlink(from);
+
 finish:
         free(from);
         free(to);
@@ -464,6 +475,28 @@ finish:
         return r;
 }
 
+static int setup_hostname(void) {
+        char *hn;
+        int r = 0;
+
+        hn = file_name_from_path(arg_directory);
+        if (hn) {
+                hn = strdup(hn);
+                if (!hn)
+                        return -ENOMEM;
+
+                hostname_cleanup(hn);
+
+                if (!isempty(hn))
+                        if (sethostname(hn, strlen(hn)) < 0)
+                                r = -errno;
+
+                free(hn);
+        }
+
+        return r;
+}
+
 static int drop_capabilities(void) {
         static const unsigned long retain[] = {
                 CAP_CHOWN,
@@ -862,7 +895,6 @@ int main(int argc, char *argv[]) {
         if (pid == 0) {
                 /* child */
 
-                const char *hn;
                 const char *home = NULL;
                 uid_t uid = (uid_t) -1;
                 gid_t gid = (gid_t) -1;
@@ -928,7 +960,7 @@ int main(int argc, char *argv[]) {
                     dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
                         goto child_fail;
 
-                if (mount(arg_directory, "/", "bind", MS_BIND|MS_MOVE, NULL) < 0) {
+                if (mount(arg_directory, "/", "bind", MS_BIND, NULL) < 0) {
                         log_error("mount(MS_MOVE) failed: %m");
                         goto child_fail;
                 }
@@ -990,8 +1022,7 @@ int main(int argc, char *argv[]) {
                     goto child_fail;
                 }
 
-                if ((hn = file_name_from_path(arg_directory)))
-                        sethostname(hn, strlen(hn));
+                setup_hostname();
 
                 if (argc > optind)
                         execvpe(argv[optind], argv + optind, (char**) envp);