]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/proxy.c
sd-bus: introduce new sd_bus_flush_close_unref() call
[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_flush_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_flush_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_flush_close_unref(p->local_bus);
242 sd_bus_flush_close_unref(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 (sd_bus_message_is_signal(m, NULL, NULL)) {
498 /* If we forward a signal from dbus-1 to kdbus, we have
499 * no idea who the recipient is. Therefore, we cannot
500 * apply any dbus-1 policies that match on receiver
501 * credentials. We know sd-bus always sets
502 * KDBUS_MSG_SIGNAL, so the kernel applies policies to
503 * the message. Therefore, skip policy checks in this
504 * case. */
505 return 0;
506 } else 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)) {
507 if (n) {
508 /* If we made a receiver decision, then remember which
509 * name's policy we used, and to which unique ID it
510 * mapped when we made the decision. Then, let's pass
511 * this to the kernel when sending the message, so that
512 * it refuses the operation should the name and unique
513 * ID not map to each other anymore. */
514
515 r = free_and_strdup(&m->destination_ptr, n);
516 if (r < 0)
517 return r;
518
519 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
520 if (r < 0)
521 return r;
522 }
523
524 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
525 return 0;
526 }
527
528 /* Return an error back to the caller */
529 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
530 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
531
532 /* Return 1, indicating that the message shall not be processed any further */
533 return 1;
534 }
535
536 return 0;
537 }
538
539 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
540 Policy *policy;
541 int r;
542
543 assert(sp);
544
545 policy = shared_policy_acquire(sp);
546 r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
547 shared_policy_release(sp, policy);
548
549 return r;
550 }
551
552 static int process_hello(Proxy *p, sd_bus_message *m) {
553 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
554 bool is_hello;
555 int r;
556
557 assert(p);
558 assert(m);
559
560 /* As reaction to hello we need to respond with two messages:
561 * the callback reply and the NameAcquired for the unique
562 * name, since hello is otherwise obsolete on kdbus. */
563
564 is_hello =
565 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
566 streq_ptr(m->destination, "org.freedesktop.DBus");
567
568 if (!is_hello) {
569 if (p->got_hello)
570 return 0;
571
572 return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
573 }
574
575 if (p->got_hello)
576 return log_error_errno(EIO, "Got duplicate hello, aborting.");
577
578 p->got_hello = true;
579
580 if (!p->destination_bus->is_kernel)
581 return 0;
582
583 r = sd_bus_message_new_method_return(m, &n);
584 if (r < 0)
585 return log_error_errno(r, "Failed to generate HELLO reply: %m");
586
587 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
588 if (r < 0)
589 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
590
591 r = bus_message_append_sender(n, "org.freedesktop.DBus");
592 if (r < 0)
593 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
594
595 r = bus_seal_synthetic_message(p->local_bus, n);
596 if (r < 0)
597 return log_error_errno(r, "Failed to seal HELLO reply: %m");
598
599 r = sd_bus_send(p->local_bus, n, NULL);
600 if (r < 0)
601 return log_error_errno(r, "Failed to send HELLO reply: %m");
602
603 n = sd_bus_message_unref(n);
604 r = sd_bus_message_new_signal(
605 p->local_bus,
606 &n,
607 "/org/freedesktop/DBus",
608 "org.freedesktop.DBus",
609 "NameAcquired");
610 if (r < 0)
611 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
612
613 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
614 if (r < 0)
615 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
616
617 r = bus_message_append_sender(n, "org.freedesktop.DBus");
618 if (r < 0)
619 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
620
621 r = bus_seal_synthetic_message(p->local_bus, n);
622 if (r < 0)
623 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
624
625 r = sd_bus_send(p->local_bus, n, NULL);
626 if (r < 0)
627 return log_error_errno(r, "Failed to send NameAcquired message: %m");
628
629 return 1;
630 }
631
632 static int patch_sender(sd_bus *a, sd_bus_message *m) {
633 char **well_known = NULL;
634 sd_bus_creds *c;
635 int r;
636
637 assert(a);
638 assert(m);
639
640 if (!a->is_kernel)
641 return 0;
642
643 /* We will change the sender of messages from the bus driver
644 * so that they originate from the bus driver. This is a
645 * speciality originating from dbus1, where the bus driver did
646 * not have a unique id, but only the well-known name. */
647
648 c = sd_bus_message_get_creds(m);
649 if (!c)
650 return 0;
651
652 r = sd_bus_creds_get_well_known_names(c, &well_known);
653 if (r < 0)
654 return r;
655
656 if (strv_contains(well_known, "org.freedesktop.DBus"))
657 m->sender = "org.freedesktop.DBus";
658
659 return 0;
660 }
661
662 static int proxy_process_destination_to_local(Proxy *p) {
663 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
664 int r;
665
666 assert(p);
667
668 r = sd_bus_process(p->destination_bus, &m);
669 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
670 return r;
671 if (r < 0) {
672 log_error_errno(r, "Failed to process destination bus: %m");
673 return r;
674 }
675 if (r == 0)
676 return 0;
677 if (!m)
678 return 1;
679
680 /* We officially got EOF, let's quit */
681 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
682 return -ECONNRESET;
683
684 r = synthesize_name_acquired(p->destination_bus, p->local_bus, m);
685 if (r == -ECONNRESET || r == -ENOTCONN)
686 return r;
687 if (r < 0)
688 return log_error_errno(r, "Failed to synthesize message: %m");
689
690 patch_sender(p->destination_bus, m);
691
692 if (p->policy) {
693 r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
694 if (r == -ECONNRESET || r == -ENOTCONN)
695 return r;
696 if (r < 0)
697 return log_error_errno(r, "Failed to process policy: %m");
698 if (r > 0)
699 return 1;
700 }
701
702 r = sd_bus_send(p->local_bus, m, NULL);
703 if (r < 0) {
704 if (r == -ECONNRESET || r == -ENOTCONN)
705 return r;
706
707 /* If the peer tries to send a reply and it is
708 * rejected with EPERM by the kernel, we ignore the
709 * error. This catches cases where the original
710 * method-call didn't had EXPECT_REPLY set, but the
711 * proxy-peer still sends a reply. This is allowed in
712 * dbus1, but not in kdbus. We don't want to track
713 * reply-windows in the proxy, so we simply ignore
714 * EPERM for all replies. The only downside is, that
715 * callers are no longer notified if their replies are
716 * dropped. However, this is equivalent to the
717 * caller's timeout to expire, so this should be
718 * acceptable. Nobody sane sends replies without a
719 * matching method-call, so nobody should care. */
720 if (r == -EPERM && m->reply_cookie > 0)
721 return 1;
722
723 /* Return the error to the client, if we can */
724 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m");
725 if (r == -ENOBUFS) {
726 /* if local dbus1 peer does not dispatch its queue, warn only once */
727 if (!p->queue_overflow)
728 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);
729 p->queue_overflow = true;
730 } else
731 log_error_errno(r,
732 "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",
733 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
734 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
735
736 return 1;
737 }
738
739 p->queue_overflow = false;
740 return 1;
741 }
742
743 static int proxy_process_local_to_destination(Proxy *p) {
744 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
745 int r;
746
747 assert(p);
748
749 r = sd_bus_process(p->local_bus, &m);
750 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
751 return r;
752 if (r < 0) {
753 log_error_errno(r, "Failed to process local bus: %m");
754 return r;
755 }
756 if (r == 0)
757 return 0;
758 if (!m)
759 return 1;
760
761 /* We officially got EOF, let's quit */
762 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
763 return -ECONNRESET;
764
765 r = process_hello(p, m);
766 if (r == -ECONNRESET || r == -ENOTCONN)
767 return r;
768 if (r < 0)
769 return log_error_errno(r, "Failed to process HELLO: %m");
770 if (r > 0)
771 return 1;
772
773 r = bus_proxy_process_driver(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
774 if (r == -ECONNRESET || r == -ENOTCONN)
775 return r;
776 if (r < 0)
777 return log_error_errno(r, "Failed to process driver calls: %m");
778 if (r > 0)
779 return 1;
780
781 for (;;) {
782 if (p->policy) {
783 r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
784 if (r == -ECONNRESET || r == -ENOTCONN)
785 return r;
786 if (r < 0)
787 return log_error_errno(r, "Failed to process policy: %m");
788 if (r > 0)
789 return 1;
790 }
791
792 r = sd_bus_send(p->destination_bus, m, NULL);
793 if (r < 0) {
794 if (r == -ECONNRESET || r == -ENOTCONN)
795 return r;
796
797 /* The name database changed since the policy check, hence let's check again */
798 if (r == -EREMCHG)
799 continue;
800
801 /* see above why EPERM is ignored for replies */
802 if (r == -EPERM && m->reply_cookie > 0)
803 return 1;
804
805 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
806 log_error_errno(r,
807 "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",
808 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
809 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
810 return 1;
811 }
812
813 break;
814 }
815
816 return 1;
817 }
818
819 int proxy_run(Proxy *p) {
820 int r;
821
822 assert(p);
823
824 for (;;) {
825 bool busy = false;
826
827 if (p->got_hello) {
828 /* Read messages from bus, to pass them on to our client */
829 r = proxy_process_destination_to_local(p);
830 if (r == -ECONNRESET || r == -ENOTCONN)
831 return 0;
832 if (r < 0)
833 return r;
834 if (r > 0)
835 busy = true;
836 }
837
838 /* Read messages from our client, to pass them on to the bus */
839 r = proxy_process_local_to_destination(p);
840 if (r == -ECONNRESET || r == -ENOTCONN)
841 return 0;
842 if (r < 0)
843 return r;
844 if (r > 0)
845 busy = true;
846
847 if (!busy) {
848 r = proxy_wait(p);
849 if (r == -ECONNRESET || r == -ENOTCONN)
850 return 0;
851 if (r < 0)
852 return r;
853 }
854 }
855
856 return 0;
857 }