From 80b0d3e3116f85cab8b19caf1cfa9d56be190a2e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Sep 2015 20:36:52 +0200 Subject: sd-bus: when connecting to a kdbus container bus pass error up We rely on the correct error used when opening the kdbus device node, hence let's make sure we pass it up from the namespaced child process to the process which actually wants to connect. --- src/libsystemd/sd-bus/bus-container.c | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'src/libsystemd') 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; } -- cgit v1.2.3-54-g00ecf From 751090cc8ae09787402d60b7080d479b3afe3b13 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Sep 2015 20:38:37 +0200 Subject: sd-bus: when connecting to a container, don't fall back to host bus We should never connect to the host bus as fallback if connecting to a container failed via one method. Otherwise connecting to a dbus1 container will always result in a connection to the host. --- src/libsystemd/sd-bus/sd-bus.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src/libsystemd') 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) { -- cgit v1.2.3-54-g00ecf