1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <fcntl.h>
4 #include <unistd.h>
5 
6 #include "bus-container.h"
7 #include "bus-internal.h"
8 #include "bus-socket.h"
9 #include "fd-util.h"
10 #include "namespace-util.h"
11 #include "process-util.h"
12 #include "string-util.h"
13 #include "util.h"
14 
bus_container_connect_socket(sd_bus * b)15 int bus_container_connect_socket(sd_bus *b) {
16         _cleanup_close_pair_ int pair[2] = { -1, -1 };
17         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
18         int r, error_buf = 0;
19         pid_t child;
20         ssize_t n;
21 
22         assert(b);
23         assert(b->input_fd < 0);
24         assert(b->output_fd < 0);
25         assert(b->nspid > 0 || b->machine);
26 
27         if (b->nspid <= 0) {
28                 log_debug("sd-bus: connecting bus%s%s to machine %s...",
29                           b->description ? " " : "", strempty(b->description), b->machine);
30 
31                 r = container_get_leader(b->machine, &b->nspid);
32                 if (r < 0)
33                         return r;
34         } else
35                 log_debug("sd-bus: connecting bus%s%s to namespace of PID "PID_FMT"...",
36                           b->description ? " " : "", strempty(b->description), b->nspid);
37 
38         r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
39         if (r < 0)
40                 return log_debug_errno(r, "Failed to open namespace of PID "PID_FMT": %m", b->nspid);
41 
42         b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
43         if (b->input_fd < 0)
44                 return log_debug_errno(errno, "Failed to create a socket: %m");
45 
46         b->input_fd = fd_move_above_stdio(b->input_fd);
47 
48         b->output_fd = b->input_fd;
49 
50         bus_socket_setup(b);
51 
52         if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
53                 return log_debug_errno(errno, "Failed to create a socket pair: %m");
54 
55         r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
56                            pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
57         if (r < 0)
58                 return log_debug_errno(r, "Failed to create namespace for (sd-buscntr): %m");
59         if (r == 0) {
60                 pair[0] = safe_close(pair[0]);
61 
62                 r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
63                 if (r < 0) {
64                         /* Try to send error up */
65                         error_buf = errno;
66                         (void) write(pair[1], &error_buf, sizeof(error_buf));
67                         _exit(EXIT_FAILURE);
68                 }
69 
70                 _exit(EXIT_SUCCESS);
71         }
72 
73         pair[1] = safe_close(pair[1]);
74 
75         r = wait_for_terminate_and_check("(sd-buscntrns)", child, 0);
76         if (r < 0)
77                 return r;
78         bool nonzero_exit_status = r != EXIT_SUCCESS;
79 
80         n = read(pair[0], &error_buf, sizeof(error_buf));
81         if (n < 0)
82                 return log_debug_errno(errno, "Failed to read error status from (sd-buscntr): %m");
83 
84         if (n > 0) {
85                 if (n != sizeof(error_buf))
86                         return log_debug_errno(SYNTHETIC_ERRNO(EIO),
87                                                "Read error status of unexpected length %zd from (sd-buscntr): %m", n);
88 
89                 if (error_buf < 0)
90                         return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
91                                                "Got unexpected error status from (sd-buscntr): %m");
92 
93                 if (error_buf == EINPROGRESS)
94                         return 1;
95 
96                 if (error_buf > 0)
97                         return log_debug_errno(error_buf, "(sd-buscntr) failed to connect to D-Bus socket: %m");
98         }
99 
100         if (nonzero_exit_status)
101                 return -EPROTO;
102 
103         return bus_socket_start_auth(b);
104 }
105