diff options
-rw-r--r-- | src/basic/terminal-util.c | 19 | ||||
-rw-r--r-- | src/basic/terminal-util.h | 2 | ||||
-rw-r--r-- | src/basic/util.c | 3 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-container.c | 46 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/sd-bus.c | 23 | ||||
-rw-r--r-- | src/machine/machine-dbus.c | 13 | ||||
-rw-r--r-- | src/run/run.c | 6 |
7 files changed, 79 insertions, 33 deletions
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index cf55263bbf..c5ef5ab0d1 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1074,3 +1074,22 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { return 0; } + +int ptsname_namespace(int pty, char **ret) { + int no = -1, r; + + /* Like ptsname(), but doesn't assume that the path is + * accessible in the local namespace. */ + + r = ioctl(pty, TIOCGPTN, &no); + if (r < 0) + return -errno; + + if (no < 0) + return -EIO; + + if (asprintf(ret, "/dev/pts/%i", no) < 0) + return -ENOMEM; + + return 0; +} diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 188714f228..b9a3809a6c 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -107,3 +107,5 @@ int get_ctty(pid_t, dev_t *_devnr, char **r); int getttyname_malloc(int fd, char **r); int getttyname_harder(int fd, char **r); + +int ptsname_namespace(int pty, char **ret); diff --git a/src/basic/util.c b/src/basic/util.c index 737f2a221c..f01f5f237b 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -6095,6 +6095,9 @@ int openpt_in_namespace(pid_t pid, int flags) { if (master < 0) _exit(EXIT_FAILURE); + if (unlockpt(master) < 0) + _exit(EXIT_FAILURE); + cmsg = CMSG_FIRSTHDR(&mh); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c index 101e4af18d..56dc086ae2 100644 --- a/src/libsystemd/sd-bus/bus-container.c +++ b/src/libsystemd/sd-bus/bus-container.c @@ -125,15 +125,22 @@ int bus_container_connect_kernel(sd_bus *b) { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; } control = {}; + int error_buf = 0; + struct iovec iov = { + .iov_base = &error_buf, + .iov_len = sizeof(error_buf), + }; struct msghdr mh = { .msg_control = &control, .msg_controllen = sizeof(control), + .msg_iov = &iov, + .msg_iovlen = 1, }; struct cmsghdr *cmsg; pid_t child; siginfo_t si; - int r; - _cleanup_close_ int fd = -1; + int r, fd = -1; + ssize_t n; assert(b); assert(b->input_fd < 0); @@ -178,10 +185,13 @@ int bus_container_connect_kernel(sd_bus *b) { _exit(EXIT_FAILURE); if (grandchild == 0) { - fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC); - if (fd < 0) + if (fd < 0) { + /* Try to send error up */ + error_buf = errno; + (void) write(pair[1], &error_buf, sizeof(error_buf)); _exit(EXIT_FAILURE); + } cmsg = CMSG_FIRSTHDR(&mh); cmsg->cmsg_level = SOL_SOCKET; @@ -213,20 +223,17 @@ int bus_container_connect_kernel(sd_bus *b) { if (r < 0) return r; - if (si.si_code != CLD_EXITED) - return -EIO; - - if (si.si_status != EXIT_SUCCESS) - return -EIO; - - if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0) + n = recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC); + if (n < 0) return -errno; - CMSG_FOREACH(cmsg, &mh) + CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int *fds; unsigned n_fds; + assert(fd < 0); + fds = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); @@ -237,9 +244,18 @@ int bus_container_connect_kernel(sd_bus *b) { fd = fds[0]; } + } + + /* If there's an fd passed, we are good. */ + if (fd >= 0) { + b->input_fd = b->output_fd = fd; + return bus_kernel_take_fd(b); + } - b->input_fd = b->output_fd = fd; - fd = -1; + /* If there's an error passed, use it */ + if (n == sizeof(error_buf) && error_buf > 0) + return -error_buf; - return bus_kernel_take_fd(b); + /* Otherwise, we have no clue */ + return -EIO; } diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 5285278d92..4ed508427e 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1025,19 +1025,30 @@ static int bus_start_address(sd_bus *b) { if (b->exec_path) r = bus_socket_exec(b); + else if ((b->nspid > 0 || b->machine) && b->kernel) { r = bus_container_connect_kernel(b); if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT)) container_kdbus_available = true; - } else if (!container_kdbus_available && (b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) - r = bus_container_connect_socket(b); - else if (b->kernel) { + + } else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) { + if (!container_kdbus_available) + r = bus_container_connect_socket(b); + else + skipped = true; + + } else if (b->kernel) { r = bus_kernel_connect(b); if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT)) kdbus_available = true; - } else if (!kdbus_available && b->sockaddr.sa.sa_family != AF_UNSPEC) - r = bus_socket_connect(b); - else + + } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) { + if (!kdbus_available) + r = bus_socket_connect(b); + else + skipped = true; + + } else skipped = true; if (!skipped) { diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index af2b8eff06..a63b9785af 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -45,6 +45,7 @@ #include "formats-util.h" #include "process-util.h" #include "env-util.h" +#include "terminal-util.h" static int property_get_id( sd_bus *bus, @@ -500,7 +501,7 @@ int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_ if (master < 0) return master; - r = ptsname_malloc(master, &pty_name); + r = ptsname_namespace(master, &pty_name); if (r < 0) return r; @@ -589,7 +590,7 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu if (master < 0) return master; - r = ptsname_malloc(master, &pty_name); + r = ptsname_namespace(master, &pty_name); if (r < 0) return r; @@ -597,9 +598,6 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu if (!p) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name); - if (unlockpt(master) < 0) - return -errno; - r = container_bus_new(m, &allocated_bus); if (r < 0) return r; @@ -690,7 +688,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu if (master < 0) return master; - r = ptsname_malloc(master, &pty_name); + r = ptsname_namespace(master, &pty_name); if (r < 0) return r; @@ -701,9 +699,6 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu utmp_id = path_startswith(pty_name, "/dev/"); assert(utmp_id); - if (unlockpt(master) < 0) - return -errno; - r = container_bus_new(m, &allocated_bus); if (r < 0) return r; diff --git a/src/run/run.c b/src/run/run.c index a69560208c..657c6fcaf1 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -702,6 +702,9 @@ static int start_transient_service( if (r < 0) return log_error_errno(r, "Failed to determine tty name: %m"); + if (unlockpt(master) < 0) + return log_error_errno(errno, "Failed to unlock tty: %m"); + } else if (arg_transport == BUS_TRANSPORT_MACHINE) { _cleanup_bus_unref_ sd_bus *system_bus = NULL; const char *s; @@ -738,9 +741,6 @@ static int start_transient_service( return log_oom(); } else assert_not_reached("Can't allocate tty via ssh"); - - if (unlockpt(master) < 0) - return log_error_errno(errno, "Failed to unlock tty: %m"); } if (!arg_no_block) { |