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