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