#include "bus-internal.h"
#include "bus-socket.h"
#include "env-file.h"
+#include "errno-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "hostname-util.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
-#include "pidref.h"
#include "process-util.h"
#include "string-util.h"
return 0;
}
+static int bus_container_connect_namespace(sd_bus *b, int pidnsfd, int mntnsfd, int usernsfd, int rootfd) {
+ _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
+ int r;
+
+ if (pipe2(errno_pipe_fd, O_CLOEXEC) < 0)
+ return log_debug_errno(errno, "Failed to create pipe: %m");
+
+ r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_WAIT,
+ pidnsfd, mntnsfd, /* netns_fd= */ -EBADF, usernsfd, rootfd, /* ret= */ NULL);
+ if (r == -EPROTO) {
+ errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
+
+ int k = read_errno(errno_pipe_fd[0]);
+ if (k < 0 && k != -EIO)
+ return k;
+ }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to create namespace for (sd-buscntr): %m");
+ if (r == 0) {
+ errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
+
+ r = RET_NERRNO(connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size));
+ report_errno_and_exit(errno_pipe_fd[1], r);
+ }
+
+ return 0;
+}
+
int bus_container_connect_socket(sd_bus *b) {
_cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF;
- _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
- _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
- int r, error_buf = 0;
- ssize_t n;
+ int r;
assert(b);
assert(b->input_fd < 0);
bus_socket_setup(b);
- if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
- return log_debug_errno(errno, "Failed to create a socket pair: %m");
-
- r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
- pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
+ r = are_our_namespaces(pidnsfd, mntnsfd, /* netns_fd= */ -EBADF, usernsfd, rootfd);
if (r < 0)
- return log_debug_errno(r, "Failed to create namespace for (sd-buscntr): %m");
- if (r == 0) {
- pair[0] = safe_close(pair[0]);
-
- r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
- if (r < 0) {
- /* Try to send error up */
- error_buf = errno;
- (void) write(pair[1], &error_buf, sizeof(error_buf));
- _exit(EXIT_FAILURE);
- }
-
- _exit(EXIT_SUCCESS);
- }
-
- pair[1] = safe_close(pair[1]);
-
- r = pidref_wait_for_terminate_and_check("(sd-buscntrns)", &child, 0);
+ return log_debug_errno(r, "Failed to check if already in PID "PID_FMT" namespaces: %m", b->nspid);
+ if (r > 0)
+ r = RET_NERRNO(connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size));
+ else
+ r = bus_container_connect_namespace(b, pidnsfd, mntnsfd, usernsfd, rootfd);
+ if (r == -EINPROGRESS)
+ return 1;
if (r < 0)
- return r;
- bool nonzero_exit_status = r != EXIT_SUCCESS;
-
- n = read(pair[0], &error_buf, sizeof(error_buf));
- if (n < 0)
- return log_debug_errno(errno, "Failed to read error status from (sd-buscntr): %m");
-
- if (n > 0) {
- if (n != sizeof(error_buf))
- return log_debug_errno(SYNTHETIC_ERRNO(EIO),
- "Read error status of unexpected length %zd from (sd-buscntr).", n);
-
- if (error_buf < 0)
- return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
- "Got unexpected error status from (sd-buscntr).");
-
- if (error_buf == EINPROGRESS)
- return 1;
-
- if (error_buf > 0)
- return log_debug_errno(error_buf, "(sd-buscntr) failed to connect to D-Bus socket: %m");
- }
-
- if (nonzero_exit_status)
- return -EPROTO;
+ return log_debug_errno(r, "Failed to connect to D-Bus socket in namespaces of PID "PID_FMT": %m", b->nspid);
return bus_socket_start_auth(b);
}