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>
36 #include <sys/epoll.h>
38 #include <sys/signalfd.h>
42 #include <sys/socket.h>
44 #include <systemd/sd-daemon.h>
51 #include "cgroup-util.h"
53 #include "path-util.h"
54 #include "loopback-setup.h"
56 static char *arg_directory = NULL;
57 static char *arg_user = NULL;
58 static char **arg_controllers = NULL;
59 static char *arg_uuid = NULL;
60 static bool arg_private_network = false;
61 static bool arg_read_only = false;
62 static bool arg_boot = false;
64 static int help(void) {
66 printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
67 "Spawn a minimal namespace container for debugging, testing and building.\n\n"
68 " -h --help Show this help\n"
69 " -D --directory=NAME Root directory for the container\n"
70 " -b --boot Boot up full system (i.e. invoke init)\n"
71 " -u --user=USER Run the command under specified user or uid\n"
72 " -C --controllers=LIST Put the container in specified comma-separated cgroup hierarchies\n"
73 " --uuid=UUID Set a specific machine UUID for the container\n"
74 " --private-network Disable network in container\n"
75 " --read-only Mount the root directory read-only\n",
76 program_invocation_short_name);
81 static int parse_argv(int argc, char *argv[]) {
84 ARG_PRIVATE_NETWORK = 0x100,
89 static const struct option options[] = {
90 { "help", no_argument, NULL, 'h' },
91 { "directory", required_argument, NULL, 'D' },
92 { "user", required_argument, NULL, 'u' },
93 { "controllers", required_argument, NULL, 'C' },
94 { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
95 { "boot", no_argument, NULL, 'b' },
96 { "uuid", required_argument, NULL, ARG_UUID },
97 { "read-only", no_argument, NULL, ARG_READ_ONLY },
106 while ((c = getopt_long(argc, argv, "+hD:u:C:b", options, NULL)) >= 0) {
116 arg_directory = canonicalize_file_name(optarg);
117 if (!arg_directory) {
118 log_error("Failed to canonicalize root directory.");
126 if (!(arg_user = strdup(optarg))) {
127 log_error("Failed to duplicate user name.");
134 strv_free(arg_controllers);
135 arg_controllers = strv_split(optarg, ",");
136 if (!arg_controllers) {
137 log_error("Failed to split controllers list.");
140 strv_uniq(arg_controllers);
144 case ARG_PRIVATE_NETWORK:
145 arg_private_network = true;
157 arg_read_only = true;
164 log_error("Unknown option code %c", c);
172 static int mount_all(const char *dest) {
174 typedef struct MountPoint {
183 static const MountPoint mount_table[] = {
184 { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
185 { "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND, true }, /* Bind mount first */
186 { "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
187 { "/sys", "/sys", "bind", NULL, MS_BIND, true }, /* Bind mount first */
188 { "/sys", "/sys", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
189 { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true },
190 { "/dev/pts", "/dev/pts", "bind", NULL, MS_BIND, true },
191 { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true },
193 { "/sys/fs/selinux", "/sys/fs/selinux", "bind", NULL, MS_BIND, false }, /* Bind mount first */
194 { "/sys/fs/selinux", "/sys/fs/selinux", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false }, /* Then, make it r/o */
202 for (k = 0; k < ELEMENTSOF(mount_table); k++) {
205 if (asprintf(&where, "%s/%s", dest, mount_table[k].where) < 0) {
206 log_error("Out of memory");
214 t = path_is_mount_point(where, false);
216 log_error("Failed to detect whether %s is a mount point: %s", where, strerror(-t));
225 mkdir_p_label(where, 0755);
227 if (mount(mount_table[k].what,
230 mount_table[k].flags,
231 mount_table[k].options) < 0 &&
232 mount_table[k].fatal) {
234 log_error("mount(%s) failed: %m", where);
246 static int setup_timezone(const char *dest) {
251 /* Fix the timezone, if possible */
252 if (asprintf(&where, "%s/etc/localtime", dest) < 0) {
253 log_error("Out of memory");
257 if (mount("/etc/localtime", where, "bind", MS_BIND, NULL) >= 0)
258 mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
262 if (asprintf(&where, "%s/etc/timezone", dest) < 0) {
263 log_error("Out of memory");
267 if (mount("/etc/timezone", where, "bind", MS_BIND, NULL) >= 0)
268 mount("/etc/timezone", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
275 static int setup_resolv_conf(const char *dest) {
280 if (arg_private_network)
283 /* Fix resolv.conf, if possible */
284 if (asprintf(&where, "%s/etc/resolv.conf", dest) < 0) {
285 log_error("Out of memory");
289 if (mount("/etc/resolv.conf", where, "bind", MS_BIND, NULL) >= 0)
290 mount("/etc/resolv.conf", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
297 static int copy_devnodes(const char *dest) {
299 static const char devnodes[] =
317 NULSTR_FOREACH(d, devnodes) {
319 char *from = NULL, *to = NULL;
321 asprintf(&from, "/dev/%s", d);
322 asprintf(&to, "%s/dev/%s", dest, d);
325 log_error("Failed to allocate devnode path");
338 if (stat(from, &st) < 0) {
340 if (errno != ENOENT) {
341 log_error("Failed to stat %s: %m", from);
346 } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
348 log_error("%s is not a char or block device, cannot copy.", from);
352 } else if (mknod(to, st.st_mode, st.st_rdev) < 0) {
354 log_error("mknod(%s) failed: %m", dest);
368 static int setup_dev_console(const char *dest, const char *console) {
379 if (stat(console, &st) < 0) {
380 log_error("Failed to stat %s: %m", console);
384 } else if (!S_ISCHR(st.st_mode)) {
385 log_error("/dev/console is not a char device.");
390 r = chmod_and_chown(console, 0600, 0, 0);
392 log_error("Failed to correct access mode for TTY: %s", strerror(-r));
396 if (asprintf(&to, "%s/dev/console", dest) < 0) {
397 log_error("Out of memory");
402 /* We need to bind mount the right tty to /dev/console since
403 * ptys can only exist on pts file systems. To have something
404 * to bind mount things on we create a device node first, that
405 * has the right major/minor (note that the major minor
406 * doesn't actually matter here, since we mount it over
409 if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) {
410 log_error("mknod() for /dev/console failed: %m");
415 if (mount(console, to, "bind", MS_BIND, NULL) < 0) {
416 log_error("Bind mount for /dev/console failed: %m");
428 static int setup_kmsg(const char *dest, int kmsg_socket) {
429 char *from = NULL, *to = NULL;
433 struct cmsghdr cmsghdr;
434 uint8_t buf[CMSG_SPACE(sizeof(int))];
437 struct cmsghdr *cmsg;
440 assert(kmsg_socket >= 0);
444 /* We create the kmsg FIFO as /dev/kmsg, but immediately
445 * delete it after bind mounting it to /proc/kmsg. While FIFOs
446 * on the reading side behave very similar to /proc/kmsg,
447 * their writing side behaves differently from /dev/kmsg in
448 * that writing blocks when nothing is reading. In order to
449 * avoid any problems with containers deadlocking due to this
450 * we simply make /dev/kmsg unavailable to the container. */
451 if (asprintf(&from, "%s/dev/kmsg", dest) < 0) {
452 log_error("Out of memory");
457 if (asprintf(&to, "%s/proc/kmsg", dest) < 0) {
458 log_error("Out of memory");
463 if (mkfifo(from, 0600) < 0) {
464 log_error("mkfifo() for /dev/kmsg failed: %m");
469 r = chmod_and_chown(from, 0600, 0, 0);
471 log_error("Failed to correct access mode for /dev/kmsg: %s", strerror(-r));
475 if (mount(from, to, "bind", MS_BIND, NULL) < 0) {
476 log_error("Bind mount for /proc/kmsg failed: %m");
481 fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC);
483 log_error("Failed to open fifo: %m");
491 mh.msg_control = &control;
492 mh.msg_controllen = sizeof(control);
494 cmsg = CMSG_FIRSTHDR(&mh);
495 cmsg->cmsg_level = SOL_SOCKET;
496 cmsg->cmsg_type = SCM_RIGHTS;
497 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
498 memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
500 mh.msg_controllen = cmsg->cmsg_len;
502 /* Store away the fd in the socket, so that it stays open as
503 * long as we run the child */
504 k = sendmsg(kmsg_socket, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
505 close_nointr_nofail(fd);
508 log_error("Failed to send FIFO fd: %m");
513 /* And now make the FIFO unavailable as /dev/kmsg... */
524 static int setup_hostname(void) {
528 hn = path_get_file_name(arg_directory);
534 hostname_cleanup(hn);
537 if (sethostname(hn, strlen(hn)) < 0)
546 static int drop_capabilities(void) {
548 static const uint64_t retain =
549 (1ULL << CAP_CHOWN) |
550 (1ULL << CAP_DAC_OVERRIDE) |
551 (1ULL << CAP_DAC_READ_SEARCH) |
552 (1ULL << CAP_FOWNER) |
553 (1ULL << CAP_FSETID) |
554 (1ULL << CAP_IPC_OWNER) |
556 (1ULL << CAP_LEASE) |
557 (1ULL << CAP_LINUX_IMMUTABLE) |
558 (1ULL << CAP_NET_BIND_SERVICE) |
559 (1ULL << CAP_NET_BROADCAST) |
560 (1ULL << CAP_NET_RAW) |
561 (1ULL << CAP_SETGID) |
562 (1ULL << CAP_SETFCAP) |
563 (1ULL << CAP_SETPCAP) |
564 (1ULL << CAP_SETUID) |
565 (1ULL << CAP_SYS_ADMIN) |
566 (1ULL << CAP_SYS_CHROOT) |
567 (1ULL << CAP_SYS_NICE) |
568 (1ULL << CAP_SYS_PTRACE) |
569 (1ULL << CAP_SYS_TTY_CONFIG);
571 return capability_bounding_set_drop(~retain, false);
574 static int is_os_tree(const char *path) {
577 /* We use /bin/sh as flag file if something is an OS */
579 if (asprintf(&p, "%s/bin/sh", path) < 0)
585 return r < 0 ? 0 : 1;
588 static int process_pty(int master, sigset_t *mask) {
590 char in_buffer[LINE_MAX], out_buffer[LINE_MAX];
591 size_t in_buffer_full = 0, out_buffer_full = 0;
592 struct epoll_event stdin_ev, stdout_ev, master_ev, signal_ev;
593 bool stdin_readable = false, stdout_writable = false, master_readable = false, master_writable = false;
594 int ep = -1, signal_fd = -1, r;
596 fd_nonblock(STDIN_FILENO, 1);
597 fd_nonblock(STDOUT_FILENO, 1);
598 fd_nonblock(master, 1);
600 if ((signal_fd = signalfd(-1, mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
601 log_error("signalfd(): %m");
606 if ((ep = epoll_create1(EPOLL_CLOEXEC)) < 0) {
607 log_error("Failed to create epoll: %m");
613 stdin_ev.events = EPOLLIN|EPOLLET;
614 stdin_ev.data.fd = STDIN_FILENO;
617 stdout_ev.events = EPOLLOUT|EPOLLET;
618 stdout_ev.data.fd = STDOUT_FILENO;
621 master_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
622 master_ev.data.fd = master;
625 signal_ev.events = EPOLLIN;
626 signal_ev.data.fd = signal_fd;
628 if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0 ||
629 epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0 ||
630 epoll_ctl(ep, EPOLL_CTL_ADD, master, &master_ev) < 0 ||
631 epoll_ctl(ep, EPOLL_CTL_ADD, signal_fd, &signal_ev) < 0) {
632 log_error("Failed to regiser fds in epoll: %m");
638 struct epoll_event ev[16];
642 if ((nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), -1)) < 0) {
644 if (errno == EINTR || errno == EAGAIN)
647 log_error("epoll_wait(): %m");
654 for (i = 0; i < nfds; i++) {
655 if (ev[i].data.fd == STDIN_FILENO) {
657 if (ev[i].events & (EPOLLIN|EPOLLHUP))
658 stdin_readable = true;
660 } else if (ev[i].data.fd == STDOUT_FILENO) {
662 if (ev[i].events & (EPOLLOUT|EPOLLHUP))
663 stdout_writable = true;
665 } else if (ev[i].data.fd == master) {
667 if (ev[i].events & (EPOLLIN|EPOLLHUP))
668 master_readable = true;
670 if (ev[i].events & (EPOLLOUT|EPOLLHUP))
671 master_writable = true;
673 } else if (ev[i].data.fd == signal_fd) {
674 struct signalfd_siginfo sfsi;
677 if ((n = read(signal_fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
680 log_error("Failed to read from signalfd: invalid block size");
685 if (errno != EINTR && errno != EAGAIN) {
686 log_error("Failed to read from signalfd: %m");
692 if (sfsi.ssi_signo == SIGWINCH) {
695 /* The window size changed, let's forward that. */
696 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
697 ioctl(master, TIOCSWINSZ, &ws);
706 while ((stdin_readable && in_buffer_full <= 0) ||
707 (master_writable && in_buffer_full > 0) ||
708 (master_readable && out_buffer_full <= 0) ||
709 (stdout_writable && out_buffer_full > 0)) {
711 if (stdin_readable && in_buffer_full < LINE_MAX) {
713 if ((k = read(STDIN_FILENO, in_buffer + in_buffer_full, LINE_MAX - in_buffer_full)) < 0) {
715 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
716 stdin_readable = false;
718 log_error("read(): %m");
723 in_buffer_full += (size_t) k;
726 if (master_writable && in_buffer_full > 0) {
728 if ((k = write(master, in_buffer, in_buffer_full)) < 0) {
730 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
731 master_writable = false;
733 log_error("write(): %m");
739 assert(in_buffer_full >= (size_t) k);
740 memmove(in_buffer, in_buffer + k, in_buffer_full - k);
745 if (master_readable && out_buffer_full < LINE_MAX) {
747 if ((k = read(master, out_buffer + out_buffer_full, LINE_MAX - out_buffer_full)) < 0) {
749 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
750 master_readable = false;
752 log_error("read(): %m");
757 out_buffer_full += (size_t) k;
760 if (stdout_writable && out_buffer_full > 0) {
762 if ((k = write(STDOUT_FILENO, out_buffer, out_buffer_full)) < 0) {
764 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
765 stdout_writable = false;
767 log_error("write(): %m");
773 assert(out_buffer_full >= (size_t) k);
774 memmove(out_buffer, out_buffer + k, out_buffer_full - k);
775 out_buffer_full -= k;
783 close_nointr_nofail(ep);
786 close_nointr_nofail(signal_fd);
791 int main(int argc, char *argv[]) {
793 int r = EXIT_FAILURE, k;
794 char *oldcg = NULL, *newcg = NULL;
795 char **controller = NULL;
797 const char *console = NULL;
798 struct termios saved_attr, raw_attr;
800 bool saved_attr_valid = false;
802 int kmsg_socket_pair[2] = { -1, -1 };
804 log_parse_environment();
807 if ((r = parse_argv(argc, argv)) <= 0)
813 p = path_make_absolute_cwd(arg_directory);
817 arg_directory = get_current_dir_name();
819 if (!arg_directory) {
820 log_error("Failed to determine path");
824 path_kill_slashes(arg_directory);
826 if (geteuid() != 0) {
827 log_error("Need to be root.");
831 if (sd_booted() <= 0) {
832 log_error("Not running on a systemd system.");
836 if (path_equal(arg_directory, "/")) {
837 log_error("Spawning container on root directory not supported.");
841 if (is_os_tree(arg_directory) <= 0) {
842 log_error("Directory %s doesn't look like an OS root directory. Refusing.", arg_directory);
846 if ((k = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &oldcg)) < 0) {
847 log_error("Failed to determine current cgroup: %s", strerror(-k));
851 if (asprintf(&newcg, "%s/nspawn-%lu", oldcg, (unsigned long) getpid()) < 0) {
852 log_error("Failed to allocate cgroup path.");
856 k = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, newcg, 0);
858 log_error("Failed to create cgroup: %s", strerror(-k));
862 STRV_FOREACH(controller,arg_controllers) {
863 k = cg_create_and_attach(*controller, newcg, 0);
865 log_warning("Failed to create cgroup in controller %s: %s", *controller, strerror(-k));
868 if ((master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY)) < 0) {
869 log_error("Failed to acquire pseudo tty: %m");
873 if (!(console = ptsname(master))) {
874 log_error("Failed to determine tty name: %m");
878 log_info("Spawning namespace container on %s (console is %s).", arg_directory, console);
880 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
881 ioctl(master, TIOCSWINSZ, &ws);
883 if (unlockpt(master) < 0) {
884 log_error("Failed to unlock tty: %m");
888 if (tcgetattr(STDIN_FILENO, &saved_attr) < 0) {
889 log_error("Failed to get terminal attributes: %m");
893 saved_attr_valid = true;
895 raw_attr = saved_attr;
896 cfmakeraw(&raw_attr);
897 raw_attr.c_lflag &= ~ECHO;
899 if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) {
900 log_error("Failed to set terminal attributes: %m");
904 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
905 log_error("Failed to create kmsg socket pair");
909 assert_se(sigemptyset(&mask) == 0);
910 sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
911 assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
913 pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS|(arg_private_network ? CLONE_NEWNET : 0), NULL);
916 log_error("clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m");
918 log_error("clone() failed: %m");
926 const char *home = NULL;
927 uid_t uid = (uid_t) -1;
928 gid_t gid = (gid_t) -1;
929 const char *envp[] = {
930 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
931 "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */
936 NULL, /* container_uuid */
940 envp[2] = strv_find_prefix(environ, "TERM=");
942 close_nointr_nofail(master);
944 close_nointr(STDIN_FILENO);
945 close_nointr(STDOUT_FILENO);
946 close_nointr(STDERR_FILENO);
948 close_all_fds(&kmsg_socket_pair[1], 1);
950 reset_all_signal_handlers();
952 assert_se(sigemptyset(&mask) == 0);
953 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
958 if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
961 /* Mark / as private, in case somebody marked it shared */
962 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
965 /* Turn directory into bind mount */
966 if (mount(arg_directory, arg_directory, "bind", MS_BIND, NULL) < 0) {
967 log_error("Failed to make bind mount.");
972 if (mount(arg_directory, arg_directory, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
973 log_error("Failed to make read-only.");
977 if (mount_all(arg_directory) < 0)
980 if (copy_devnodes(arg_directory) < 0)
983 if (setup_dev_console(arg_directory, console) < 0)
986 if (setup_kmsg(arg_directory, kmsg_socket_pair[1]) < 0)
989 close_nointr_nofail(kmsg_socket_pair[1]);
991 if (setup_timezone(arg_directory) < 0)
994 if (setup_resolv_conf(arg_directory) < 0)
997 if (chdir(arg_directory) < 0) {
998 log_error("chdir(%s) failed: %m", arg_directory);
1002 if (open_terminal("dev/console", O_RDWR) != STDIN_FILENO ||
1003 dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
1004 dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
1007 if (mount(arg_directory, "/", "bind", MS_MOVE, NULL) < 0) {
1008 log_error("mount(MS_BIND) failed: %m");
1012 if (chroot(".") < 0) {
1013 log_error("chroot() failed: %m");
1017 if (chdir("/") < 0) {
1018 log_error("chdir() failed: %m");
1026 if (drop_capabilities() < 0) {
1027 log_error("drop_capabilities() failed: %m");
1033 if (get_user_creds((const char**)&arg_user, &uid, &gid, &home) < 0) {
1034 log_error("get_user_creds() failed: %m");
1038 if (mkdir_parents_label(home, 0775) < 0) {
1039 log_error("mkdir_parents_label() failed: %m");
1043 if (mkdir_safe_label(home, 0775, uid, gid) < 0) {
1044 log_error("mkdir_safe_label() failed: %m");
1048 if (initgroups((const char*)arg_user, gid) < 0) {
1049 log_error("initgroups() failed: %m");
1053 if (setresgid(gid, gid, gid) < 0) {
1054 log_error("setregid() failed: %m");
1058 if (setresuid(uid, uid, uid) < 0) {
1059 log_error("setreuid() failed: %m");
1064 if ((asprintf((char**)(envp + 3), "HOME=%s", home ? home: "/root") < 0) ||
1065 (asprintf((char**)(envp + 4), "USER=%s", arg_user ? arg_user : "root") < 0) ||
1066 (asprintf((char**)(envp + 5), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) {
1067 log_error("Out of memory");
1072 if (asprintf((char**)(envp + 6), "container_uuid=%s", arg_uuid) < 0) {
1073 log_error("Out of memory");
1084 /* Automatically search for the init system */
1086 l = 1 + argc - optind;
1087 a = newa(char*, l + 1);
1088 memcpy(a + 1, argv + optind, l * sizeof(char*));
1090 a[0] = (char*) "/usr/lib/systemd/systemd";
1091 execve(a[0], a, (char**) envp);
1093 a[0] = (char*) "/lib/systemd/systemd";
1094 execve(a[0], a, (char**) envp);
1096 a[0] = (char*) "/sbin/init";
1097 execve(a[0], a, (char**) envp);
1098 } else if (argc > optind)
1099 execvpe(argv[optind], argv + optind, (char**) envp);
1101 chdir(home ? home : "/root");
1102 execle("/bin/bash", "-bash", NULL, (char**) envp);
1105 log_error("execv() failed: %m");
1108 _exit(EXIT_FAILURE);
1111 if (process_pty(master, &mask) < 0)
1114 if (saved_attr_valid) {
1115 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
1116 saved_attr_valid = false;
1119 r = wait_for_terminate_and_warn(argc > optind ? argv[optind] : "bash", pid);
1125 if (saved_attr_valid)
1126 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
1129 close_nointr_nofail(master);
1131 close_pipe(kmsg_socket_pair);
1134 cg_attach(SYSTEMD_CGROUP_CONTROLLER, oldcg, 0);
1137 cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
1139 free(arg_directory);
1140 strv_free(arg_controllers);