summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-09-01 20:36:52 +0200
committerLennart Poettering <lennart@poettering.net>2015-09-01 20:40:24 +0200
commit80b0d3e3116f85cab8b19caf1cfa9d56be190a2e (patch)
tree663500190ce47ac1d179b942e29895954178c451
parenta07c35c3e65c16264cb25206c2d564afdbae8a28 (diff)
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.
-rw-r--r--src/libsystemd/sd-bus/bus-container.c46
1 files changed, 31 insertions, 15 deletions
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;
}