1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/types.h>
26 #include <sys/syscall.h>
27 #include <sys/mount.h>
33 #include <sys/prctl.h>
34 #include <sys/capability.h>
37 #include <sys/signalfd.h>
41 #include <sys/socket.h>
42 #include <linux/netlink.h>
43 #include <sys/eventfd.h>
45 #include <linux/veth.h>
48 #include <selinux/selinux.h>
55 #include "sd-daemon.h"
65 #include "cgroup-util.h"
67 #include "path-util.h"
68 #include "loopback-setup.h"
69 #include "dev-setup.h"
74 #include "bus-error.h"
76 #include "bus-kernel.h"
79 #include "rtnl-util.h"
80 #include "udev-util.h"
83 #include "seccomp-util.h"
86 typedef enum LinkJournal {
93 static char *arg_directory = NULL;
94 static char *arg_user = NULL;
95 static sd_id128_t arg_uuid = {};
96 static char *arg_machine = NULL;
97 static char *arg_selinux_context = NULL;
98 static char *arg_selinux_apifs_context = NULL;
99 static const char *arg_slice = NULL;
100 static bool arg_private_network = false;
101 static bool arg_read_only = false;
102 static bool arg_boot = false;
103 static LinkJournal arg_link_journal = LINK_AUTO;
104 static uint64_t arg_retain =
105 (1ULL << CAP_CHOWN) |
106 (1ULL << CAP_DAC_OVERRIDE) |
107 (1ULL << CAP_DAC_READ_SEARCH) |
108 (1ULL << CAP_FOWNER) |
109 (1ULL << CAP_FSETID) |
110 (1ULL << CAP_IPC_OWNER) |
112 (1ULL << CAP_LEASE) |
113 (1ULL << CAP_LINUX_IMMUTABLE) |
114 (1ULL << CAP_NET_BIND_SERVICE) |
115 (1ULL << CAP_NET_BROADCAST) |
116 (1ULL << CAP_NET_RAW) |
117 (1ULL << CAP_SETGID) |
118 (1ULL << CAP_SETFCAP) |
119 (1ULL << CAP_SETPCAP) |
120 (1ULL << CAP_SETUID) |
121 (1ULL << CAP_SYS_ADMIN) |
122 (1ULL << CAP_SYS_CHROOT) |
123 (1ULL << CAP_SYS_NICE) |
124 (1ULL << CAP_SYS_PTRACE) |
125 (1ULL << CAP_SYS_TTY_CONFIG) |
126 (1ULL << CAP_SYS_RESOURCE) |
127 (1ULL << CAP_SYS_BOOT) |
128 (1ULL << CAP_AUDIT_WRITE) |
129 (1ULL << CAP_AUDIT_CONTROL) |
131 static char **arg_bind = NULL;
132 static char **arg_bind_ro = NULL;
133 static char **arg_setenv = NULL;
134 static bool arg_quiet = false;
135 static bool arg_share_system = false;
136 static bool arg_register = true;
137 static bool arg_keep_unit = false;
138 static char **arg_network_interfaces = NULL;
139 static bool arg_network_veth = false;
140 static char *arg_network_bridge = NULL;
142 static int help(void) {
144 printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
145 "Spawn a minimal namespace container for debugging, testing and building.\n\n"
146 " -h --help Show this help\n"
147 " --version Print version string\n"
148 " -q --quiet Do not show status information\n"
149 " -D --directory=NAME Root directory for the container\n"
150 " -b --boot Boot up full system (i.e. invoke init)\n"
151 " -u --user=USER Run the command under specified user or uid\n"
152 " -M --machine=NAME Set the machine name for the container\n"
153 " --uuid=UUID Set a specific machine UUID for the container\n"
154 " -S --slice=SLICE Place the container in the specified slice\n"
155 " --private-network Disable network in container\n"
156 " --network-interface=INTERFACE\n"
157 " Assign an existing network interface to the\n"
159 " --network-veth Add a virtual ethernet connection between host\n"
161 " --network-bridge=INTERFACE\n"
162 " Add a virtual ethernet connection between host\n"
163 " and container and add it to an existing bridge on\n"
165 " -Z --selinux-context=SECLABEL\n"
166 " Set the SELinux security context to be used by\n"
167 " processes in the container\n"
168 " -L --selinux-apifs-context=SECLABEL\n"
169 " Set the SELinux security context to be used by\n"
170 " API/tmpfs file systems in the container\n"
171 " --capability=CAP In addition to the default, retain specified\n"
173 " --drop-capability=CAP Drop the specified capability from the default set\n"
174 " --link-journal=MODE Link up guest journal, one of no, auto, guest, host\n"
175 " -j Equivalent to --link-journal=host\n"
176 " --read-only Mount the root directory read-only\n"
177 " --bind=PATH[:PATH] Bind mount a file or directory from the host into\n"
179 " --bind-ro=PATH[:PATH] Similar, but creates a read-only bind mount\n"
180 " --setenv=NAME=VALUE Pass an environment variable to PID 1\n"
181 " --share-system Share system namespaces with host\n"
182 " --register=BOOLEAN Register container as machine\n"
183 " --keep-unit Do not register a scope for the machine, reuse\n"
184 " the service unit nspawn is running in\n",
185 program_invocation_short_name);
190 static int parse_argv(int argc, char *argv[]) {
206 ARG_NETWORK_INTERFACE,
211 static const struct option options[] = {
212 { "help", no_argument, NULL, 'h' },
213 { "version", no_argument, NULL, ARG_VERSION },
214 { "directory", required_argument, NULL, 'D' },
215 { "user", required_argument, NULL, 'u' },
216 { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
217 { "boot", no_argument, NULL, 'b' },
218 { "uuid", required_argument, NULL, ARG_UUID },
219 { "read-only", no_argument, NULL, ARG_READ_ONLY },
220 { "capability", required_argument, NULL, ARG_CAPABILITY },
221 { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY },
222 { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL },
223 { "bind", required_argument, NULL, ARG_BIND },
224 { "bind-ro", required_argument, NULL, ARG_BIND_RO },
225 { "machine", required_argument, NULL, 'M' },
226 { "slice", required_argument, NULL, 'S' },
227 { "setenv", required_argument, NULL, ARG_SETENV },
228 { "selinux-context", required_argument, NULL, 'Z' },
229 { "selinux-apifs-context", required_argument, NULL, 'L' },
230 { "quiet", no_argument, NULL, 'q' },
231 { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM },
232 { "register", required_argument, NULL, ARG_REGISTER },
233 { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT },
234 { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
235 { "network-veth", no_argument, NULL, ARG_NETWORK_VETH },
236 { "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE },
241 uint64_t plus = 0, minus = 0;
246 while ((c = getopt_long(argc, argv, "+hD:u:bL:M:jS:Z:q", options, NULL)) >= 0) {
254 puts(PACKAGE_STRING);
255 puts(SYSTEMD_FEATURES);
260 arg_directory = canonicalize_file_name(optarg);
261 if (!arg_directory) {
262 log_error("Invalid root directory: %m");
270 arg_user = strdup(optarg);
276 case ARG_NETWORK_BRIDGE:
277 arg_network_bridge = strdup(optarg);
278 if (!arg_network_bridge)
283 case ARG_NETWORK_VETH:
284 arg_network_veth = true;
285 arg_private_network = true;
288 case ARG_NETWORK_INTERFACE:
289 if (strv_push(&arg_network_interfaces, optarg) < 0)
294 case ARG_PRIVATE_NETWORK:
295 arg_private_network = true;
303 r = sd_id128_from_string(optarg, &arg_uuid);
305 log_error("Invalid UUID: %s", optarg);
311 arg_slice = strdup(optarg);
318 if (isempty(optarg)) {
323 if (!hostname_is_valid(optarg)) {
324 log_error("Invalid machine name: %s", optarg);
329 arg_machine = strdup(optarg);
337 arg_selinux_context = optarg;
341 arg_selinux_apifs_context = optarg;
345 arg_read_only = true;
349 case ARG_DROP_CAPABILITY: {
353 FOREACH_WORD_SEPARATOR(word, length, optarg, ",", state) {
354 _cleanup_free_ char *t;
357 t = strndup(word, length);
361 if (streq(t, "all")) {
362 if (c == ARG_CAPABILITY)
363 plus = (uint64_t) -1;
365 minus = (uint64_t) -1;
367 if (cap_from_name(t, &cap) < 0) {
368 log_error("Failed to parse capability %s.", t);
372 if (c == ARG_CAPABILITY)
373 plus |= 1ULL << (uint64_t) cap;
375 minus |= 1ULL << (uint64_t) cap;
383 arg_link_journal = LINK_GUEST;
386 case ARG_LINK_JOURNAL:
387 if (streq(optarg, "auto"))
388 arg_link_journal = LINK_AUTO;
389 else if (streq(optarg, "no"))
390 arg_link_journal = LINK_NO;
391 else if (streq(optarg, "guest"))
392 arg_link_journal = LINK_GUEST;
393 else if (streq(optarg, "host"))
394 arg_link_journal = LINK_HOST;
396 log_error("Failed to parse link journal mode %s", optarg);
404 _cleanup_free_ char *a = NULL, *b = NULL;
408 x = c == ARG_BIND ? &arg_bind : &arg_bind_ro;
410 e = strchr(optarg, ':');
412 a = strndup(optarg, e - optarg);
422 if (!path_is_absolute(a) || !path_is_absolute(b)) {
423 log_error("Invalid bind mount specification: %s", optarg);
427 r = strv_extend(x, a);
431 r = strv_extend(x, b);
441 if (!env_assignment_is_valid(optarg)) {
442 log_error("Environment variable assignment '%s' is not valid.", optarg);
446 n = strv_env_set(arg_setenv, optarg);
450 strv_free(arg_setenv);
459 case ARG_SHARE_SYSTEM:
460 arg_share_system = true;
464 r = parse_boolean(optarg);
466 log_error("Failed to parse --register= argument: %s", optarg);
474 arg_keep_unit = true;
481 assert_not_reached("Unhandled option");
485 if (arg_share_system)
486 arg_register = false;
488 if (arg_boot && arg_share_system) {
489 log_error("--boot and --share-system may not be combined.");
493 if (arg_keep_unit && cg_pid_get_owner_uid(0, NULL) >= 0) {
494 log_error("--keep-unit may not be used when invoked from a user session.");
498 arg_retain = (arg_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus;
503 static int mount_all(const char *dest) {
505 typedef struct MountPoint {
514 static const MountPoint mount_table[] = {
515 { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
516 { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true }, /* Bind mount first */
517 { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
518 { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
519 { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true },
520 { "devpts", "/dev/pts", "devpts","newinstance,ptmxmode=0666,mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, true },
521 { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true },
522 { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true },
524 { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false }, /* Bind mount first */
525 { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false }, /* Then, make it r/o */
532 for (k = 0; k < ELEMENTSOF(mount_table); k++) {
533 _cleanup_free_ char *where = NULL;
535 _cleanup_free_ char *options = NULL;
540 where = strjoin(dest, "/", mount_table[k].where, NULL);
544 t = path_is_mount_point(where, true);
546 log_error("Failed to detect whether %s is a mount point: %s", where, strerror(-t));
554 /* Skip this entry if it is not a remount. */
555 if (mount_table[k].what && t > 0)
558 mkdir_p(where, 0755);
561 if (arg_selinux_apifs_context &&
562 (streq_ptr(mount_table[k].what, "tmpfs") || streq_ptr(mount_table[k].what, "devpts"))) {
563 options = strjoin(mount_table[k].options, ",context=\"", arg_selinux_apifs_context, "\"", NULL);
570 o = mount_table[k].options;
573 if (mount(mount_table[k].what,
576 mount_table[k].flags,
578 mount_table[k].fatal) {
580 log_error("mount(%s) failed: %m", where);
590 static int mount_binds(const char *dest, char **l, unsigned long flags) {
593 STRV_FOREACH_PAIR(x, y, l) {
595 struct stat source_st, dest_st;
598 if (stat(*x, &source_st) < 0) {
599 log_error("failed to stat %s: %m", *x);
603 where = strappenda(dest, *y);
604 r = stat(where, &dest_st);
606 if ((source_st.st_mode & S_IFMT) != (dest_st.st_mode & S_IFMT)) {
607 log_error("The file types of %s and %s do not match. Refusing bind mount",
611 } else if (errno == ENOENT) {
612 r = mkdir_parents_label(where, 0755);
614 log_error("Failed to bind mount %s: %s", *x, strerror(-r));
618 log_error("Failed to bind mount %s: %s", *x, strerror(errno));
621 /* Create the mount point, but be conservative -- refuse to create block
622 * and char devices. */
623 if (S_ISDIR(source_st.st_mode))
624 mkdir_label(where, 0755);
625 else if (S_ISFIFO(source_st.st_mode))
627 else if (S_ISSOCK(source_st.st_mode))
628 mknod(where, 0644 | S_IFSOCK, 0);
629 else if (S_ISREG(source_st.st_mode))
632 log_error("Refusing to create mountpoint for file: %s", *x);
636 if (mount(*x, where, "bind", MS_BIND, NULL) < 0) {
637 log_error("mount(%s) failed: %m", where);
641 if (flags && mount(NULL, where, NULL, MS_REMOUNT|MS_BIND|flags, NULL) < 0) {
642 log_error("mount(%s) failed: %m", where);
650 static int setup_timezone(const char *dest) {
651 _cleanup_free_ char *where = NULL, *p = NULL, *q = NULL, *check = NULL, *what = NULL;
657 /* Fix the timezone, if possible */
658 r = readlink_malloc("/etc/localtime", &p);
660 log_warning("/etc/localtime is not a symlink, not updating container timezone.");
664 z = path_startswith(p, "../usr/share/zoneinfo/");
666 z = path_startswith(p, "/usr/share/zoneinfo/");
668 log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.");
672 where = strappend(dest, "/etc/localtime");
676 r = readlink_malloc(where, &q);
678 y = path_startswith(q, "../usr/share/zoneinfo/");
680 y = path_startswith(q, "/usr/share/zoneinfo/");
683 /* Already pointing to the right place? Then do nothing .. */
684 if (y && streq(y, z))
688 check = strjoin(dest, "/usr/share/zoneinfo/", z, NULL);
692 if (access(check, F_OK) < 0) {
693 log_warning("Timezone %s does not exist in container, not updating container timezone.", z);
697 what = strappend("../usr/share/zoneinfo/", z);
702 if (symlink(what, where) < 0) {
703 log_error("Failed to correct timezone of container: %m");
710 static int setup_resolv_conf(const char *dest) {
711 char _cleanup_free_ *where = NULL;
715 if (arg_private_network)
718 /* Fix resolv.conf, if possible */
719 where = strappend(dest, "/etc/resolv.conf");
723 /* We don't really care for the results of this really. If it
724 * fails, it fails, but meh... */
725 copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW);
730 static int setup_boot_id(const char *dest) {
731 _cleanup_free_ char *from = NULL, *to = NULL;
738 if (arg_share_system)
741 /* Generate a new randomized boot ID, so that each boot-up of
742 * the container gets a new one */
744 from = strappend(dest, "/dev/proc-sys-kernel-random-boot-id");
745 to = strappend(dest, "/proc/sys/kernel/random/boot_id");
749 r = sd_id128_randomize(&rnd);
751 log_error("Failed to generate random boot id: %s", strerror(-r));
755 snprintf(as_uuid, sizeof(as_uuid),
756 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
757 SD_ID128_FORMAT_VAL(rnd));
758 char_array_0(as_uuid);
760 r = write_string_file(from, as_uuid);
762 log_error("Failed to write boot id: %s", strerror(-r));
766 if (mount(from, to, "bind", MS_BIND, NULL) < 0) {
767 log_error("Failed to bind mount boot id: %m");
769 } else if (mount(from, to, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL))
770 log_warning("Failed to make boot id read-only: %m");
776 static int copy_devnodes(const char *dest) {
778 static const char devnodes[] =
788 _cleanup_umask_ mode_t u;
794 NULSTR_FOREACH(d, devnodes) {
795 _cleanup_free_ char *from = NULL, *to = NULL;
798 from = strappend("/dev/", d);
799 to = strjoin(dest, "/dev/", d, NULL);
803 if (stat(from, &st) < 0) {
805 if (errno != ENOENT) {
806 log_error("Failed to stat %s: %m", from);
810 } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
812 log_error("%s is not a char or block device, cannot copy", from);
815 } else if (mknod(to, st.st_mode, st.st_rdev) < 0) {
817 log_error("mknod(%s) failed: %m", dest);
825 static int setup_ptmx(const char *dest) {
826 _cleanup_free_ char *p = NULL;
828 p = strappend(dest, "/dev/ptmx");
832 if (symlink("pts/ptmx", p) < 0) {
833 log_error("Failed to create /dev/ptmx symlink: %m");
840 static int setup_dev_console(const char *dest, const char *console) {
842 _cleanup_free_ char *to = NULL;
844 _cleanup_umask_ mode_t u;
851 if (stat(console, &st) < 0) {
852 log_error("Failed to stat %s: %m", console);
855 } else if (!S_ISCHR(st.st_mode)) {
856 log_error("/dev/console is not a char device");
860 r = chmod_and_chown(console, 0600, 0, 0);
862 log_error("Failed to correct access mode for TTY: %s", strerror(-r));
866 if (asprintf(&to, "%s/dev/console", dest) < 0)
869 /* We need to bind mount the right tty to /dev/console since
870 * ptys can only exist on pts file systems. To have something
871 * to bind mount things on we create a device node first, that
872 * has the right major/minor (note that the major minor
873 * doesn't actually matter here, since we mount it over
876 if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) {
877 log_error("mknod() for /dev/console failed: %m");
881 if (mount(console, to, "bind", MS_BIND, NULL) < 0) {
882 log_error("Bind mount for /dev/console failed: %m");
889 static int setup_kmsg(const char *dest, int kmsg_socket) {
890 _cleanup_free_ char *from = NULL, *to = NULL;
892 _cleanup_umask_ mode_t u;
894 struct cmsghdr cmsghdr;
895 uint8_t buf[CMSG_SPACE(sizeof(int))];
898 .msg_control = &control,
899 .msg_controllen = sizeof(control),
901 struct cmsghdr *cmsg;
904 assert(kmsg_socket >= 0);
908 /* We create the kmsg FIFO as /dev/kmsg, but immediately
909 * delete it after bind mounting it to /proc/kmsg. While FIFOs
910 * on the reading side behave very similar to /proc/kmsg,
911 * their writing side behaves differently from /dev/kmsg in
912 * that writing blocks when nothing is reading. In order to
913 * avoid any problems with containers deadlocking due to this
914 * we simply make /dev/kmsg unavailable to the container. */
915 if (asprintf(&from, "%s/dev/kmsg", dest) < 0 ||
916 asprintf(&to, "%s/proc/kmsg", dest) < 0)
919 if (mkfifo(from, 0600) < 0) {
920 log_error("mkfifo() for /dev/kmsg failed: %m");
924 r = chmod_and_chown(from, 0600, 0, 0);
926 log_error("Failed to correct access mode for /dev/kmsg: %s", strerror(-r));
930 if (mount(from, to, "bind", MS_BIND, NULL) < 0) {
931 log_error("Bind mount for /proc/kmsg failed: %m");
935 fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC);
937 log_error("Failed to open fifo: %m");
941 cmsg = CMSG_FIRSTHDR(&mh);
942 cmsg->cmsg_level = SOL_SOCKET;
943 cmsg->cmsg_type = SCM_RIGHTS;
944 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
945 memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
947 mh.msg_controllen = cmsg->cmsg_len;
949 /* Store away the fd in the socket, so that it stays open as
950 * long as we run the child */
951 k = sendmsg(kmsg_socket, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
952 close_nointr_nofail(fd);
955 log_error("Failed to send FIFO fd: %m");
959 /* And now make the FIFO unavailable as /dev/kmsg... */
964 static int setup_hostname(void) {
966 if (arg_share_system)
969 if (sethostname(arg_machine, strlen(arg_machine)) < 0)
975 static int setup_journal(const char *directory) {
976 sd_id128_t machine_id, this_id;
977 _cleanup_free_ char *p = NULL, *b = NULL, *q = NULL, *d = NULL;
981 p = strappend(directory, "/etc/machine-id");
985 r = read_one_line_file(p, &b);
986 if (r == -ENOENT && arg_link_journal == LINK_AUTO)
989 log_error("Failed to read machine ID from %s: %s", p, strerror(-r));
994 if (isempty(id) && arg_link_journal == LINK_AUTO)
997 /* Verify validity */
998 r = sd_id128_from_string(id, &machine_id);
1000 log_error("Failed to parse machine ID from %s: %s", p, strerror(-r));
1004 r = sd_id128_get_machine(&this_id);
1006 log_error("Failed to retrieve machine ID: %s", strerror(-r));
1010 if (sd_id128_equal(machine_id, this_id)) {
1011 log_full(arg_link_journal == LINK_AUTO ? LOG_WARNING : LOG_ERR,
1012 "Host and machine ids are equal (%s): refusing to link journals", id);
1013 if (arg_link_journal == LINK_AUTO)
1019 if (arg_link_journal == LINK_NO)
1023 p = strappend("/var/log/journal/", id);
1024 q = strjoin(directory, "/var/log/journal/", id, NULL);
1028 if (path_is_mount_point(p, false) > 0) {
1029 if (arg_link_journal != LINK_AUTO) {
1030 log_error("%s: already a mount point, refusing to use for journal", p);
1037 if (path_is_mount_point(q, false) > 0) {
1038 if (arg_link_journal != LINK_AUTO) {
1039 log_error("%s: already a mount point, refusing to use for journal", q);
1046 r = readlink_and_make_absolute(p, &d);
1048 if ((arg_link_journal == LINK_GUEST ||
1049 arg_link_journal == LINK_AUTO) &&
1052 r = mkdir_p(q, 0755);
1054 log_warning("failed to create directory %s: %m", q);
1058 if (unlink(p) < 0) {
1059 log_error("Failed to remove symlink %s: %m", p);
1062 } else if (r == -EINVAL) {
1064 if (arg_link_journal == LINK_GUEST &&
1067 if (errno == ENOTDIR) {
1068 log_error("%s already exists and is neither a symlink nor a directory", p);
1071 log_error("Failed to remove %s: %m", p);
1075 } else if (r != -ENOENT) {
1076 log_error("readlink(%s) failed: %m", p);
1080 if (arg_link_journal == LINK_GUEST) {
1082 if (symlink(q, p) < 0) {
1083 log_error("Failed to symlink %s to %s: %m", q, p);
1087 r = mkdir_p(q, 0755);
1089 log_warning("failed to create directory %s: %m", q);
1093 if (arg_link_journal == LINK_HOST) {
1094 r = mkdir_p(p, 0755);
1096 log_error("Failed to create %s: %m", p);
1100 } else if (access(p, F_OK) < 0)
1103 if (dir_is_empty(q) == 0) {
1104 log_error("%s not empty.", q);
1108 r = mkdir_p(q, 0755);
1110 log_error("Failed to create %s: %m", q);
1114 if (mount(p, q, "bind", MS_BIND, NULL) < 0) {
1115 log_error("Failed to bind mount journal from host into guest: %m");
1122 static int setup_kdbus(const char *dest, const char *path) {
1128 p = strappenda(dest, "/dev/kdbus");
1129 if (mkdir(p, 0755) < 0) {
1130 log_error("Failed to create kdbus path: %m");
1134 if (mount(path, p, "bind", MS_BIND, NULL) < 0) {
1135 log_error("Failed to mount kdbus domain path: %m");
1142 static int drop_capabilities(void) {
1143 return capability_bounding_set_drop(~arg_retain, false);
1146 static int register_machine(pid_t pid) {
1147 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1148 _cleanup_bus_unref_ sd_bus *bus = NULL;
1154 r = sd_bus_default_system(&bus);
1156 log_error("Failed to open system bus: %s", strerror(-r));
1160 if (arg_keep_unit) {
1161 r = sd_bus_call_method(
1163 "org.freedesktop.machine1",
1164 "/org/freedesktop/machine1",
1165 "org.freedesktop.machine1.Manager",
1171 SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
1175 strempty(arg_directory));
1177 r = sd_bus_call_method(
1179 "org.freedesktop.machine1",
1180 "/org/freedesktop/machine1",
1181 "org.freedesktop.machine1.Manager",
1187 SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
1191 strempty(arg_directory),
1192 !isempty(arg_slice), "Slice", "s", arg_slice);
1196 log_error("Failed to register machine: %s", bus_error_message(&error, r));
1203 static int terminate_machine(pid_t pid) {
1204 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1205 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1206 _cleanup_bus_unref_ sd_bus *bus = NULL;
1213 r = sd_bus_default_system(&bus);
1215 log_error("Failed to open system bus: %s", strerror(-r));
1219 r = sd_bus_call_method(
1221 "org.freedesktop.machine1",
1222 "/org/freedesktop/machine1",
1223 "org.freedesktop.machine1.Manager",
1230 /* Note that the machine might already have been
1231 * cleaned up automatically, hence don't consider it a
1232 * failure if we cannot get the machine object. */
1233 log_debug("Failed to get machine: %s", bus_error_message(&error, r));
1237 r = sd_bus_message_read(reply, "o", &path);
1239 return bus_log_parse_error(r);
1241 r = sd_bus_call_method(
1243 "org.freedesktop.machine1",
1245 "org.freedesktop.machine1.Machine",
1251 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
1258 static int reset_audit_loginuid(void) {
1259 _cleanup_free_ char *p = NULL;
1262 if (arg_share_system)
1265 r = read_one_line_file("/proc/self/loginuid", &p);
1269 log_error("Failed to read /proc/self/loginuid: %s", strerror(-r));
1273 /* Already reset? */
1274 if (streq(p, "4294967295"))
1277 r = write_string_file("/proc/self/loginuid", "4294967295");
1279 log_error("Failed to reset audit login UID. This probably means that your kernel is too\n"
1280 "old and you have audit enabled. Note that the auditing subsystem is known to\n"
1281 "be incompatible with containers on old kernels. Please make sure to upgrade\n"
1282 "your kernel or to off auditing with 'audit=0' on the kernel command line before\n"
1283 "using systemd-nspawn. Sleeping for 5s... (%s)\n", strerror(-r));
1291 static int setup_veth(pid_t pid, char iface_name[]) {
1292 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1293 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
1296 if (!arg_private_network)
1299 if (!arg_network_veth)
1302 strncpy(iface_name+3, arg_machine, IFNAMSIZ - 3);
1304 r = sd_rtnl_open(0, &rtnl);
1306 log_error("Failed to connect to netlink: %s", strerror(-r));
1310 r = sd_rtnl_message_new_link(rtnl, RTM_NEWLINK, 0, &m);
1312 log_error("Failed to allocate netlink message: %s", strerror(-r));
1316 r = sd_rtnl_message_append_string(m, IFLA_IFNAME, iface_name);
1318 log_error("Failed to add netlink interface name: %s", strerror(-r));
1322 r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
1324 log_error("Failed to open netlink container: %s", strerror(-r));
1328 r = sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "veth");
1330 log_error("Failed to append netlink kind: %s", strerror(-r));
1334 r = sd_rtnl_message_open_container(m, IFLA_INFO_DATA);
1336 log_error("Failed to open netlink container: %s", strerror(-r));
1340 r = sd_rtnl_message_open_container(m, VETH_INFO_PEER);
1342 log_error("Failed to open netlink container: %s", strerror(-r));
1346 r = sd_rtnl_message_append_string(m, IFLA_IFNAME, "host0");
1348 log_error("Failed to add netlink interface name: %s", strerror(-r));
1352 r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_PID, pid);
1354 log_error("Failed to add netlink namespace field: %s", strerror(-r));
1358 r = sd_rtnl_message_close_container(m);
1360 log_error("Failed to close netlink container: %s", strerror(-r));
1364 r = sd_rtnl_message_close_container(m);
1366 log_error("Failed to close netlink container: %s", strerror(-r));
1370 r = sd_rtnl_message_close_container(m);
1372 log_error("Failed to close netlink container: %s", strerror(-r));
1376 r = sd_rtnl_call(rtnl, m, 0, NULL);
1378 log_error("Failed to add new veth interfaces: %s", strerror(-r));
1385 static int setup_bridge(const char veth_name[]) {
1386 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1387 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
1390 if (!arg_private_network)
1393 if (!arg_network_veth)
1396 if (!arg_network_bridge)
1399 bridge = (int) if_nametoindex(arg_network_bridge);
1401 log_error("Failed to resolve interface %s: %m", arg_network_bridge);
1405 r = sd_rtnl_open(0, &rtnl);
1407 log_error("Failed to connect to netlink: %s", strerror(-r));
1411 r = sd_rtnl_message_new_link(rtnl, RTM_SETLINK, 0, &m);
1413 log_error("Failed to allocate netlink message: %s", strerror(-r));
1417 r = sd_rtnl_message_append_string(m, IFLA_IFNAME, veth_name);
1419 log_error("Failed to add netlink interface name field: %s", strerror(-r));
1423 r = sd_rtnl_message_append_u32(m, IFLA_MASTER, bridge);
1425 log_error("Failed to add netlink master field: %s", strerror(-r));
1429 r = sd_rtnl_call(rtnl, m, 0, NULL);
1431 log_error("Failed to add veth interface to bridge: %s", strerror(-r));
1438 static int move_network_interfaces(pid_t pid) {
1439 _cleanup_udev_unref_ struct udev *udev = NULL;
1440 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
1444 if (!arg_private_network)
1447 if (strv_isempty(arg_network_interfaces))
1450 r = sd_rtnl_open(0, &rtnl);
1452 log_error("Failed to connect to netlink: %s", strerror(-r));
1458 log_error("Failed to connect to udev.");
1462 STRV_FOREACH(i, arg_network_interfaces) {
1463 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1464 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1465 char ifi_str[2 + DECIMAL_STR_MAX(int)];
1468 ifi = (int) if_nametoindex(*i);
1470 log_error("Failed to resolve interface %s: %m", *i);
1474 sprintf(ifi_str, "n%i", ifi);
1475 d = udev_device_new_from_device_id(udev, ifi_str);
1477 log_error("Failed to get udev device for interface %s: %m", *i);
1481 if (udev_device_get_is_initialized(d) <= 0) {
1482 log_error("Network interface %s is not initialized yet.", *i);
1486 r = sd_rtnl_message_new_link(rtnl, RTM_NEWLINK, ifi, &m);
1488 log_error("Failed to allocate netlink message: %s", strerror(-r));
1492 r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_PID, pid);
1494 log_error("Failed to append namespace PID to netlink message: %s", strerror(-r));
1498 r = sd_rtnl_call(rtnl, m, 0, NULL);
1500 log_error("Failed to move interface %s to namespace: %s", *i, strerror(-r));
1508 static int audit_still_doesnt_work_in_containers(void) {
1511 scmp_filter_ctx seccomp;
1515 Audit is broken in containers, much of the userspace audit
1516 hookup will fail if running inside a container. We don't
1517 care and just turn off creation of audit sockets.
1519 This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail
1520 with EAFNOSUPPORT which audit userspace uses as indication
1521 that audit is disabled in the kernel.
1524 seccomp = seccomp_init(SCMP_ACT_ALLOW);
1528 r = seccomp_add_secondary_archs(seccomp);
1529 if (r < 0 && r != -EEXIST) {
1530 log_error("Failed to add secondary archs to seccomp filter: %s", strerror(-r));
1534 r = seccomp_rule_add(
1536 SCMP_ACT_ERRNO(EAFNOSUPPORT),
1539 SCMP_A0(SCMP_CMP_EQ, AF_NETLINK),
1540 SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT));
1542 log_error("Failed to add audit seccomp rule: %s", strerror(-r));
1546 r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
1548 log_error("Failed to unset NO_NEW_PRIVS: %s", strerror(-r));
1552 r = seccomp_load(seccomp);
1554 log_error("Failed to install seccomp audit filter: %s", strerror(-r));
1557 seccomp_release(seccomp);
1565 int main(int argc, char *argv[]) {
1567 _cleanup_close_ int master = -1, kdbus_fd = -1, sync_fd = -1;
1568 _cleanup_close_pipe_ int kmsg_socket_pair[2] = { -1, -1 };
1569 _cleanup_free_ char *kdbus_domain = NULL;
1570 _cleanup_fdset_free_ FDSet *fds = NULL;
1571 const char *console = NULL;
1572 int r = EXIT_FAILURE, k;
1576 char veth_name[IFNAMSIZ] = "ve-";
1578 log_parse_environment();
1581 k = parse_argv(argc, argv);
1589 if (arg_directory) {
1592 p = path_make_absolute_cwd(arg_directory);
1593 free(arg_directory);
1596 arg_directory = get_current_dir_name();
1598 if (!arg_directory) {
1599 log_error("Failed to determine path, please use -D.");
1603 path_kill_slashes(arg_directory);
1606 arg_machine = strdup(basename(arg_directory));
1612 hostname_cleanup(arg_machine, false);
1613 if (isempty(arg_machine)) {
1614 log_error("Failed to determine machine name automatically, please use -M.");
1619 if (geteuid() != 0) {
1620 log_error("Need to be root.");
1624 if (sd_booted() <= 0) {
1625 log_error("Not running on a systemd system.");
1629 if (path_equal(arg_directory, "/")) {
1630 log_error("Spawning container on root directory not supported.");
1635 if (path_is_os_tree(arg_directory) <= 0) {
1636 log_error("Directory %s doesn't look like an OS root directory (/etc/os-release is missing). Refusing.", arg_directory);
1642 p = strappenda(arg_directory,
1643 argc > optind && path_is_absolute(argv[optind]) ? argv[optind] : "/usr/bin/");
1644 if (access(p, F_OK) < 0) {
1645 log_error("Directory %s lacks the binary to execute or doesn't look like a binary tree. Refusing.", arg_directory);
1652 n_fd_passed = sd_listen_fds(false);
1653 if (n_fd_passed > 0) {
1654 k = fdset_new_listen_fds(&fds, false);
1656 log_error("Failed to collect file descriptors: %s", strerror(-k));
1660 fdset_close_others(fds);
1663 master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
1665 log_error("Failed to acquire pseudo tty: %m");
1669 console = ptsname(master);
1671 log_error("Failed to determine tty name: %m");
1676 log_info("Spawning container %s on %s. Press ^] three times within 1s to abort execution.", arg_machine, arg_directory);
1678 if (unlockpt(master) < 0) {
1679 log_error("Failed to unlock tty: %m");
1683 if (access("/dev/kdbus/control", F_OK) >= 0) {
1685 if (arg_share_system) {
1686 kdbus_domain = strdup("/dev/kdbus");
1687 if (!kdbus_domain) {
1694 ns = strappenda("machine-", arg_machine);
1695 kdbus_fd = bus_kernel_create_domain(ns, &kdbus_domain);
1697 log_debug("Failed to create kdbus domain: %s", strerror(-r));
1699 log_debug("Successfully created kdbus domain as %s", kdbus_domain);
1703 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
1704 log_error("Failed to create kmsg socket pair: %m");
1708 sd_notify(0, "READY=1");
1710 assert_se(sigemptyset(&mask) == 0);
1711 sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
1712 assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
1717 sync_fd = eventfd(0, EFD_CLOEXEC);
1719 log_error("Failed to create event fd: %m");
1723 pid = syscall(__NR_clone,
1724 SIGCHLD|CLONE_NEWNS|
1725 (arg_share_system ? 0 : CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS)|
1726 (arg_private_network ? CLONE_NEWNET : 0), NULL);
1728 if (errno == EINVAL)
1729 log_error("clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m");
1731 log_error("clone() failed: %m");
1738 const char *home = NULL;
1739 uid_t uid = (uid_t) -1;
1740 gid_t gid = (gid_t) -1;
1742 const char *envp[] = {
1743 "PATH=" DEFAULT_PATH_SPLIT_USR,
1744 "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */
1749 NULL, /* container_uuid */
1750 NULL, /* LISTEN_FDS */
1751 NULL, /* LISTEN_PID */
1757 envp[n_env] = strv_find_prefix(environ, "TERM=");
1761 close_nointr_nofail(master);
1764 close_nointr(STDIN_FILENO);
1765 close_nointr(STDOUT_FILENO);
1766 close_nointr(STDERR_FILENO);
1768 close_nointr_nofail(kmsg_socket_pair[0]);
1769 kmsg_socket_pair[0] = -1;
1771 reset_all_signal_handlers();
1773 assert_se(sigemptyset(&mask) == 0);
1774 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
1776 k = open_terminal(console, O_RDWR);
1777 if (k != STDIN_FILENO) {
1779 close_nointr_nofail(k);
1783 log_error("Failed to open console: %s", strerror(-k));
1787 if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
1788 dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
1789 log_error("Failed to duplicate console: %m");
1794 log_error("setsid() failed: %m");
1798 if (reset_audit_loginuid() < 0)
1801 if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) {
1802 log_error("PR_SET_PDEATHSIG failed: %m");
1806 /* Mark everything as slave, so that we still
1807 * receive mounts from the real root, but don't
1808 * propagate mounts to the real root. */
1809 if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
1810 log_error("MS_SLAVE|MS_REC failed: %m");
1814 /* Turn directory into bind mount */
1815 if (mount(arg_directory, arg_directory, "bind", MS_BIND|MS_REC, NULL) < 0) {
1816 log_error("Failed to make bind mount.");
1821 if (mount(arg_directory, arg_directory, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0) {
1822 log_error("Failed to make read-only.");
1826 if (mount_all(arg_directory) < 0)
1829 if (copy_devnodes(arg_directory) < 0)
1832 if (setup_ptmx(arg_directory) < 0)
1835 dev_setup(arg_directory);
1837 if (audit_still_doesnt_work_in_containers() < 0)
1840 if (setup_dev_console(arg_directory, console) < 0)
1843 if (setup_kmsg(arg_directory, kmsg_socket_pair[1]) < 0)
1846 close_nointr_nofail(kmsg_socket_pair[1]);
1847 kmsg_socket_pair[1] = -1;
1849 if (setup_boot_id(arg_directory) < 0)
1852 if (setup_timezone(arg_directory) < 0)
1855 if (setup_resolv_conf(arg_directory) < 0)
1858 if (setup_journal(arg_directory) < 0)
1861 if (mount_binds(arg_directory, arg_bind, 0) < 0)
1864 if (mount_binds(arg_directory, arg_bind_ro, MS_RDONLY) < 0)
1867 if (setup_kdbus(arg_directory, kdbus_domain) < 0)
1870 if (chdir(arg_directory) < 0) {
1871 log_error("chdir(%s) failed: %m", arg_directory);
1875 if (mount(arg_directory, "/", NULL, MS_MOVE, NULL) < 0) {
1876 log_error("mount(MS_MOVE) failed: %m");
1880 if (chroot(".") < 0) {
1881 log_error("chroot() failed: %m");
1885 if (chdir("/") < 0) {
1886 log_error("chdir() failed: %m");
1892 if (arg_private_network)
1895 if (drop_capabilities() < 0) {
1896 log_error("drop_capabilities() failed: %m");
1902 /* Note that this resolves user names
1903 * inside the container, and hence
1904 * accesses the NSS modules from the
1905 * container and not the host. This is
1908 if (get_user_creds((const char**)&arg_user, &uid, &gid, &home, NULL) < 0) {
1909 log_error("get_user_creds() failed: %m");
1913 if (mkdir_parents_label(home, 0775) < 0) {
1914 log_error("mkdir_parents_label() failed: %m");
1918 if (mkdir_safe_label(home, 0775, uid, gid) < 0) {
1919 log_error("mkdir_safe_label() failed: %m");
1923 if (initgroups((const char*)arg_user, gid) < 0) {
1924 log_error("initgroups() failed: %m");
1928 if (setresgid(gid, gid, gid) < 0) {
1929 log_error("setregid() failed: %m");
1933 if (setresuid(uid, uid, uid) < 0) {
1934 log_error("setreuid() failed: %m");
1938 /* Reset everything fully to 0, just in case */
1940 if (setgroups(0, NULL) < 0) {
1941 log_error("setgroups() failed: %m");
1945 if (setresgid(0, 0, 0) < 0) {
1946 log_error("setregid() failed: %m");
1950 if (setresuid(0, 0, 0) < 0) {
1951 log_error("setreuid() failed: %m");
1956 if ((asprintf((char**)(envp + n_env++), "HOME=%s", home ? home: "/root") < 0) ||
1957 (asprintf((char**)(envp + n_env++), "USER=%s", arg_user ? arg_user : "root") < 0) ||
1958 (asprintf((char**)(envp + n_env++), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) {
1963 if (!sd_id128_equal(arg_uuid, SD_ID128_NULL)) {
1964 if (asprintf((char**)(envp + n_env++), "container_uuid=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(arg_uuid)) < 0) {
1970 if (fdset_size(fds) > 0) {
1971 k = fdset_cloexec(fds, false);
1973 log_error("Failed to unset O_CLOEXEC for file descriptors.");
1977 if ((asprintf((char **)(envp + n_env++), "LISTEN_FDS=%u", n_fd_passed) < 0) ||
1978 (asprintf((char **)(envp + n_env++), "LISTEN_PID=1") < 0)) {
1986 eventfd_read(sync_fd, &x);
1987 close_nointr_nofail(sync_fd);
1990 if (!strv_isempty(arg_setenv)) {
1993 n = strv_env_merge(2, envp, arg_setenv);
2001 env_use = (char**) envp;
2004 if (arg_selinux_context)
2005 if (setexeccon(arg_selinux_context) < 0)
2006 log_error("setexeccon(\"%s\") failed: %m", arg_selinux_context);
2012 /* Automatically search for the init system */
2014 l = 1 + argc - optind;
2015 a = newa(char*, l + 1);
2016 memcpy(a + 1, argv + optind, l * sizeof(char*));
2018 a[0] = (char*) "/usr/lib/systemd/systemd";
2019 execve(a[0], a, env_use);
2021 a[0] = (char*) "/lib/systemd/systemd";
2022 execve(a[0], a, env_use);
2024 a[0] = (char*) "/sbin/init";
2025 execve(a[0], a, env_use);
2026 } else if (argc > optind)
2027 execvpe(argv[optind], argv + optind, env_use);
2029 chdir(home ? home : "/root");
2030 execle("/bin/bash", "-bash", NULL, env_use);
2031 execle("/bin/sh", "-sh", NULL, env_use);
2034 log_error("execv() failed: %m");
2037 _exit(EXIT_FAILURE);
2043 r = register_machine(pid);
2047 r = move_network_interfaces(pid);
2051 r = setup_veth(pid, veth_name);
2055 r = setup_bridge(veth_name);
2059 eventfd_write(sync_fd, 1);
2060 close_nointr_nofail(sync_fd);
2063 k = process_pty(master, &mask, arg_boot ? pid : 0, SIGRTMIN+3);
2072 /* Kill if it is not dead yet anyway */
2073 terminate_machine(pid);
2075 /* Redundant, but better safe than sorry */
2078 k = wait_for_terminate(pid, &status);
2086 if (status.si_code == CLD_EXITED) {
2087 r = status.si_status;
2088 if (status.si_status != 0) {
2089 log_error("Container %s failed with error code %i.", arg_machine, status.si_status);
2094 log_debug("Container %s exited successfully.", arg_machine);
2096 } else if (status.si_code == CLD_KILLED &&
2097 status.si_status == SIGINT) {
2100 log_info("Container %s has been shut down.", arg_machine);
2103 } else if (status.si_code == CLD_KILLED &&
2104 status.si_status == SIGHUP) {
2107 log_info("Container %s is being rebooted.", arg_machine);
2109 } else if (status.si_code == CLD_KILLED ||
2110 status.si_code == CLD_DUMPED) {
2112 log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status));
2116 log_error("Container %s failed due to unknown reason.", arg_machine);
2126 free(arg_directory);
2129 free(arg_network_interfaces);