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 "loopback-setup.h"
55 static char *arg_directory = NULL;
56 static char *arg_user = NULL;
57 static char **arg_controllers = NULL;
58 static char *arg_uuid = NULL;
59 static bool arg_private_network = false;
60 static bool arg_boot = false;
62 static int help(void) {
64 printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
65 "Spawn a minimal namespace container for debugging, testing and building.\n\n"
66 " -h --help Show this help\n"
67 " -D --directory=NAME Root directory for the container\n"
68 " -b --boot Boot up full system (i.e. invoke init)\n"
69 " -u --user=USER Run the command under specified user or uid\n"
70 " -C --controllers=LIST Put the container in specified comma-separated cgroup hierarchies\n"
71 " --uuid=UUID Set a specific machine UUID for the container\n"
72 " --private-network Disable network in container\n",
73 program_invocation_short_name);
78 static int parse_argv(int argc, char *argv[]) {
81 ARG_PRIVATE_NETWORK = 0x100,
85 static const struct option options[] = {
86 { "help", no_argument, NULL, 'h' },
87 { "directory", required_argument, NULL, 'D' },
88 { "user", required_argument, NULL, 'u' },
89 { "controllers", required_argument, NULL, 'C' },
90 { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
91 { "boot", no_argument, NULL, 'b' },
92 { "uuid", required_argument, NULL, ARG_UUID },
101 while ((c = getopt_long(argc, argv, "+hD:u:C:b", options, NULL)) >= 0) {
111 arg_directory = canonicalize_file_name(optarg);
112 if (!arg_directory) {
113 log_error("Failed to canonicalize root directory.");
121 if (!(arg_user = strdup(optarg))) {
122 log_error("Failed to duplicate user name.");
129 strv_free(arg_controllers);
130 arg_controllers = strv_split(optarg, ",");
131 if (!arg_controllers) {
132 log_error("Failed to split controllers list.");
135 strv_uniq(arg_controllers);
139 case ARG_PRIVATE_NETWORK:
140 arg_private_network = true;
155 log_error("Unknown option code %c", c);
163 static int mount_all(const char *dest) {
165 typedef struct MountPoint {
174 static const MountPoint mount_table[] = {
175 { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
176 { "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND, true }, /* Bind mount first */
177 { "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
178 { "/sys", "/sys", "bind", NULL, MS_BIND, true }, /* Bind mount first */
179 { "/sys", "/sys", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
180 { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true },
181 { "/dev/pts", "/dev/pts", "bind", NULL, MS_BIND, true },
182 { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true },
184 { "/sys/fs/selinux", "/sys/fs/selinux", "bind", NULL, MS_BIND, false }, /* Bind mount first */
185 { "/sys/fs/selinux", "/sys/fs/selinux", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false }, /* Then, make it r/o */
193 for (k = 0; k < ELEMENTSOF(mount_table); k++) {
196 if (asprintf(&where, "%s/%s", dest, mount_table[k].where) < 0) {
197 log_error("Out of memory");
205 t = path_is_mount_point(where, false);
207 log_error("Failed to detect whether %s is a mount point: %s", where, strerror(-t));
216 mkdir_p(where, 0755);
218 if (mount(mount_table[k].what,
221 mount_table[k].flags,
222 mount_table[k].options) < 0 &&
223 mount_table[k].fatal) {
225 log_error("mount(%s) failed: %m", where);
237 static int setup_timezone(const char *dest) {
242 /* Fix the timezone, if possible */
243 if (asprintf(&where, "%s/etc/localtime", dest) < 0) {
244 log_error("Out of memory");
248 if (mount("/etc/localtime", where, "bind", MS_BIND, NULL) >= 0)
249 mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
253 if (asprintf(&where, "%s/etc/timezone", dest) < 0) {
254 log_error("Out of memory");
258 if (mount("/etc/timezone", where, "bind", MS_BIND, NULL) >= 0)
259 mount("/etc/timezone", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
266 static int copy_devnodes(const char *dest) {
268 static const char devnodes[] =
286 NULSTR_FOREACH(d, devnodes) {
288 char *from = NULL, *to = NULL;
290 asprintf(&from, "/dev/%s", d);
291 asprintf(&to, "%s/dev/%s", dest, d);
294 log_error("Failed to allocate devnode path");
307 if (stat(from, &st) < 0) {
309 if (errno != ENOENT) {
310 log_error("Failed to stat %s: %m", from);
315 } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
317 log_error("%s is not a char or block device, cannot copy.", from);
321 } else if (mknod(to, st.st_mode, st.st_rdev) < 0) {
323 log_error("mknod(%s) failed: %m", dest);
337 static int setup_dev_console(const char *dest, const char *console) {
348 if (stat(console, &st) < 0) {
349 log_error("Failed to stat %s: %m", console);
353 } else if (!S_ISCHR(st.st_mode)) {
354 log_error("/dev/console is not a char device.");
359 r = chmod_and_chown(console, 0600, 0, 0);
361 log_error("Failed to correct access mode for TTY: %s", strerror(-r));
365 if (asprintf(&to, "%s/dev/console", dest) < 0) {
366 log_error("Out of memory");
371 /* We need to bind mount the right tty to /dev/console since
372 * ptys can only exist on pts file systems. To have something
373 * to bind mount things on we create a device node first, that
374 * has the right major/minor (note that the major minor
375 * doesn't actually matter here, since we mount it over
378 if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) {
379 log_error("mknod() for /dev/console failed: %m");
384 if (mount(console, to, "bind", MS_BIND, NULL) < 0) {
385 log_error("Bind mount for /dev/console failed: %m");
397 static int setup_kmsg(const char *dest, int kmsg_socket) {
398 char *from = NULL, *to = NULL;
402 struct cmsghdr cmsghdr;
403 uint8_t buf[CMSG_SPACE(sizeof(int))];
406 struct cmsghdr *cmsg;
409 assert(kmsg_socket >= 0);
413 /* We create the kmsg FIFO as /dev/kmsg, but immediately
414 * delete it after bind mounting it to /proc/kmsg. While FIFOs
415 * on the reading side behave very similar to /proc/kmsg,
416 * their writing side behaves differently from /dev/kmsg in
417 * that writing blocks when nothing is reading. In order to
418 * avoid any problems with containers deadlocking due to this
419 * we simply make /dev/kmsg unavailable to the container. */
420 if (asprintf(&from, "%s/dev/kmsg", dest) < 0) {
421 log_error("Out of memory");
426 if (asprintf(&to, "%s/proc/kmsg", dest) < 0) {
427 log_error("Out of memory");
432 if (mkfifo(from, 0600) < 0) {
433 log_error("mkfifo() for /dev/kmsg failed: %m");
438 r = chmod_and_chown(from, 0600, 0, 0);
440 log_error("Failed to correct access mode for /dev/kmsg: %s", strerror(-r));
444 if (mount(from, to, "bind", MS_BIND, NULL) < 0) {
445 log_error("Bind mount for /proc/kmsg failed: %m");
450 fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC);
452 log_error("Failed to open fifo: %m");
460 mh.msg_control = &control;
461 mh.msg_controllen = sizeof(control);
463 cmsg = CMSG_FIRSTHDR(&mh);
464 cmsg->cmsg_level = SOL_SOCKET;
465 cmsg->cmsg_type = SCM_RIGHTS;
466 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
467 memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
469 mh.msg_controllen = cmsg->cmsg_len;
471 /* Store away the fd in the socket, so that it stays open as
472 * long as we run the child */
473 k = sendmsg(kmsg_socket, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
474 close_nointr_nofail(fd);
477 log_error("Failed to send FIFO fd: %m");
482 /* And now make the FIFO unavailable as /dev/kmsg... */
493 static int setup_hostname(void) {
497 hn = file_name_from_path(arg_directory);
503 hostname_cleanup(hn);
506 if (sethostname(hn, strlen(hn)) < 0)
515 static int drop_capabilities(void) {
516 static const unsigned long retain[] = {
526 CAP_NET_BIND_SERVICE,
542 for (l = 0; l <= cap_last_cap(); l++) {
545 for (i = 0; i < ELEMENTSOF(retain); i++)
549 if (i < ELEMENTSOF(retain))
552 if (prctl(PR_CAPBSET_DROP, l) < 0) {
553 log_error("PR_CAPBSET_DROP failed: %m");
561 static int is_os_tree(const char *path) {
564 /* We use /bin/sh as flag file if something is an OS */
566 if (asprintf(&p, "%s/bin/sh", path) < 0)
572 return r < 0 ? 0 : 1;
575 static int process_pty(int master, sigset_t *mask) {
577 char in_buffer[LINE_MAX], out_buffer[LINE_MAX];
578 size_t in_buffer_full = 0, out_buffer_full = 0;
579 struct epoll_event stdin_ev, stdout_ev, master_ev, signal_ev;
580 bool stdin_readable = false, stdout_writable = false, master_readable = false, master_writable = false;
581 int ep = -1, signal_fd = -1, r;
583 fd_nonblock(STDIN_FILENO, 1);
584 fd_nonblock(STDOUT_FILENO, 1);
585 fd_nonblock(master, 1);
587 if ((signal_fd = signalfd(-1, mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
588 log_error("signalfd(): %m");
593 if ((ep = epoll_create1(EPOLL_CLOEXEC)) < 0) {
594 log_error("Failed to create epoll: %m");
600 stdin_ev.events = EPOLLIN|EPOLLET;
601 stdin_ev.data.fd = STDIN_FILENO;
604 stdout_ev.events = EPOLLOUT|EPOLLET;
605 stdout_ev.data.fd = STDOUT_FILENO;
608 master_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
609 master_ev.data.fd = master;
612 signal_ev.events = EPOLLIN;
613 signal_ev.data.fd = signal_fd;
615 if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0 ||
616 epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0 ||
617 epoll_ctl(ep, EPOLL_CTL_ADD, master, &master_ev) < 0 ||
618 epoll_ctl(ep, EPOLL_CTL_ADD, signal_fd, &signal_ev) < 0) {
619 log_error("Failed to regiser fds in epoll: %m");
625 struct epoll_event ev[16];
629 if ((nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), -1)) < 0) {
631 if (errno == EINTR || errno == EAGAIN)
634 log_error("epoll_wait(): %m");
641 for (i = 0; i < nfds; i++) {
642 if (ev[i].data.fd == STDIN_FILENO) {
644 if (ev[i].events & (EPOLLIN|EPOLLHUP))
645 stdin_readable = true;
647 } else if (ev[i].data.fd == STDOUT_FILENO) {
649 if (ev[i].events & (EPOLLOUT|EPOLLHUP))
650 stdout_writable = true;
652 } else if (ev[i].data.fd == master) {
654 if (ev[i].events & (EPOLLIN|EPOLLHUP))
655 master_readable = true;
657 if (ev[i].events & (EPOLLOUT|EPOLLHUP))
658 master_writable = true;
660 } else if (ev[i].data.fd == signal_fd) {
661 struct signalfd_siginfo sfsi;
664 if ((n = read(signal_fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
667 log_error("Failed to read from signalfd: invalid block size");
672 if (errno != EINTR && errno != EAGAIN) {
673 log_error("Failed to read from signalfd: %m");
679 if (sfsi.ssi_signo == SIGWINCH) {
682 /* The window size changed, let's forward that. */
683 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
684 ioctl(master, TIOCSWINSZ, &ws);
693 while ((stdin_readable && in_buffer_full <= 0) ||
694 (master_writable && in_buffer_full > 0) ||
695 (master_readable && out_buffer_full <= 0) ||
696 (stdout_writable && out_buffer_full > 0)) {
698 if (stdin_readable && in_buffer_full < LINE_MAX) {
700 if ((k = read(STDIN_FILENO, in_buffer + in_buffer_full, LINE_MAX - in_buffer_full)) < 0) {
702 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
703 stdin_readable = false;
705 log_error("read(): %m");
710 in_buffer_full += (size_t) k;
713 if (master_writable && in_buffer_full > 0) {
715 if ((k = write(master, in_buffer, in_buffer_full)) < 0) {
717 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
718 master_writable = false;
720 log_error("write(): %m");
726 assert(in_buffer_full >= (size_t) k);
727 memmove(in_buffer, in_buffer + k, in_buffer_full - k);
732 if (master_readable && out_buffer_full < LINE_MAX) {
734 if ((k = read(master, out_buffer + out_buffer_full, LINE_MAX - out_buffer_full)) < 0) {
736 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
737 master_readable = false;
739 log_error("read(): %m");
744 out_buffer_full += (size_t) k;
747 if (stdout_writable && out_buffer_full > 0) {
749 if ((k = write(STDOUT_FILENO, out_buffer, out_buffer_full)) < 0) {
751 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
752 stdout_writable = false;
754 log_error("write(): %m");
760 assert(out_buffer_full >= (size_t) k);
761 memmove(out_buffer, out_buffer + k, out_buffer_full - k);
762 out_buffer_full -= k;
770 close_nointr_nofail(ep);
773 close_nointr_nofail(signal_fd);
778 int main(int argc, char *argv[]) {
780 int r = EXIT_FAILURE, k;
781 char *oldcg = NULL, *newcg = NULL;
782 char **controller = NULL;
784 const char *console = NULL;
785 struct termios saved_attr, raw_attr;
787 bool saved_attr_valid = false;
789 int kmsg_socket_pair[2] = { -1, -1 };
791 log_parse_environment();
794 if ((r = parse_argv(argc, argv)) <= 0)
800 p = path_make_absolute_cwd(arg_directory);
804 arg_directory = get_current_dir_name();
806 if (!arg_directory) {
807 log_error("Failed to determine path");
811 path_kill_slashes(arg_directory);
813 if (geteuid() != 0) {
814 log_error("Need to be root.");
818 if (sd_booted() <= 0) {
819 log_error("Not running on a systemd system.");
823 if (path_equal(arg_directory, "/")) {
824 log_error("Spawning container on root directory not supported.");
828 if (is_os_tree(arg_directory) <= 0) {
829 log_error("Directory %s doesn't look like an OS root directory. Refusing.", arg_directory);
833 if ((k = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &oldcg)) < 0) {
834 log_error("Failed to determine current cgroup: %s", strerror(-k));
838 if (asprintf(&newcg, "%s/nspawn-%lu", oldcg, (unsigned long) getpid()) < 0) {
839 log_error("Failed to allocate cgroup path.");
843 k = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, newcg, 0);
845 log_error("Failed to create cgroup: %s", strerror(-k));
849 STRV_FOREACH(controller,arg_controllers) {
850 k = cg_create_and_attach(*controller, newcg, 0);
852 log_warning("Failed to create cgroup in controller %s: %s", *controller, strerror(-k));
855 if ((master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY)) < 0) {
856 log_error("Failed to acquire pseudo tty: %m");
860 if (!(console = ptsname(master))) {
861 log_error("Failed to determine tty name: %m");
865 log_info("Spawning namespace container on %s (console is %s).", arg_directory, console);
867 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
868 ioctl(master, TIOCSWINSZ, &ws);
870 if (unlockpt(master) < 0) {
871 log_error("Failed to unlock tty: %m");
875 if (tcgetattr(STDIN_FILENO, &saved_attr) < 0) {
876 log_error("Failed to get terminal attributes: %m");
880 saved_attr_valid = true;
882 raw_attr = saved_attr;
883 cfmakeraw(&raw_attr);
884 raw_attr.c_lflag &= ~ECHO;
886 if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) {
887 log_error("Failed to set terminal attributes: %m");
891 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
892 log_error("Failed to create kmsg socket pair");
896 assert_se(sigemptyset(&mask) == 0);
897 sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
898 assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
900 pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS|(arg_private_network ? CLONE_NEWNET : 0), NULL);
903 log_error("clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m");
905 log_error("clone() failed: %m");
913 const char *home = NULL;
914 uid_t uid = (uid_t) -1;
915 gid_t gid = (gid_t) -1;
916 const char *envp[] = {
917 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
918 "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */
923 NULL, /* container_uuid */
927 envp[2] = strv_find_prefix(environ, "TERM=");
929 close_nointr_nofail(master);
931 close_nointr(STDIN_FILENO);
932 close_nointr(STDOUT_FILENO);
933 close_nointr(STDERR_FILENO);
935 close_all_fds(&kmsg_socket_pair[1], 1);
937 reset_all_signal_handlers();
939 assert_se(sigemptyset(&mask) == 0);
940 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
945 if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
948 /* Mark / as private, in case somebody marked it shared */
949 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
952 if (mount_all(arg_directory) < 0)
955 if (copy_devnodes(arg_directory) < 0)
958 if (setup_dev_console(arg_directory, console) < 0)
961 if (setup_kmsg(arg_directory, kmsg_socket_pair[1]) < 0)
964 close_nointr_nofail(kmsg_socket_pair[1]);
966 if (setup_timezone(arg_directory) < 0)
969 if (chdir(arg_directory) < 0) {
970 log_error("chdir(%s) failed: %m", arg_directory);
974 if (open_terminal("dev/console", O_RDWR) != STDIN_FILENO ||
975 dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
976 dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
979 if (mount(arg_directory, "/", "bind", MS_BIND, NULL) < 0) {
980 log_error("mount(MS_MOVE) failed: %m");
984 if (chroot(".") < 0) {
985 log_error("chroot() failed: %m");
989 if (chdir("/") < 0) {
990 log_error("chdir() failed: %m");
998 if (drop_capabilities() < 0)
1003 if (get_user_creds((const char**)&arg_user, &uid, &gid, &home) < 0) {
1004 log_error("get_user_creds() failed: %m");
1008 if (mkdir_parents(home, 0775) < 0) {
1009 log_error("mkdir_parents() failed: %m");
1013 if (safe_mkdir(home, 0775, uid, gid) < 0) {
1014 log_error("safe_mkdir() failed: %m");
1018 if (initgroups((const char*)arg_user, gid) < 0) {
1019 log_error("initgroups() failed: %m");
1023 if (setresgid(gid, gid, gid) < 0) {
1024 log_error("setregid() failed: %m");
1028 if (setresuid(uid, uid, uid) < 0) {
1029 log_error("setreuid() failed: %m");
1034 if ((asprintf((char**)(envp + 3), "HOME=%s", home ? home: "/root") < 0) ||
1035 (asprintf((char**)(envp + 4), "USER=%s", arg_user ? arg_user : "root") < 0) ||
1036 (asprintf((char**)(envp + 5), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) {
1037 log_error("Out of memory");
1042 if (asprintf((char**)(envp + 6), "container_uuid=%s", arg_uuid) < 0) {
1043 log_error("Out of memory");
1054 /* Automatically search for the init system */
1056 l = 1 + argc - optind;
1057 a = newa(char*, l + 1);
1058 memcpy(a + 1, argv + optind, l * sizeof(char*));
1060 a[0] = (char*) "/usr/lib/systemd/systemd";
1061 execve(a[0], a, (char**) envp);
1063 a[0] = (char*) "/lib/systemd/systemd";
1064 execve(a[0], a, (char**) envp);
1066 a[0] = (char*) "/sbin/init";
1067 execve(a[0], a, (char**) envp);
1068 } else if (argc > optind)
1069 execvpe(argv[optind], argv + optind, (char**) envp);
1071 chdir(home ? home : "/root");
1072 execle("/bin/bash", "-bash", NULL, (char**) envp);
1075 log_error("execv() failed: %m");
1078 _exit(EXIT_FAILURE);
1081 if (process_pty(master, &mask) < 0)
1084 if (saved_attr_valid) {
1085 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
1086 saved_attr_valid = false;
1089 r = wait_for_terminate_and_warn(argc > optind ? argv[optind] : "bash", pid);
1095 if (saved_attr_valid)
1096 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
1099 close_nointr_nofail(master);
1101 close_pipe(kmsg_socket_pair);
1104 cg_attach(SYSTEMD_CGROUP_CONTROLLER, oldcg, 0);
1107 cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
1109 free(arg_directory);
1110 strv_free(arg_controllers);