2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Daniel Mack
6 Copyright 2014 Kay Sievers
7 Copyright 2014 David Herrmann
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/socket.h>
27 #include <sys/types.h>
30 #include "sd-daemon.h"
32 #include "alloc-util.h"
33 #include "bus-control.h"
34 #include "bus-internal.h"
35 #include "bus-message.h"
37 #include "bus-xml-policy.h"
40 #include "formats-util.h"
45 #include "synthesize.h"
46 #include "user-util.h"
49 static int proxy_create_destination(Proxy
*p
, const char *destination
, const char *local_sec
, bool negotiate_fds
) {
50 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*b
= NULL
;
55 return log_error_errno(r
, "Failed to allocate bus: %m");
57 r
= sd_bus_set_description(b
, "sd-proxy");
59 return log_error_errno(r
, "Failed to set bus name: %m");
61 r
= sd_bus_set_address(b
, destination
);
63 return log_error_errno(r
, "Failed to set address to connect to: %m");
65 r
= sd_bus_negotiate_fds(b
, negotiate_fds
);
67 return log_error_errno(r
, "Failed to set FD negotiation: %m");
69 r
= sd_bus_negotiate_creds(b
, true, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
71 return log_error_errno(r
, "Failed to set credential negotiation: %m");
73 if (p
->local_creds
.pid
> 0) {
74 b
->fake_pids
.pid
= p
->local_creds
.pid
;
75 b
->fake_pids_valid
= true;
77 b
->fake_creds
.uid
= UID_INVALID
;
78 b
->fake_creds
.euid
= p
->local_creds
.uid
;
79 b
->fake_creds
.suid
= UID_INVALID
;
80 b
->fake_creds
.fsuid
= UID_INVALID
;
81 b
->fake_creds
.gid
= GID_INVALID
;
82 b
->fake_creds
.egid
= p
->local_creds
.gid
;
83 b
->fake_creds
.sgid
= GID_INVALID
;
84 b
->fake_creds
.fsgid
= GID_INVALID
;
85 b
->fake_creds_valid
= true;
89 b
->fake_label
= strdup(local_sec
);
94 b
->manual_peer_interface
= true;
98 return log_error_errno(r
, "Failed to start bus client: %m");
100 p
->destination_bus
= b
;
105 static int proxy_create_local(Proxy
*p
, bool negotiate_fds
) {
106 sd_id128_t server_id
;
112 return log_error_errno(r
, "Failed to allocate bus: %m");
114 r
= sd_bus_set_fd(b
, p
->local_in
, p
->local_out
);
117 return log_error_errno(r
, "Failed to set fds: %m");
120 /* The fds are now owned by the bus, and we indicate that by
121 * storing the bus object in the proxy object. */
124 r
= sd_bus_get_bus_id(p
->destination_bus
, &server_id
);
126 return log_error_errno(r
, "Failed to get server ID: %m");
128 r
= sd_bus_set_server(b
, 1, server_id
);
130 return log_error_errno(r
, "Failed to set server mode: %m");
132 r
= sd_bus_negotiate_fds(b
, negotiate_fds
);
134 return log_error_errno(r
, "Failed to set FD negotiation: %m");
136 r
= sd_bus_negotiate_creds(b
, true, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
138 return log_error_errno(r
, "Failed to set credential negotiation: %m");
140 r
= sd_bus_set_anonymous(b
, true);
142 return log_error_errno(r
, "Failed to set anonymous authentication: %m");
144 b
->manual_peer_interface
= true;
148 return log_error_errno(r
, "Failed to start bus client: %m");
153 static int proxy_match_synthetic(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
156 p
->synthetic_matched
= true;
157 return 0; /* make sure to continue processing it in further handlers */
161 * We always need NameOwnerChanged so we can synthesize NameLost and
162 * NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so
163 * subscribe unconditionally.
165 static int proxy_prepare_matches(Proxy
*p
) {
166 _cleanup_free_
char *match
= NULL
;
170 if (!p
->destination_bus
->is_kernel
)
173 r
= sd_bus_get_unique_name(p
->destination_bus
, &unique
);
175 return log_error_errno(r
, "Failed to get unique name: %m");
177 match
= strjoin("type='signal',"
178 "sender='org.freedesktop.DBus',"
179 "path='/org/freedesktop/DBus',"
180 "interface='org.freedesktop.DBus',"
181 "member='NameOwnerChanged',"
189 r
= sd_bus_add_match(p
->destination_bus
, NULL
, match
, proxy_match_synthetic
, p
);
191 return log_error_errno(r
, "Failed to add match for NameLost: %m");
194 match
= strjoin("type='signal',"
195 "sender='org.freedesktop.DBus',"
196 "path='/org/freedesktop/DBus',"
197 "interface='org.freedesktop.DBus',"
198 "member='NameOwnerChanged',"
206 r
= sd_bus_add_match(p
->destination_bus
, NULL
, match
, proxy_match_synthetic
, p
);
208 return log_error_errno(r
, "Failed to add match for NameAcquired: %m");
211 match
= strjoin("type='signal',"
219 r
= sd_bus_add_match(p
->destination_bus
, NULL
, match
, proxy_match_synthetic
, p
);
221 log_error_errno(r
, "Failed to add match for directed signals: %m");
222 /* FIXME: temporarily ignore error to support older kdbus versions */
227 int proxy_new(Proxy
**out
, int in_fd
, int out_fd
, const char *destination
) {
228 _cleanup_(proxy_freep
) Proxy
*p
= NULL
;
229 _cleanup_free_
char *local_sec
= NULL
;
233 /* This takes possession/destroys the file descriptors passed
234 * in even on failure. The caller should hence forget about
235 * the fds in all cases after calling this function and not
246 p
->local_out
= out_fd
;
248 p
->owned_names
= set_new(&string_hash_ops
);
252 is_unix
= sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
253 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
256 (void) getpeercred(in_fd
, &p
->local_creds
);
257 (void) getpeersec(in_fd
, &local_sec
);
260 r
= proxy_create_destination(p
, destination
, local_sec
, is_unix
);
264 r
= proxy_create_local(p
, is_unix
);
268 r
= proxy_prepare_matches(p
);
278 Proxy
*proxy_free(Proxy
*p
) {
279 ProxyActivation
*activation
;
284 while ((activation
= p
->activations
)) {
285 LIST_REMOVE(activations_by_proxy
, p
->activations
, activation
);
286 sd_bus_message_unref(activation
->request
);
287 sd_bus_slot_unref(activation
->slot
);
292 sd_bus_flush_close_unref(p
->local_bus
);
294 safe_close(p
->local_in
);
295 if (p
->local_out
!= p
->local_in
)
296 safe_close(p
->local_out
);
299 sd_bus_flush_close_unref(p
->destination_bus
);
300 set_free_free(p
->owned_names
);
306 int proxy_set_policy(Proxy
*p
, SharedPolicy
*sp
, char **configuration
) {
307 _cleanup_strv_free_
char **strv
= NULL
;
314 /* no need to load legacy policy if destination is not kdbus */
315 if (!p
->destination_bus
->is_kernel
)
320 policy
= shared_policy_acquire(sp
);
322 /* policy already pre-loaded */
323 shared_policy_release(sp
, policy
);
327 if (!configuration
) {
330 r
= sd_bus_get_scope(p
->destination_bus
, &scope
);
332 return log_error_errno(r
, "Couldn't determine bus scope: %m");
334 if (streq(scope
, "system"))
335 strv
= strv_new("/usr/share/dbus-1/system.conf",
336 "/etc/dbus-1/system.conf",
337 "/usr/share/dbus-1/system.d/",
338 "/etc/dbus-1/system.d/",
339 "/etc/dbus-1/system-local.conf",
341 else if (streq(scope
, "user"))
342 strv
= strv_new("/usr/share/dbus-1/session.conf",
343 "/etc/dbus-1/session.conf",
344 "/usr/share/dbus-1/session.d/",
345 "/etc/dbus-1/session.d/",
346 "/etc/dbus-1/session-local.conf",
349 return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope
);
354 configuration
= strv
;
357 return shared_policy_preload(sp
, configuration
);
360 int proxy_hello_policy(Proxy
*p
, uid_t original_uid
) {
369 policy
= shared_policy_acquire(p
->policy
);
371 if (p
->local_creds
.uid
== original_uid
)
372 log_debug("Permitting access, since bus owner matches bus client.");
373 else if (policy_check_hello(policy
, p
->local_creds
.uid
, p
->local_creds
.gid
))
374 log_debug("Permitting access due to XML policy.");
376 r
= log_error_errno(EPERM
, "Policy denied connection.");
378 shared_policy_release(p
->policy
, policy
);
383 static int proxy_wait(Proxy
*p
) {
384 uint64_t timeout_destination
, timeout_local
, t
;
385 int events_destination
, events_local
, fd
;
386 struct timespec _ts
, *ts
;
387 struct pollfd
*pollfd
;
392 fd
= sd_bus_get_fd(p
->destination_bus
);
394 return log_error_errno(fd
, "Failed to get fd: %m");
396 events_destination
= sd_bus_get_events(p
->destination_bus
);
397 if (events_destination
< 0)
398 return log_error_errno(events_destination
, "Failed to get events mask: %m");
400 r
= sd_bus_get_timeout(p
->destination_bus
, &timeout_destination
);
402 return log_error_errno(r
, "Failed to get timeout: %m");
404 events_local
= sd_bus_get_events(p
->local_bus
);
405 if (events_local
< 0)
406 return log_error_errno(events_local
, "Failed to get events mask: %m");
408 r
= sd_bus_get_timeout(p
->local_bus
, &timeout_local
);
410 return log_error_errno(r
, "Failed to get timeout: %m");
412 t
= timeout_destination
;
413 if (t
== (uint64_t) -1 || (timeout_local
!= (uint64_t) -1 && timeout_local
< timeout_destination
))
416 if (t
== (uint64_t) -1)
421 nw
= now(CLOCK_MONOTONIC
);
427 ts
= timespec_store(&_ts
, t
);
430 pollfd
= (struct pollfd
[3]) {
431 { .fd
= fd
, .events
= events_destination
, },
432 { .fd
= p
->local_in
, .events
= events_local
& POLLIN
, },
433 { .fd
= p
->local_out
, .events
= events_local
& POLLOUT
, },
436 r
= ppoll(pollfd
, 3, ts
, NULL
);
438 return log_error_errno(errno
, "ppoll() failed: %m");
443 static int handle_policy_error(sd_bus_message
*m
, int r
) {
444 if (r
== -ESRCH
|| r
== -ENXIO
)
445 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Name %s is currently not owned by anyone.", m
->destination
);
450 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
) {
461 * dbus-1 distinguishes expected and non-expected replies by tracking
462 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
463 * on expected replies, unless explicitly specified. But we dont track
464 * method-calls, thus, we cannot know whether a reply is expected.
465 * Fortunately, the kdbus forbids non-expected replies, so we can safely
466 * ignore any policy on those and let the kernel deal with it.
468 * TODO: To be correct, we should only ignore policy-tags that are
469 * applied on non-expected replies. However, so far we don't parse those
470 * tags so we let everything pass. I haven't seen a DENY policy tag on
471 * expected-replies, ever, so don't bother..
473 if (m
->reply_cookie
> 0)
476 if (from
->is_kernel
) {
477 uid_t sender_uid
= UID_INVALID
;
478 gid_t sender_gid
= GID_INVALID
;
479 char **sender_names
= NULL
;
481 /* Driver messages are always OK */
482 if (streq_ptr(m
->sender
, "org.freedesktop.DBus"))
485 /* The message came from the kernel, and is sent to our legacy client. */
486 (void) sd_bus_creds_get_well_known_names(&m
->creds
, &sender_names
);
488 (void) sd_bus_creds_get_euid(&m
->creds
, &sender_uid
);
489 (void) sd_bus_creds_get_egid(&m
->creds
, &sender_gid
);
491 if (sender_uid
== UID_INVALID
|| sender_gid
== GID_INVALID
) {
492 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*sender_creds
= NULL
;
494 /* If the message came from another legacy
495 * client, then the message creds will be
496 * missing, simply because on legacy clients
497 * per-message creds were unknown. In this
498 * case, query the creds of the peer
501 r
= bus_get_name_creds_kdbus(from
, m
->sender
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EGID
, true, &sender_creds
);
503 return handle_policy_error(m
, r
);
505 (void) sd_bus_creds_get_euid(sender_creds
, &sender_uid
);
506 (void) sd_bus_creds_get_egid(sender_creds
, &sender_gid
);
509 /* First check whether the sender can send the message to our name */
510 if (policy_check_send(policy
, sender_uid
, sender_gid
, m
->header
->type
, owned_names
, NULL
, m
->path
, m
->interface
, m
->member
, false, NULL
) &&
511 policy_check_recv(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, NULL
, sender_names
, m
->path
, m
->interface
, m
->member
, false))
514 /* Return an error back to the caller */
515 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
516 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML receiver policy.");
518 /* Return 1, indicating that the message shall not be processed any further */
523 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*destination_creds
= NULL
;
524 uid_t destination_uid
= UID_INVALID
;
525 gid_t destination_gid
= GID_INVALID
;
526 const char *destination_unique
= NULL
;
527 char **destination_names
= NULL
;
530 /* Driver messages are always OK */
531 if (streq_ptr(m
->destination
, "org.freedesktop.DBus"))
534 /* The message came from the legacy client, and is sent to kdbus. */
535 if (m
->destination
) {
536 r
= bus_get_name_creds_kdbus(to
, m
->destination
,
537 SD_BUS_CREDS_WELL_KNOWN_NAMES
|SD_BUS_CREDS_UNIQUE_NAME
|
538 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_PID
,
539 true, &destination_creds
);
541 return handle_policy_error(m
, r
);
543 r
= sd_bus_creds_get_unique_name(destination_creds
, &destination_unique
);
545 return handle_policy_error(m
, r
);
547 (void) sd_bus_creds_get_well_known_names(destination_creds
, &destination_names
);
549 (void) sd_bus_creds_get_euid(destination_creds
, &destination_uid
);
550 (void) sd_bus_creds_get_egid(destination_creds
, &destination_gid
);
553 /* First check if we (the sender) can send to this name */
554 if (sd_bus_message_is_signal(m
, NULL
, NULL
)) {
555 /* If we forward a signal from dbus-1 to kdbus, we have
556 * no idea who the recipient is. Therefore, we cannot
557 * apply any dbus-1 policies that match on receiver
558 * credentials. We know sd-bus always sets
559 * KDBUS_MSG_SIGNAL, so the kernel applies policies to
560 * the message. Therefore, skip policy checks in this
563 } 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
)) {
565 /* If we made a receiver decision, then remember which
566 * name's policy we used, and to which unique ID it
567 * mapped when we made the decision. Then, let's pass
568 * this to the kernel when sending the message, so that
569 * it refuses the operation should the name and unique
570 * ID not map to each other anymore. */
572 r
= free_and_strdup(&m
->destination_ptr
, n
);
576 r
= bus_kernel_parse_unique_name(destination_unique
, &m
->verify_destination_id
);
581 if (policy_check_recv(policy
, destination_uid
, destination_gid
, m
->header
->type
, owned_names
, NULL
, m
->path
, m
->interface
, m
->member
, true))
585 /* Return an error back to the caller */
586 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
587 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML sender policy.");
589 /* Return 1, indicating that the message shall not be processed any further */
596 static int process_policy(sd_bus
*from
, sd_bus
*to
, sd_bus_message
*m
, SharedPolicy
*sp
, const struct ucred
*our_ucred
, Set
*owned_names
) {
602 policy
= shared_policy_acquire(sp
);
603 r
= process_policy_unlocked(from
, to
, m
, policy
, our_ucred
, owned_names
);
604 shared_policy_release(sp
, policy
);
609 static int process_hello(Proxy
*p
, sd_bus_message
*m
) {
610 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
617 /* As reaction to hello we need to respond with two messages:
618 * the callback reply and the NameAcquired for the unique
619 * name, since hello is otherwise obsolete on kdbus. */
622 sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "Hello") &&
623 streq_ptr(m
->destination
, "org.freedesktop.DBus");
629 return log_error_errno(EIO
, "First packet isn't hello (it's %s.%s), aborting.", m
->interface
, m
->member
);
633 return log_error_errno(EIO
, "Got duplicate hello, aborting.");
637 if (!p
->destination_bus
->is_kernel
)
640 r
= sd_bus_message_new_method_return(m
, &n
);
642 return log_error_errno(r
, "Failed to generate HELLO reply: %m");
644 r
= sd_bus_message_append(n
, "s", p
->destination_bus
->unique_name
);
646 return log_error_errno(r
, "Failed to append unique name to HELLO reply: %m");
648 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
650 return log_error_errno(r
, "Failed to append sender to HELLO reply: %m");
652 r
= bus_seal_synthetic_message(p
->local_bus
, n
);
654 return log_error_errno(r
, "Failed to seal HELLO reply: %m");
656 r
= sd_bus_send(p
->local_bus
, n
, NULL
);
658 return log_error_errno(r
, "Failed to send HELLO reply: %m");
660 n
= sd_bus_message_unref(n
);
661 r
= sd_bus_message_new_signal(
664 "/org/freedesktop/DBus",
665 "org.freedesktop.DBus",
668 return log_error_errno(r
, "Failed to allocate initial NameAcquired message: %m");
670 r
= sd_bus_message_append(n
, "s", p
->destination_bus
->unique_name
);
672 return log_error_errno(r
, "Failed to append unique name to NameAcquired message: %m");
674 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
676 return log_error_errno(r
, "Failed to append sender to NameAcquired message: %m");
678 r
= sd_bus_message_set_destination(n
, p
->destination_bus
->unique_name
);
680 return log_error_errno(r
, "Failed to set destination for NameAcquired message: %m");
682 r
= bus_seal_synthetic_message(p
->local_bus
, n
);
684 return log_error_errno(r
, "Failed to seal NameAcquired message: %m");
686 r
= sd_bus_send(p
->local_bus
, n
, NULL
);
688 return log_error_errno(r
, "Failed to send NameAcquired message: %m");
693 static int patch_sender(sd_bus
*a
, sd_bus_message
*m
) {
694 char **well_known
= NULL
;
704 /* We will change the sender of messages from the bus driver
705 * so that they originate from the bus driver. This is a
706 * speciality originating from dbus1, where the bus driver did
707 * not have a unique id, but only the well-known name. */
709 c
= sd_bus_message_get_creds(m
);
713 r
= sd_bus_creds_get_well_known_names(c
, &well_known
);
717 if (strv_contains(well_known
, "org.freedesktop.DBus"))
718 m
->sender
= "org.freedesktop.DBus";
723 static int proxy_process_destination_to_local(Proxy
*p
) {
724 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
725 bool matched
, matched_synthetic
;
731 * Usually, we would just take any message that the bus passes to us
732 * and forward it to the local connection. However, there are actually
733 * applications that fail if they receive broadcasts that they didn't
734 * subscribe to. Therefore, we actually emulate a real broadcast
735 * matching here, and discard any broadcasts that weren't matched. Our
736 * match-handlers remembers whether a message was matched by any rule,
737 * by marking it in @p->message_matched.
740 r
= sd_bus_process(p
->destination_bus
, &m
);
742 matched
= p
->message_matched
;
743 matched_synthetic
= p
->synthetic_matched
;
744 p
->message_matched
= false;
745 p
->synthetic_matched
= false;
747 if (r
== -ECONNRESET
|| r
== -ENOTCONN
) /* Treat 'connection reset by peer' as clean exit condition */
750 log_error_errno(r
, "Failed to process destination bus: %m");
758 /* We officially got EOF, let's quit */
759 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected"))
762 r
= synthesize_name_acquired(p
, p
->destination_bus
, p
->local_bus
, m
);
763 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
766 return log_error_errno(r
, "Failed to synthesize message: %m");
768 /* discard broadcasts that were not matched by any MATCH rule */
769 if (!matched
&& !sd_bus_message_get_destination(m
)) {
770 if (!matched_synthetic
)
771 log_debug("Dropped unmatched broadcast: uid=" UID_FMT
" gid=" GID_FMT
" pid=" PID_FMT
" message=%s path=%s interface=%s member=%s sender=%s destination=%s",
772 p
->local_creds
.uid
, p
->local_creds
.gid
, p
->local_creds
.pid
, bus_message_type_to_string(m
->header
->type
),
773 strna(m
->path
), strna(m
->interface
), strna(m
->member
), strna(m
->sender
), strna(m
->destination
));
777 patch_sender(p
->destination_bus
, m
);
780 r
= process_policy(p
->destination_bus
, p
->local_bus
, m
, p
->policy
, &p
->local_creds
, p
->owned_names
);
781 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
784 return log_error_errno(r
, "Failed to process policy: %m");
789 r
= sd_bus_send(p
->local_bus
, m
, NULL
);
791 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
794 /* If the peer tries to send a reply and it is
795 * rejected with EBADSLT by the kernel, we ignore the
796 * error. This catches cases where the original
797 * method-call didn't had EXPECT_REPLY set, but the
798 * proxy-peer still sends a reply. This is allowed in
799 * dbus1, but not in kdbus. We don't want to track
800 * reply-windows in the proxy, so we simply ignore
801 * EBADSLT for all replies. The only downside is, that
802 * callers are no longer notified if their replies are
803 * dropped. However, this is equivalent to the
804 * caller's timeout to expire, so this should be
805 * acceptable. Nobody sane sends replies without a
806 * matching method-call, so nobody should care. */
808 /* FIXME: remove -EPERM when kdbus is updated */
809 if ((r
== -EPERM
|| r
== -EBADSLT
) && m
->reply_cookie
> 0)
812 /* Return the error to the client, if we can */
813 synthetic_reply_method_errnof(m
, r
, "Failed to forward message we got from destination: %m");
815 /* if local dbus1 peer does not dispatch its queue, warn only once */
816 if (!p
->queue_overflow
)
817 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
);
818 p
->queue_overflow
= true;
821 "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",
822 p
->local_creds
.uid
, p
->local_creds
.gid
, bus_message_type_to_string(m
->header
->type
),
823 strna(m
->destination
), strna(m
->path
), strna(m
->interface
), strna(m
->member
));
828 p
->queue_overflow
= false;
832 static int proxy_process_local_to_destination(Proxy
*p
) {
833 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
838 r
= sd_bus_process(p
->local_bus
, &m
);
839 if (r
== -ECONNRESET
|| r
== -ENOTCONN
) /* Treat 'connection reset by peer' as clean exit condition */
842 log_error_errno(r
, "Failed to process local bus: %m");
850 /* We officially got EOF, let's quit */
851 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected"))
854 r
= process_hello(p
, m
);
855 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
858 return log_error_errno(r
, "Failed to process HELLO: %m");
862 r
= bus_proxy_process_driver(p
, p
->destination_bus
, p
->local_bus
, m
, p
->policy
, &p
->local_creds
, p
->owned_names
);
863 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
866 return log_error_errno(r
, "Failed to process driver calls: %m");
872 r
= process_policy(p
->local_bus
, p
->destination_bus
, m
, p
->policy
, &p
->local_creds
, p
->owned_names
);
873 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
876 return log_error_errno(r
, "Failed to process policy: %m");
881 r
= sd_bus_send(p
->destination_bus
, m
, NULL
);
883 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
886 /* The name database changed since the policy check, hence let's check again */
890 /* see above why EBADSLT is ignored for replies */
891 if ((r
== -EPERM
|| r
== -EBADSLT
) && m
->reply_cookie
> 0)
894 synthetic_reply_method_errnof(m
, r
, "Failed to forward message we got from local: %m");
896 "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",
897 p
->local_creds
.uid
, p
->local_creds
.gid
, bus_message_type_to_string(m
->header
->type
),
898 strna(m
->destination
), strna(m
->path
), strna(m
->interface
), strna(m
->member
));
908 int proxy_match(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
911 p
->message_matched
= true;
912 return 0; /* make sure to continue processing it in further handlers */
915 int proxy_run(Proxy
*p
) {
924 /* Read messages from bus, to pass them on to our client */
925 r
= proxy_process_destination_to_local(p
);
926 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
934 /* Read messages from our client, to pass them on to the bus */
935 r
= proxy_process_local_to_destination(p
);
936 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
945 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)