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