]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/proxy.c
bus-proxy: add new dbus policy search paths from /usr
[thirdparty/systemd.git] / src / bus-proxyd / proxy.c
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
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
9 Copyright 2014 David Herrmann
10
11 systemd is free software; you can redistribute it and/or modify it
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
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
19 Lesser General Public License for more details.
20
21 You should have received a copy of the GNU Lesser General Public License
22 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 ***/
24
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <poll.h>
30
31 #include "log.h"
32 #include "util.h"
33 #include "sd-daemon.h"
34 #include "sd-bus.h"
35 #include "bus-internal.h"
36 #include "bus-message.h"
37 #include "bus-util.h"
38 #include "strv.h"
39 #include "bus-control.h"
40 #include "set.h"
41 #include "bus-xml-policy.h"
42 #include "driver.h"
43 #include "proxy.h"
44 #include "synthesize.h"
45 #include "formats-util.h"
46
47 static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
48 _cleanup_bus_close_unref_ sd_bus *b = NULL;
49 int r;
50
51 r = sd_bus_new(&b);
52 if (r < 0)
53 return log_error_errno(r, "Failed to allocate bus: %m");
54
55 r = sd_bus_set_description(b, "sd-proxy");
56 if (r < 0)
57 return log_error_errno(r, "Failed to set bus name: %m");
58
59 r = sd_bus_set_address(b, destination);
60 if (r < 0)
61 return log_error_errno(r, "Failed to set address to connect to: %m");
62
63 r = sd_bus_negotiate_fds(b, negotiate_fds);
64 if (r < 0)
65 return log_error_errno(r, "Failed to set FD negotiation: %m");
66
67 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
68 if (r < 0)
69 return log_error_errno(r, "Failed to set credential negotiation: %m");
70
71 if (p->local_creds.pid > 0) {
72 b->fake_pids.pid = p->local_creds.pid;
73 b->fake_pids_valid = true;
74
75 b->fake_creds.uid = UID_INVALID;
76 b->fake_creds.euid = p->local_creds.uid;
77 b->fake_creds.suid = UID_INVALID;
78 b->fake_creds.fsuid = UID_INVALID;
79 b->fake_creds.gid = GID_INVALID;
80 b->fake_creds.egid = p->local_creds.gid;
81 b->fake_creds.sgid = GID_INVALID;
82 b->fake_creds.fsgid = GID_INVALID;
83 b->fake_creds_valid = true;
84 }
85
86 if (local_sec) {
87 b->fake_label = strdup(local_sec);
88 if (!b->fake_label)
89 return log_oom();
90 }
91
92 b->manual_peer_interface = true;
93
94 r = sd_bus_start(b);
95 if (r < 0)
96 return log_error_errno(r, "Failed to start bus client: %m");
97
98 p->destination_bus = b;
99 b = NULL;
100 return 0;
101 }
102
103 static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fds) {
104 _cleanup_bus_close_unref_ sd_bus *b = NULL;
105 sd_id128_t server_id;
106 int r;
107
108 r = sd_bus_new(&b);
109 if (r < 0)
110 return log_error_errno(r, "Failed to allocate bus: %m");
111
112 r = sd_bus_set_fd(b, in_fd, out_fd);
113 if (r < 0)
114 return log_error_errno(r, "Failed to set fds: %m");
115
116 r = sd_bus_get_bus_id(p->destination_bus, &server_id);
117 if (r < 0)
118 return log_error_errno(r, "Failed to get server ID: %m");
119
120 r = sd_bus_set_server(b, 1, server_id);
121 if (r < 0)
122 return log_error_errno(r, "Failed to set server mode: %m");
123
124 r = sd_bus_negotiate_fds(b, negotiate_fds);
125 if (r < 0)
126 return log_error_errno(r, "Failed to set FD negotiation: %m");
127
128 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
129 if (r < 0)
130 return log_error_errno(r, "Failed to set credential negotiation: %m");
131
132 r = sd_bus_set_anonymous(b, true);
133 if (r < 0)
134 return log_error_errno(r, "Failed to set anonymous authentication: %m");
135
136 b->manual_peer_interface = true;
137
138 r = sd_bus_start(b);
139 if (r < 0)
140 return log_error_errno(r, "Failed to start bus client: %m");
141
142 p->local_bus = b;
143 b = NULL;
144 return 0;
145 }
146
147 static int proxy_prepare_matches(Proxy *p) {
148 _cleanup_free_ char *match = NULL;
149 const char *unique;
150 int r;
151
152 if (!p->destination_bus->is_kernel)
153 return 0;
154
155 r = sd_bus_get_unique_name(p->destination_bus, &unique);
156 if (r < 0)
157 return log_error_errno(r, "Failed to get unique name: %m");
158
159 match = strjoin("type='signal',"
160 "sender='org.freedesktop.DBus',"
161 "path='/org/freedesktop/DBus',"
162 "interface='org.freedesktop.DBus',"
163 "member='NameOwnerChanged',"
164 "arg1='",
165 unique,
166 "'",
167 NULL);
168 if (!match)
169 return log_oom();
170
171 r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL);
172 if (r < 0)
173 return log_error_errno(r, "Failed to add match for NameLost: %m");
174
175 free(match);
176 match = strjoin("type='signal',"
177 "sender='org.freedesktop.DBus',"
178 "path='/org/freedesktop/DBus',"
179 "interface='org.freedesktop.DBus',"
180 "member='NameOwnerChanged',"
181 "arg2='",
182 unique,
183 "'",
184 NULL);
185 if (!match)
186 return log_oom();
187
188 r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL);
189 if (r < 0)
190 return log_error_errno(r, "Failed to add match for NameAcquired: %m");
191
192 return 0;
193 }
194
195 int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
196 _cleanup_(proxy_freep) Proxy *p = NULL;
197 _cleanup_free_ char *local_sec = NULL;
198 bool is_unix;
199 int r;
200
201 p = new0(Proxy, 1);
202 if (!p)
203 return log_oom();
204
205 p->local_in = in_fd;
206 p->local_out = out_fd;
207
208 p->owned_names = set_new(&string_hash_ops);
209 if (!p->owned_names)
210 return log_oom();
211
212 is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
213 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
214
215 if (is_unix) {
216 (void) getpeercred(in_fd, &p->local_creds);
217 (void) getpeersec(in_fd, &local_sec);
218 }
219
220 r = proxy_create_destination(p, destination, local_sec, is_unix);
221 if (r < 0)
222 return r;
223
224 r = proxy_create_local(p, in_fd, out_fd, is_unix);
225 if (r < 0)
226 return r;
227
228 r = proxy_prepare_matches(p);
229 if (r < 0)
230 return r;
231
232 *out = p;
233 p = NULL;
234 return 0;
235 }
236
237 Proxy *proxy_free(Proxy *p) {
238 if (!p)
239 return NULL;
240
241 sd_bus_close_unrefp(&p->local_bus);
242 sd_bus_close_unrefp(&p->destination_bus);
243 set_free_free(p->owned_names);
244 free(p);
245
246 return NULL;
247 }
248
249 int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
250 _cleanup_strv_free_ char **strv = NULL;
251 Policy *policy;
252 int r;
253
254 assert(p);
255 assert(sp);
256
257 /* no need to load legacy policy if destination is not kdbus */
258 if (!p->destination_bus->is_kernel)
259 return 0;
260
261 p->policy = sp;
262
263 policy = shared_policy_acquire(sp);
264 if (policy) {
265 /* policy already pre-loaded */
266 shared_policy_release(sp, policy);
267 return 0;
268 }
269
270 if (!configuration) {
271 const char *scope;
272
273 r = sd_bus_get_scope(p->destination_bus, &scope);
274 if (r < 0)
275 return log_error_errno(r, "Couldn't determine bus scope: %m");
276
277 if (streq(scope, "system"))
278 strv = strv_new("/usr/share/dbus-1/system.conf",
279 "/etc/dbus-1/system.conf",
280 "/usr/share/dbus-1/system.d/",
281 "/etc/dbus-1/system.d/",
282 "/etc/dbus-1/system-local.conf",
283 NULL);
284 else if (streq(scope, "user"))
285 strv = strv_new("/usr/share/dbus-1/session.conf",
286 "/etc/dbus-1/session.conf",
287 "/usr/share/dbus-1/session.d/",
288 "/etc/dbus-1/session.d/",
289 "/etc/dbus-1/session-local.conf",
290 NULL);
291 else
292 return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
293
294 if (!strv)
295 return log_oom();
296
297 configuration = strv;
298 }
299
300 return shared_policy_preload(sp, configuration);
301 }
302
303 int proxy_hello_policy(Proxy *p, uid_t original_uid) {
304 Policy *policy;
305 int r = 0;
306
307 assert(p);
308
309 if (!p->policy)
310 return 0;
311
312 policy = shared_policy_acquire(p->policy);
313
314 if (p->local_creds.uid == original_uid)
315 log_debug("Permitting access, since bus owner matches bus client.");
316 else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
317 log_debug("Permitting access due to XML policy.");
318 else
319 r = log_error_errno(EPERM, "Policy denied connection.");
320
321 shared_policy_release(p->policy, policy);
322
323 return r;
324 }
325
326 static int proxy_wait(Proxy *p) {
327 uint64_t timeout_destination, timeout_local, t;
328 int events_destination, events_local, fd;
329 struct timespec _ts, *ts;
330 struct pollfd *pollfd;
331 int r;
332
333 assert(p);
334
335 fd = sd_bus_get_fd(p->destination_bus);
336 if (fd < 0)
337 return log_error_errno(fd, "Failed to get fd: %m");
338
339 events_destination = sd_bus_get_events(p->destination_bus);
340 if (events_destination < 0)
341 return log_error_errno(events_destination, "Failed to get events mask: %m");
342
343 r = sd_bus_get_timeout(p->destination_bus, &timeout_destination);
344 if (r < 0)
345 return log_error_errno(r, "Failed to get timeout: %m");
346
347 events_local = sd_bus_get_events(p->local_bus);
348 if (events_local < 0)
349 return log_error_errno(events_local, "Failed to get events mask: %m");
350
351 r = sd_bus_get_timeout(p->local_bus, &timeout_local);
352 if (r < 0)
353 return log_error_errno(r, "Failed to get timeout: %m");
354
355 t = timeout_destination;
356 if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination))
357 t = timeout_local;
358
359 if (t == (uint64_t) -1)
360 ts = NULL;
361 else {
362 usec_t nw;
363
364 nw = now(CLOCK_MONOTONIC);
365 if (t > nw)
366 t -= nw;
367 else
368 t = 0;
369
370 ts = timespec_store(&_ts, t);
371 }
372
373 pollfd = (struct pollfd[3]) {
374 { .fd = fd, .events = events_destination, },
375 { .fd = p->local_in, .events = events_local & POLLIN, },
376 { .fd = p->local_out, .events = events_local & POLLOUT, },
377 };
378
379 r = ppoll(pollfd, 3, ts, NULL);
380 if (r < 0)
381 return log_error_errno(errno, "ppoll() failed: %m");
382
383 return 0;
384 }
385
386 static int handle_policy_error(sd_bus_message *m, int r) {
387 if (r == -ESRCH || r == -ENXIO)
388 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
389
390 return r;
391 }
392
393 static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
394 int r;
395
396 assert(from);
397 assert(to);
398 assert(m);
399
400 if (!policy)
401 return 0;
402
403 /*
404 * dbus-1 distinguishes expected and non-expected replies by tracking
405 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
406 * on expected replies, unless explicitly specified. But we dont track
407 * method-calls, thus, we cannot know whether a reply is expected.
408 * Fortunately, the kdbus forbids non-expected replies, so we can safely
409 * ignore any policy on those and let the kernel deal with it.
410 *
411 * TODO: To be correct, we should only ignore policy-tags that are
412 * applied on non-expected replies. However, so far we don't parse those
413 * tags so we let everything pass. I haven't seen a DENY policy tag on
414 * expected-replies, ever, so don't bother..
415 */
416 if (m->reply_cookie > 0)
417 return 0;
418
419 if (from->is_kernel) {
420 uid_t sender_uid = UID_INVALID;
421 gid_t sender_gid = GID_INVALID;
422 char **sender_names = NULL;
423
424 /* Driver messages are always OK */
425 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
426 return 0;
427
428 /* The message came from the kernel, and is sent to our legacy client. */
429 (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
430
431 (void) sd_bus_creds_get_euid(&m->creds, &sender_uid);
432 (void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
433
434 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
435 _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
436
437 /* If the message came from another legacy
438 * client, then the message creds will be
439 * missing, simply because on legacy clients
440 * per-message creds were unknown. In this
441 * case, query the creds of the peer
442 * instead. */
443
444 r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
445 if (r < 0)
446 return handle_policy_error(m, r);
447
448 (void) sd_bus_creds_get_euid(sender_creds, &sender_uid);
449 (void) sd_bus_creds_get_egid(sender_creds, &sender_gid);
450 }
451
452 /* First check whether the sender can send the message to our name */
453 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) &&
454 policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false))
455 return 0;
456
457 /* Return an error back to the caller */
458 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
459 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
460
461 /* Return 1, indicating that the message shall not be processed any further */
462 return 1;
463 }
464
465 if (to->is_kernel) {
466 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
467 uid_t destination_uid = UID_INVALID;
468 gid_t destination_gid = GID_INVALID;
469 const char *destination_unique = NULL;
470 char **destination_names = NULL;
471 char *n;
472
473 /* Driver messages are always OK */
474 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
475 return 0;
476
477 /* The message came from the legacy client, and is sent to kdbus. */
478 if (m->destination) {
479 r = bus_get_name_creds_kdbus(to, m->destination,
480 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
481 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID,
482 true, &destination_creds);
483 if (r < 0)
484 return handle_policy_error(m, r);
485
486 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
487 if (r < 0)
488 return handle_policy_error(m, r);
489
490 (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
491
492 (void) sd_bus_creds_get_euid(destination_creds, &destination_uid);
493 (void) sd_bus_creds_get_egid(destination_creds, &destination_gid);
494 }
495
496 /* First check if we (the sender) can send to this name */
497 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
498 if (n) {
499 /* If we made a receiver decision, then remember which
500 * name's policy we used, and to which unique ID it
501 * mapped when we made the decision. Then, let's pass
502 * this to the kernel when sending the message, so that
503 * it refuses the operation should the name and unique
504 * ID not map to each other anymore. */
505
506 r = free_and_strdup(&m->destination_ptr, n);
507 if (r < 0)
508 return r;
509
510 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
511 if (r < 0)
512 return r;
513 }
514
515 if (sd_bus_message_is_signal(m, NULL, NULL)) {
516 /* If we forward a signal from dbus-1 to kdbus,
517 * we have no idea who the recipient is.
518 * Therefore, we cannot apply any dbus-1
519 * receiver policies that match on receiver
520 * credentials. We know sd-bus always sets
521 * KDBUS_MSG_SIGNAL, so the kernel applies
522 * receiver policies to the message. Therefore,
523 * skip policy checks in this case. */
524 return 0;
525 } else if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) {
526 return 0;
527 }
528 }
529
530 /* Return an error back to the caller */
531 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
532 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
533
534 /* Return 1, indicating that the message shall not be processed any further */
535 return 1;
536 }
537
538 return 0;
539 }
540
541 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
542 Policy *policy;
543 int r;
544
545 assert(sp);
546
547 policy = shared_policy_acquire(sp);
548 r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
549 shared_policy_release(sp, policy);
550
551 return r;
552 }
553
554 static int process_hello(Proxy *p, sd_bus_message *m) {
555 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
556 bool is_hello;
557 int r;
558
559 assert(p);
560 assert(m);
561
562 /* As reaction to hello we need to respond with two messages:
563 * the callback reply and the NameAcquired for the unique
564 * name, since hello is otherwise obsolete on kdbus. */
565
566 is_hello =
567 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
568 streq_ptr(m->destination, "org.freedesktop.DBus");
569
570 if (!is_hello) {
571 if (p->got_hello)
572 return 0;
573
574 return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
575 }
576
577 if (p->got_hello)
578 return log_error_errno(EIO, "Got duplicate hello, aborting.");
579
580 p->got_hello = true;
581
582 if (!p->destination_bus->is_kernel)
583 return 0;
584
585 r = sd_bus_message_new_method_return(m, &n);
586 if (r < 0)
587 return log_error_errno(r, "Failed to generate HELLO reply: %m");
588
589 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
590 if (r < 0)
591 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
592
593 r = bus_message_append_sender(n, "org.freedesktop.DBus");
594 if (r < 0)
595 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
596
597 r = bus_seal_synthetic_message(p->local_bus, n);
598 if (r < 0)
599 return log_error_errno(r, "Failed to seal HELLO reply: %m");
600
601 r = sd_bus_send(p->local_bus, n, NULL);
602 if (r < 0)
603 return log_error_errno(r, "Failed to send HELLO reply: %m");
604
605 n = sd_bus_message_unref(n);
606 r = sd_bus_message_new_signal(
607 p->local_bus,
608 &n,
609 "/org/freedesktop/DBus",
610 "org.freedesktop.DBus",
611 "NameAcquired");
612 if (r < 0)
613 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
614
615 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
616 if (r < 0)
617 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
618
619 r = bus_message_append_sender(n, "org.freedesktop.DBus");
620 if (r < 0)
621 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
622
623 r = bus_seal_synthetic_message(p->local_bus, n);
624 if (r < 0)
625 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
626
627 r = sd_bus_send(p->local_bus, n, NULL);
628 if (r < 0)
629 return log_error_errno(r, "Failed to send NameAcquired message: %m");
630
631 return 1;
632 }
633
634 static int patch_sender(sd_bus *a, sd_bus_message *m) {
635 char **well_known = NULL;
636 sd_bus_creds *c;
637 int r;
638
639 assert(a);
640 assert(m);
641
642 if (!a->is_kernel)
643 return 0;
644
645 /* We will change the sender of messages from the bus driver
646 * so that they originate from the bus driver. This is a
647 * speciality originating from dbus1, where the bus driver did
648 * not have a unique id, but only the well-known name. */
649
650 c = sd_bus_message_get_creds(m);
651 if (!c)
652 return 0;
653
654 r = sd_bus_creds_get_well_known_names(c, &well_known);
655 if (r < 0)
656 return r;
657
658 if (strv_contains(well_known, "org.freedesktop.DBus"))
659 m->sender = "org.freedesktop.DBus";
660
661 return 0;
662 }
663
664 static int proxy_process_destination_to_local(Proxy *p) {
665 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
666 int r;
667
668 assert(p);
669
670 r = sd_bus_process(p->destination_bus, &m);
671 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
672 return r;
673 if (r < 0) {
674 log_error_errno(r, "Failed to process destination bus: %m");
675 return r;
676 }
677 if (r == 0)
678 return 0;
679 if (!m)
680 return 1;
681
682 /* We officially got EOF, let's quit */
683 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
684 return -ECONNRESET;
685
686 r = synthesize_name_acquired(p->destination_bus, p->local_bus, m);
687 if (r == -ECONNRESET || r == -ENOTCONN)
688 return r;
689 if (r < 0)
690 return log_error_errno(r, "Failed to synthesize message: %m");
691
692 patch_sender(p->destination_bus, m);
693
694 if (p->policy) {
695 r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
696 if (r == -ECONNRESET || r == -ENOTCONN)
697 return r;
698 if (r < 0)
699 return log_error_errno(r, "Failed to process policy: %m");
700 if (r > 0)
701 return 1;
702 }
703
704 r = sd_bus_send(p->local_bus, m, NULL);
705 if (r < 0) {
706 if (r == -ECONNRESET || r == -ENOTCONN)
707 return r;
708
709 /* If the peer tries to send a reply and it is
710 * rejected with EPERM by the kernel, we ignore the
711 * error. This catches cases where the original
712 * method-call didn't had EXPECT_REPLY set, but the
713 * proxy-peer still sends a reply. This is allowed in
714 * dbus1, but not in kdbus. We don't want to track
715 * reply-windows in the proxy, so we simply ignore
716 * EPERM for all replies. The only downside is, that
717 * callers are no longer notified if their replies are
718 * dropped. However, this is equivalent to the
719 * caller's timeout to expire, so this should be
720 * acceptable. Nobody sane sends replies without a
721 * matching method-call, so nobody should care. */
722 if (r == -EPERM && m->reply_cookie > 0)
723 return 1;
724
725 /* Return the error to the client, if we can */
726 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m");
727 if (r == -ENOBUFS) {
728 /* if local dbus1 peer does not dispatch its queue, warn only once */
729 if (!p->queue_overflow)
730 log_error("Dropped messages due to queue overflow of local peer (pid: "PID_FMT" uid: "UID_FMT")", p->local_creds.pid, p->local_creds.uid);
731 p->queue_overflow = true;
732 } else
733 log_error_errno(r,
734 "Failed to forward message we got from destination: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
735 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
736 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
737
738 return 1;
739 }
740
741 p->queue_overflow = false;
742 return 1;
743 }
744
745 static int proxy_process_local_to_destination(Proxy *p) {
746 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
747 int r;
748
749 assert(p);
750
751 r = sd_bus_process(p->local_bus, &m);
752 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
753 return r;
754 if (r < 0) {
755 log_error_errno(r, "Failed to process local bus: %m");
756 return r;
757 }
758 if (r == 0)
759 return 0;
760 if (!m)
761 return 1;
762
763 /* We officially got EOF, let's quit */
764 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
765 return -ECONNRESET;
766
767 r = process_hello(p, m);
768 if (r == -ECONNRESET || r == -ENOTCONN)
769 return r;
770 if (r < 0)
771 return log_error_errno(r, "Failed to process HELLO: %m");
772 if (r > 0)
773 return 1;
774
775 r = bus_proxy_process_driver(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
776 if (r == -ECONNRESET || r == -ENOTCONN)
777 return r;
778 if (r < 0)
779 return log_error_errno(r, "Failed to process driver calls: %m");
780 if (r > 0)
781 return 1;
782
783 for (;;) {
784 if (p->policy) {
785 r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
786 if (r == -ECONNRESET || r == -ENOTCONN)
787 return r;
788 if (r < 0)
789 return log_error_errno(r, "Failed to process policy: %m");
790 if (r > 0)
791 return 1;
792 }
793
794 r = sd_bus_send(p->destination_bus, m, NULL);
795 if (r < 0) {
796 if (r == -ECONNRESET || r == -ENOTCONN)
797 return r;
798
799 /* The name database changed since the policy check, hence let's check again */
800 if (r == -EREMCHG)
801 continue;
802
803 /* see above why EPERM is ignored for replies */
804 if (r == -EPERM && m->reply_cookie > 0)
805 return 1;
806
807 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
808 log_error_errno(r,
809 "Failed to forward message we got from local: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
810 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
811 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
812 return 1;
813 }
814
815 break;
816 }
817
818 return 1;
819 }
820
821 int proxy_run(Proxy *p) {
822 int r;
823
824 assert(p);
825
826 for (;;) {
827 bool busy = false;
828
829 if (p->got_hello) {
830 /* Read messages from bus, to pass them on to our client */
831 r = proxy_process_destination_to_local(p);
832 if (r == -ECONNRESET || r == -ENOTCONN)
833 return 0;
834 if (r < 0)
835 return r;
836 if (r > 0)
837 busy = true;
838 }
839
840 /* Read messages from our client, to pass them on to the bus */
841 r = proxy_process_local_to_destination(p);
842 if (r == -ECONNRESET || r == -ENOTCONN)
843 return 0;
844 if (r < 0)
845 return r;
846 if (r > 0)
847 busy = true;
848
849 if (!busy) {
850 r = proxy_wait(p);
851 if (r == -ECONNRESET || r == -ENOTCONN)
852 return 0;
853 if (r < 0)
854 return r;
855 }
856 }
857
858 return 0;
859 }