]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/bus-proxyd/bus-proxyd.c
selinux: drop mac_selinux_unit_access_check_strv()
[thirdparty/systemd.git] / src / bus-proxyd / bus-proxyd.c
CommitLineData
a8f11321
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
dc780ecf
KS
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
a8a1a43f 9 Copyright 2015 David Herrmann
a8f11321
LP
10
11 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
12 under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 2.1 of the License, or
a8f11321
LP
14 (at your option) any later version.
15
16 systemd is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 19 Lesser General Public License for more details.
a8f11321 20
5430f7f2 21 You should have received a copy of the GNU Lesser General Public License
a8f11321
LP
22 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23***/
24
25#include <sys/socket.h>
a8f11321
LP
26#include <unistd.h>
27#include <string.h>
28#include <errno.h>
d3394ff4 29#include <sys/prctl.h>
a8f11321 30#include <stddef.h>
71008e18 31#include <getopt.h>
a8a1a43f 32#include <pthread.h>
a8f11321
LP
33
34#include "log.h"
35#include "util.h"
d51539b1 36#include "sd-daemon.h"
d51539b1 37#include "bus-internal.h"
71008e18 38#include "build.h"
0721804f 39#include "strv.h"
ab9001a1 40#include "def.h"
6a010ac9 41#include "capability.h"
3c70e3bb 42#include "bus-xml-policy.h"
c0395aeb 43#include "proxy.h"
6482f626 44#include "formats-util.h"
71008e18 45
7f0d207d 46static char *arg_address = NULL;
2e2b3608 47static char **arg_configuration = NULL;
0721804f 48
a8a1a43f
DH
49typedef struct {
50 int fd;
c4bc1a84 51 SharedPolicy *policy;
d340f820 52 uid_t bus_uid;
a8a1a43f
DH
53} ClientContext;
54
55static ClientContext *client_context_free(ClientContext *c) {
56 if (!c)
57 return NULL;
58
95eb099f 59 safe_close(c->fd);
a8a1a43f
DH
60 free(c);
61
62 return NULL;
63}
64
65DEFINE_TRIVIAL_CLEANUP_FUNC(ClientContext*, client_context_free);
66
c4bc1a84 67static int client_context_new(ClientContext **out) {
a8a1a43f
DH
68 _cleanup_(client_context_freep) ClientContext *c = NULL;
69
70 c = new0(ClientContext, 1);
71 if (!c)
c2900521 72 return -ENOMEM;
a8a1a43f 73
c4bc1a84 74 c->fd = -1;
a8a1a43f
DH
75
76 *out = c;
77 c = NULL;
78 return 0;
79}
80
81static void *run_client(void *userdata) {
82 _cleanup_(client_context_freep) ClientContext *c = userdata;
83 _cleanup_(proxy_freep) Proxy *p = NULL;
d3394ff4 84 char comm[16];
a8a1a43f
DH
85 int r;
86
87 r = proxy_new(&p, c->fd, c->fd, arg_address);
88 if (r < 0)
89 goto exit;
90
95eb099f
LP
91 c->fd = -1;
92
d3394ff4
DH
93 /* set comm to "p$PIDu$UID" and suffix with '*' if truncated */
94 r = snprintf(comm, sizeof(comm), "p" PID_FMT "u" UID_FMT, p->local_creds.pid, p->local_creds.uid);
95 if (r >= (ssize_t)sizeof(comm))
96 comm[sizeof(comm) - 2] = '*';
97 (void) prctl(PR_SET_NAME, comm);
98
c4bc1a84 99 r = proxy_set_policy(p, c->policy, arg_configuration);
a8a1a43f
DH
100 if (r < 0)
101 goto exit;
102
d340f820 103 r = proxy_hello_policy(p, c->bus_uid);
a8a1a43f
DH
104 if (r < 0)
105 goto exit;
106
107 r = proxy_run(p);
108
109exit:
110 return NULL;
111}
112
d340f820 113static int loop_clients(int accept_fd, uid_t bus_uid) {
c4bc1a84 114 _cleanup_(shared_policy_freep) SharedPolicy *sp = NULL;
a8a1a43f
DH
115 pthread_attr_t attr;
116 int r;
117
118 r = pthread_attr_init(&attr);
119 if (r < 0) {
5569b33a 120 return log_error_errno(errno, "Cannot initialize pthread attributes: %m");
a8a1a43f
DH
121 }
122
123 r = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
124 if (r < 0) {
125 r = log_error_errno(errno, "Cannot mark pthread attributes as detached: %m");
5569b33a 126 goto finish;
a8a1a43f
DH
127 }
128
c4bc1a84
DH
129 r = shared_policy_new(&sp);
130 if (r < 0)
5569b33a 131 goto finish;
c4bc1a84 132
a8a1a43f
DH
133 for (;;) {
134 ClientContext *c;
135 pthread_t tid;
136 int fd;
137
138 fd = accept4(accept_fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
139 if (fd < 0) {
140 if (errno == EAGAIN || errno == EINTR)
141 continue;
142
143 r = log_error_errno(errno, "accept4() failed: %m");
5569b33a 144 goto finish;
a8a1a43f
DH
145 }
146
c4bc1a84 147 r = client_context_new(&c);
a8a1a43f
DH
148 if (r < 0) {
149 log_oom();
150 close(fd);
151 continue;
152 }
153
c4bc1a84
DH
154 c->fd = fd;
155 c->policy = sp;
d340f820 156 c->bus_uid = bus_uid;
c4bc1a84 157
a8a1a43f
DH
158 r = pthread_create(&tid, &attr, run_client, c);
159 if (r < 0) {
160 log_error("Cannot spawn thread: %m");
161 client_context_free(c);
162 continue;
163 }
164 }
165
5569b33a 166finish:
a8a1a43f 167 pthread_attr_destroy(&attr);
a8a1a43f
DH
168 return r;
169}
170
71008e18
DM
171static int help(void) {
172
173 printf("%s [OPTIONS...]\n\n"
a8a1a43f 174 "DBus proxy server.\n\n"
2e2b3608
LP
175 " -h --help Show this help\n"
176 " --version Show package version\n"
2e2b3608 177 " --configuration=PATH Configuration file or directory\n"
7f0d207d 178 " --machine=MACHINE Connect to specified machine\n"
2e2b3608 179 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
d4d00020
KS
180 " (default: %s)\n",
181 program_invocation_short_name,
182 is_kdbus_available() ? KERNEL_SYSTEM_BUS_ADDRESS : UNIX_SYSTEM_BUS_ADDRESS);
71008e18
DM
183
184 return 0;
185}
186
187static int parse_argv(int argc, char *argv[]) {
188
189 enum {
190 ARG_VERSION = 0x100,
ba768916 191 ARG_ADDRESS,
2e2b3608 192 ARG_CONFIGURATION,
7f0d207d 193 ARG_MACHINE,
71008e18
DM
194 };
195
196 static const struct option options[] = {
6a010ac9
LP
197 { "help", no_argument, NULL, 'h' },
198 { "version", no_argument, NULL, ARG_VERSION },
199 { "address", required_argument, NULL, ARG_ADDRESS },
2e2b3608 200 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
7f0d207d
LP
201 { "machine", required_argument, NULL, ARG_MACHINE },
202 {},
71008e18
DM
203 };
204
2e2b3608 205 int c, r;
71008e18
DM
206
207 assert(argc >= 0);
208 assert(argv);
209
601185b4 210 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
71008e18
DM
211
212 switch (c) {
213
214 case 'h':
215 help();
216 return 0;
217
218 case ARG_VERSION:
219 puts(PACKAGE_STRING);
220 puts(SYSTEMD_FEATURES);
221 return 0;
222
5569b33a
LP
223 case ARG_ADDRESS:
224 r = free_and_strdup(&arg_address, optarg);
225 if (r < 0)
7f0d207d 226 return log_oom();
ba768916
LP
227 break;
228
2e2b3608
LP
229 case ARG_CONFIGURATION:
230 r = strv_extend(&arg_configuration, optarg);
231 if (r < 0)
232 return log_oom();
233 break;
234
7f0d207d
LP
235 case ARG_MACHINE: {
236 _cleanup_free_ char *e = NULL;
237 char *a;
238
239 e = bus_address_escape(optarg);
240 if (!e)
241 return log_oom();
242
146d4773 243 a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
7f0d207d
LP
244 if (!a)
245 return log_oom();
246
247 free(arg_address);
248 arg_address = a;
249
250 break;
251 }
252
71008e18
DM
253 case '?':
254 return -EINVAL;
255
71008e18 256 default:
ba768916 257 assert_not_reached("Unhandled option");
71008e18 258 }
71008e18 259
a8a1a43f 260 if (argc > optind) {
0721804f
LP
261 log_error("Too many arguments");
262 return -EINVAL;
263 }
264
7f0d207d 265 if (!arg_address) {
d4d00020 266 arg_address = strdup(is_kdbus_available() ? KERNEL_SYSTEM_BUS_ADDRESS : UNIX_SYSTEM_BUS_ADDRESS);
7f0d207d
LP
267 if (!arg_address)
268 return log_oom();
269 }
270
71008e18
DM
271 return 1;
272}
a8f11321
LP
273
274int main(int argc, char *argv[]) {
a8a1a43f 275 int r, accept_fd;
d340f820 276 uid_t uid, bus_uid;
a80a3a75 277 gid_t gid;
a8f11321 278
4cfa2c99 279 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
a8f11321
LP
280 log_parse_environment();
281 log_open();
282
d340f820
DH
283 bus_uid = getuid();
284
a80a3a75 285 if (geteuid() == 0) {
5569b33a
LP
286 const char *user = "systemd-bus-proxy";
287
a80a3a75
DH
288 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
289 if (r < 0) {
290 log_error_errno(r, "Cannot resolve user name %s: %m", user);
291 goto finish;
292 }
293
294 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
295 if (r < 0) {
296 log_error_errno(r, "Cannot drop privileges: %m");
297 goto finish;
298 }
299 }
300
71008e18
DM
301 r = parse_argv(argc, argv);
302 if (r <= 0)
303 goto finish;
304
305 r = sd_listen_fds(0);
a8a1a43f 306 if (r != 1) {
9f6445e3 307 log_error("Illegal number of file descriptors passed");
71008e18
DM
308 goto finish;
309 }
310
a8a1a43f 311 accept_fd = SD_LISTEN_FDS_START;
5569b33a 312
a8a1a43f
DH
313 r = fd_nonblock(accept_fd, false);
314 if (r < 0) {
315 log_error_errno(r, "Cannot mark accept-fd non-blocking: %m");
ac4eaf6d 316 goto finish;
a8a1a43f 317 }
ac4eaf6d 318
d340f820 319 r = loop_clients(accept_fd, bus_uid);
a8f11321 320
a8f11321 321finish:
af4ec430
LP
322 sd_notify(false,
323 "STOPPING=1\n"
324 "STATUS=Shutting down.");
325
2e2b3608 326 strv_free(arg_configuration);
7f0d207d 327 free(arg_address);
bcf3295d 328
d51539b1 329 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
a8f11321 330}