]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-container.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-container.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7893c6b
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
a7893c6b 21#include <fcntl.h>
cf0fbc49 22#include <unistd.h>
a7893c6b 23
3ffd4af2 24#include "bus-container.h"
a7893c6b
LP
25#include "bus-internal.h"
26#include "bus-socket.h"
3ffd4af2
LP
27#include "fd-util.h"
28#include "process-util.h"
29#include "util.h"
a7893c6b 30
bc9fd78c 31int bus_container_connect_socket(sd_bus *b) {
2b7d6d33 32 _cleanup_close_pair_ int pair[2] = { -1, -1 };
671c3419 33 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
ee502e0c 34 pid_t child;
bc9fd78c 35 siginfo_t si;
2b7d6d33
LP
36 int r, error_buf = 0;
37 ssize_t n;
a7893c6b
LP
38
39 assert(b);
40 assert(b->input_fd < 0);
41 assert(b->output_fd < 0);
ee502e0c 42 assert(b->nspid > 0 || b->machine);
a7893c6b 43
ee502e0c
LP
44 if (b->nspid <= 0) {
45 r = container_get_leader(b->machine, &b->nspid);
46 if (r < 0)
47 return r;
48 }
a7893c6b 49
671c3419 50 r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
a7893c6b
LP
51 if (r < 0)
52 return r;
a7893c6b
LP
53
54 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
55 if (b->input_fd < 0)
56 return -errno;
57
58 b->output_fd = b->input_fd;
59
8f04d2eb 60 bus_socket_setup(b);
a7893c6b 61
2b7d6d33
LP
62 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
63 return -errno;
64
a7893c6b
LP
65 child = fork();
66 if (child < 0)
67 return -errno;
68
69 if (child == 0) {
5d6cf65f 70 pid_t grandchild;
a7893c6b 71
2b7d6d33
LP
72 pair[0] = safe_close(pair[0]);
73
671c3419 74 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
bc9fd78c 75 if (r < 0)
2b7d6d33 76 _exit(EXIT_FAILURE);
a7893c6b 77
5d6cf65f
LP
78 /* We just changed PID namespace, however it will only
79 * take effect on the children we now fork. Hence,
80 * let's fork another time, and connect from this
81 * grandchild, so that SO_PEERCRED of our connection
82 * comes from a process from within the container, and
83 * not outside of it */
a7893c6b 84
5d6cf65f
LP
85 grandchild = fork();
86 if (grandchild < 0)
2b7d6d33 87 _exit(EXIT_FAILURE);
5d6cf65f
LP
88
89 if (grandchild == 0) {
90
91 r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
92 if (r < 0) {
2b7d6d33
LP
93 /* Try to send error up */
94 error_buf = errno;
95 (void) write(pair[1], &error_buf, sizeof(error_buf));
96 _exit(EXIT_FAILURE);
5d6cf65f
LP
97 }
98
99 _exit(EXIT_SUCCESS);
a7893c6b
LP
100 }
101
5d6cf65f
LP
102 r = wait_for_terminate(grandchild, &si);
103 if (r < 0)
2b7d6d33 104 _exit(EXIT_FAILURE);
5d6cf65f
LP
105
106 if (si.si_code != CLD_EXITED)
2b7d6d33 107 _exit(EXIT_FAILURE);
5d6cf65f
LP
108
109 _exit(si.si_status);
a7893c6b
LP
110 }
111
2b7d6d33
LP
112 pair[1] = safe_close(pair[1]);
113
a7893c6b
LP
114 r = wait_for_terminate(child, &si);
115 if (r < 0)
116 return r;
117
2b7d6d33
LP
118 n = read(pair[0], &error_buf, sizeof(error_buf));
119 if (n < 0)
120 return -errno;
121
122 if (n > 0) {
123 if (n != sizeof(error_buf))
124 return -EIO;
125
126 if (error_buf < 0)
127 return -EIO;
128
129 if (error_buf == EINPROGRESS)
130 return 1;
131
132 if (error_buf > 0)
133 return -error_buf;
134 }
135
a7893c6b
LP
136 if (si.si_code != CLD_EXITED)
137 return -EIO;
138
bc9fd78c 139 if (si.si_status != EXIT_SUCCESS)
a7893c6b
LP
140 return -EIO;
141
142 return bus_socket_start_auth(b);
143}