1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
9 Copyright 2014 David Herrmann
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.
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.
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/>.
28 #include <sys/socket.h>
29 #include <sys/types.h>
32 #include "sd-daemon.h"
34 #include "alloc-util.h"
35 #include "bus-control.h"
36 #include "bus-internal.h"
37 #include "bus-message.h"
39 #include "bus-xml-policy.h"
42 #include "formats-util.h"
47 #include "synthesize.h"
48 #include "user-util.h"
51 static int proxy_create_destination(Proxy
*p
, const char *destination
, const char *local_sec
, bool negotiate_fds
) {
52 _cleanup_bus_flush_close_unref_ sd_bus
*b
= NULL
;
57 return log_error_errno(r
, "Failed to allocate bus: %m");
59 r
= sd_bus_set_description(b
, "sd-proxy");
61 return log_error_errno(r
, "Failed to set bus name: %m");
63 r
= sd_bus_set_address(b
, destination
);
65 return log_error_errno(r
, "Failed to set address to connect to: %m");
67 r
= sd_bus_negotiate_fds(b
, negotiate_fds
);
69 return log_error_errno(r
, "Failed to set FD negotiation: %m");
71 r
= sd_bus_negotiate_creds(b
, true, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
73 return log_error_errno(r
, "Failed to set credential negotiation: %m");
75 if (p
->local_creds
.pid
> 0) {
76 b
->fake_pids
.pid
= p
->local_creds
.pid
;
77 b
->fake_pids_valid
= true;
79 b
->fake_creds
.uid
= UID_INVALID
;
80 b
->fake_creds
.euid
= p
->local_creds
.uid
;
81 b
->fake_creds
.suid
= UID_INVALID
;
82 b
->fake_creds
.fsuid
= UID_INVALID
;
83 b
->fake_creds
.gid
= GID_INVALID
;
84 b
->fake_creds
.egid
= p
->local_creds
.gid
;
85 b
->fake_creds
.sgid
= GID_INVALID
;
86 b
->fake_creds
.fsgid
= GID_INVALID
;
87 b
->fake_creds_valid
= true;
91 b
->fake_label
= strdup(local_sec
);
96 b
->manual_peer_interface
= true;
100 return log_error_errno(r
, "Failed to start bus client: %m");
102 p
->destination_bus
= b
;
107 static int proxy_create_local(Proxy
*p
, bool negotiate_fds
) {
108 sd_id128_t server_id
;
114 return log_error_errno(r
, "Failed to allocate bus: %m");
116 r
= sd_bus_set_fd(b
, p
->local_in
, p
->local_out
);
119 return log_error_errno(r
, "Failed to set fds: %m");
122 /* The fds are now owned by the bus, and we indicate that by
123 * storing the bus object in the proxy object. */
126 r
= sd_bus_get_bus_id(p
->destination_bus
, &server_id
);
128 return log_error_errno(r
, "Failed to get server ID: %m");
130 r
= sd_bus_set_server(b
, 1, server_id
);
132 return log_error_errno(r
, "Failed to set server mode: %m");
134 r
= sd_bus_negotiate_fds(b
, negotiate_fds
);
136 return log_error_errno(r
, "Failed to set FD negotiation: %m");
138 r
= sd_bus_negotiate_creds(b
, true, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
140 return log_error_errno(r
, "Failed to set credential negotiation: %m");
142 r
= sd_bus_set_anonymous(b
, true);
144 return log_error_errno(r
, "Failed to set anonymous authentication: %m");
146 b
->manual_peer_interface
= true;
150 return log_error_errno(r
, "Failed to start bus client: %m");
155 static int proxy_match_synthetic(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
158 p
->synthetic_matched
= true;
159 return 0; /* make sure to continue processing it in further handlers */
163 * We always need NameOwnerChanged so we can synthesize NameLost and
164 * NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so
165 * subscribe unconditionally.
167 static int proxy_prepare_matches(Proxy
*p
) {
168 _cleanup_free_
char *match
= NULL
;
172 if (!p
->destination_bus
->is_kernel
)
175 r
= sd_bus_get_unique_name(p
->destination_bus
, &unique
);
177 return log_error_errno(r
, "Failed to get unique name: %m");
179 match
= strjoin("type='signal',"
180 "sender='org.freedesktop.DBus',"
181 "path='/org/freedesktop/DBus',"
182 "interface='org.freedesktop.DBus',"
183 "member='NameOwnerChanged',"
191 r
= sd_bus_add_match(p
->destination_bus
, NULL
, match
, proxy_match_synthetic
, p
);
193 return log_error_errno(r
, "Failed to add match for NameLost: %m");
196 match
= strjoin("type='signal',"
197 "sender='org.freedesktop.DBus',"
198 "path='/org/freedesktop/DBus',"
199 "interface='org.freedesktop.DBus',"
200 "member='NameOwnerChanged',"
208 r
= sd_bus_add_match(p
->destination_bus
, NULL
, match
, proxy_match_synthetic
, p
);
210 return log_error_errno(r
, "Failed to add match for NameAcquired: %m");
213 match
= strjoin("type='signal',"
221 r
= sd_bus_add_match(p
->destination_bus
, NULL
, match
, proxy_match_synthetic
, p
);
223 log_error_errno(r
, "Failed to add match for directed signals: %m");
224 /* FIXME: temporarily ignore error to support older kdbus versions */
229 int proxy_new(Proxy
**out
, int in_fd
, int out_fd
, const char *destination
) {
230 _cleanup_(proxy_freep
) Proxy
*p
= NULL
;
231 _cleanup_free_
char *local_sec
= NULL
;
235 /* This takes possession/destroys the file descriptors passed
236 * in even on failure. The caller should hence forget about
237 * the fds in all cases after calling this function and not
248 p
->local_out
= out_fd
;
250 p
->owned_names
= set_new(&string_hash_ops
);
254 is_unix
= sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
255 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
258 (void) getpeercred(in_fd
, &p
->local_creds
);
259 (void) getpeersec(in_fd
, &local_sec
);
262 r
= proxy_create_destination(p
, destination
, local_sec
, is_unix
);
266 r
= proxy_create_local(p
, is_unix
);
270 r
= proxy_prepare_matches(p
);
280 Proxy
*proxy_free(Proxy
*p
) {
281 ProxyActivation
*activation
;
286 while ((activation
= p
->activations
)) {
287 LIST_REMOVE(activations_by_proxy
, p
->activations
, activation
);
288 sd_bus_message_unref(activation
->request
);
289 sd_bus_slot_unref(activation
->slot
);
294 sd_bus_flush_close_unref(p
->local_bus
);
296 safe_close(p
->local_in
);
297 if (p
->local_out
!= p
->local_in
)
298 safe_close(p
->local_out
);
301 sd_bus_flush_close_unref(p
->destination_bus
);
302 set_free_free(p
->owned_names
);
308 int proxy_set_policy(Proxy
*p
, SharedPolicy
*sp
, char **configuration
) {
309 _cleanup_strv_free_
char **strv
= NULL
;
316 /* no need to load legacy policy if destination is not kdbus */
317 if (!p
->destination_bus
->is_kernel
)
322 policy
= shared_policy_acquire(sp
);
324 /* policy already pre-loaded */
325 shared_policy_release(sp
, policy
);
329 if (!configuration
) {
332 r
= sd_bus_get_scope(p
->destination_bus
, &scope
);
334 return log_error_errno(r
, "Couldn't determine bus scope: %m");
336 if (streq(scope
, "system"))
337 strv
= strv_new("/usr/share/dbus-1/system.conf",
338 "/etc/dbus-1/system.conf",
339 "/usr/share/dbus-1/system.d/",
340 "/etc/dbus-1/system.d/",
341 "/etc/dbus-1/system-local.conf",
343 else if (streq(scope
, "user"))
344 strv
= strv_new("/usr/share/dbus-1/session.conf",
345 "/etc/dbus-1/session.conf",
346 "/usr/share/dbus-1/session.d/",
347 "/etc/dbus-1/session.d/",
348 "/etc/dbus-1/session-local.conf",
351 return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope
);
356 configuration
= strv
;
359 return shared_policy_preload(sp
, configuration
);
362 int proxy_hello_policy(Proxy
*p
, uid_t original_uid
) {
371 policy
= shared_policy_acquire(p
->policy
);
373 if (p
->local_creds
.uid
== original_uid
)
374 log_debug("Permitting access, since bus owner matches bus client.");
375 else if (policy_check_hello(policy
, p
->local_creds
.uid
, p
->local_creds
.gid
))
376 log_debug("Permitting access due to XML policy.");
378 r
= log_error_errno(EPERM
, "Policy denied connection.");
380 shared_policy_release(p
->policy
, policy
);
385 static int proxy_wait(Proxy
*p
) {
386 uint64_t timeout_destination
, timeout_local
, t
;
387 int events_destination
, events_local
, fd
;
388 struct timespec _ts
, *ts
;
389 struct pollfd
*pollfd
;
394 fd
= sd_bus_get_fd(p
->destination_bus
);
396 return log_error_errno(fd
, "Failed to get fd: %m");
398 events_destination
= sd_bus_get_events(p
->destination_bus
);
399 if (events_destination
< 0)
400 return log_error_errno(events_destination
, "Failed to get events mask: %m");
402 r
= sd_bus_get_timeout(p
->destination_bus
, &timeout_destination
);
404 return log_error_errno(r
, "Failed to get timeout: %m");
406 events_local
= sd_bus_get_events(p
->local_bus
);
407 if (events_local
< 0)
408 return log_error_errno(events_local
, "Failed to get events mask: %m");
410 r
= sd_bus_get_timeout(p
->local_bus
, &timeout_local
);
412 return log_error_errno(r
, "Failed to get timeout: %m");
414 t
= timeout_destination
;
415 if (t
== (uint64_t) -1 || (timeout_local
!= (uint64_t) -1 && timeout_local
< timeout_destination
))
418 if (t
== (uint64_t) -1)
423 nw
= now(CLOCK_MONOTONIC
);
429 ts
= timespec_store(&_ts
, t
);
432 pollfd
= (struct pollfd
[3]) {
433 { .fd
= fd
, .events
= events_destination
, },
434 { .fd
= p
->local_in
, .events
= events_local
& POLLIN
, },
435 { .fd
= p
->local_out
, .events
= events_local
& POLLOUT
, },
438 r
= ppoll(pollfd
, 3, ts
, NULL
);
440 return log_error_errno(errno
, "ppoll() failed: %m");
445 static int handle_policy_error(sd_bus_message
*m
, int r
) {
446 if (r
== -ESRCH
|| r
== -ENXIO
)
447 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Name %s is currently not owned by anyone.", m
->destination
);
452 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
) {
463 * dbus-1 distinguishes expected and non-expected replies by tracking
464 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
465 * on expected replies, unless explicitly specified. But we dont track
466 * method-calls, thus, we cannot know whether a reply is expected.
467 * Fortunately, the kdbus forbids non-expected replies, so we can safely
468 * ignore any policy on those and let the kernel deal with it.
470 * TODO: To be correct, we should only ignore policy-tags that are
471 * applied on non-expected replies. However, so far we don't parse those
472 * tags so we let everything pass. I haven't seen a DENY policy tag on
473 * expected-replies, ever, so don't bother..
475 if (m
->reply_cookie
> 0)
478 if (from
->is_kernel
) {
479 uid_t sender_uid
= UID_INVALID
;
480 gid_t sender_gid
= GID_INVALID
;
481 char **sender_names
= NULL
;
483 /* Driver messages are always OK */
484 if (streq_ptr(m
->sender
, "org.freedesktop.DBus"))
487 /* The message came from the kernel, and is sent to our legacy client. */
488 (void) sd_bus_creds_get_well_known_names(&m
->creds
, &sender_names
);
490 (void) sd_bus_creds_get_euid(&m
->creds
, &sender_uid
);
491 (void) sd_bus_creds_get_egid(&m
->creds
, &sender_gid
);
493 if (sender_uid
== UID_INVALID
|| sender_gid
== GID_INVALID
) {
494 _cleanup_bus_creds_unref_ sd_bus_creds
*sender_creds
= NULL
;
496 /* If the message came from another legacy
497 * client, then the message creds will be
498 * missing, simply because on legacy clients
499 * per-message creds were unknown. In this
500 * case, query the creds of the peer
503 r
= bus_get_name_creds_kdbus(from
, m
->sender
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EGID
, true, &sender_creds
);
505 return handle_policy_error(m
, r
);
507 (void) sd_bus_creds_get_euid(sender_creds
, &sender_uid
);
508 (void) sd_bus_creds_get_egid(sender_creds
, &sender_gid
);
511 /* First check whether the sender can send the message to our name */
512 if (policy_check_send(policy
, sender_uid
, sender_gid
, m
->header
->type
, owned_names
, NULL
, m
->path
, m
->interface
, m
->member
, false, NULL
) &&
513 policy_check_recv(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, NULL
, sender_names
, m
->path
, m
->interface
, m
->member
, false))
516 /* Return an error back to the caller */
517 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
518 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML receiver policy.");
520 /* Return 1, indicating that the message shall not be processed any further */
525 _cleanup_bus_creds_unref_ sd_bus_creds
*destination_creds
= NULL
;
526 uid_t destination_uid
= UID_INVALID
;
527 gid_t destination_gid
= GID_INVALID
;
528 const char *destination_unique
= NULL
;
529 char **destination_names
= NULL
;
532 /* Driver messages are always OK */
533 if (streq_ptr(m
->destination
, "org.freedesktop.DBus"))
536 /* The message came from the legacy client, and is sent to kdbus. */
537 if (m
->destination
) {
538 r
= bus_get_name_creds_kdbus(to
, m
->destination
,
539 SD_BUS_CREDS_WELL_KNOWN_NAMES
|SD_BUS_CREDS_UNIQUE_NAME
|
540 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_PID
,
541 true, &destination_creds
);
543 return handle_policy_error(m
, r
);
545 r
= sd_bus_creds_get_unique_name(destination_creds
, &destination_unique
);
547 return handle_policy_error(m
, r
);
549 (void) sd_bus_creds_get_well_known_names(destination_creds
, &destination_names
);
551 (void) sd_bus_creds_get_euid(destination_creds
, &destination_uid
);
552 (void) sd_bus_creds_get_egid(destination_creds
, &destination_gid
);
555 /* First check if we (the sender) can send to this name */
556 if (sd_bus_message_is_signal(m
, NULL
, NULL
)) {
557 /* If we forward a signal from dbus-1 to kdbus, we have
558 * no idea who the recipient is. Therefore, we cannot
559 * apply any dbus-1 policies that match on receiver
560 * credentials. We know sd-bus always sets
561 * KDBUS_MSG_SIGNAL, so the kernel applies policies to
562 * the message. Therefore, skip policy checks in this
565 } 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
)) {
567 /* If we made a receiver decision, then remember which
568 * name's policy we used, and to which unique ID it
569 * mapped when we made the decision. Then, let's pass
570 * this to the kernel when sending the message, so that
571 * it refuses the operation should the name and unique
572 * ID not map to each other anymore. */
574 r
= free_and_strdup(&m
->destination_ptr
, n
);
578 r
= bus_kernel_parse_unique_name(destination_unique
, &m
->verify_destination_id
);
583 if (policy_check_recv(policy
, destination_uid
, destination_gid
, m
->header
->type
, owned_names
, NULL
, m
->path
, m
->interface
, m
->member
, true))
587 /* Return an error back to the caller */
588 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
589 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML sender policy.");
591 /* Return 1, indicating that the message shall not be processed any further */
598 static int process_policy(sd_bus
*from
, sd_bus
*to
, sd_bus_message
*m
, SharedPolicy
*sp
, const struct ucred
*our_ucred
, Set
*owned_names
) {
604 policy
= shared_policy_acquire(sp
);
605 r
= process_policy_unlocked(from
, to
, m
, policy
, our_ucred
, owned_names
);
606 shared_policy_release(sp
, policy
);
611 static int process_hello(Proxy
*p
, sd_bus_message
*m
) {
612 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
619 /* As reaction to hello we need to respond with two messages:
620 * the callback reply and the NameAcquired for the unique
621 * name, since hello is otherwise obsolete on kdbus. */
624 sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "Hello") &&
625 streq_ptr(m
->destination
, "org.freedesktop.DBus");
631 return log_error_errno(EIO
, "First packet isn't hello (it's %s.%s), aborting.", m
->interface
, m
->member
);
635 return log_error_errno(EIO
, "Got duplicate hello, aborting.");
639 if (!p
->destination_bus
->is_kernel
)
642 r
= sd_bus_message_new_method_return(m
, &n
);
644 return log_error_errno(r
, "Failed to generate HELLO reply: %m");
646 r
= sd_bus_message_append(n
, "s", p
->destination_bus
->unique_name
);
648 return log_error_errno(r
, "Failed to append unique name to HELLO reply: %m");
650 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
652 return log_error_errno(r
, "Failed to append sender to HELLO reply: %m");
654 r
= bus_seal_synthetic_message(p
->local_bus
, n
);
656 return log_error_errno(r
, "Failed to seal HELLO reply: %m");
658 r
= sd_bus_send(p
->local_bus
, n
, NULL
);
660 return log_error_errno(r
, "Failed to send HELLO reply: %m");
662 n
= sd_bus_message_unref(n
);
663 r
= sd_bus_message_new_signal(
666 "/org/freedesktop/DBus",
667 "org.freedesktop.DBus",
670 return log_error_errno(r
, "Failed to allocate initial NameAcquired message: %m");
672 r
= sd_bus_message_append(n
, "s", p
->destination_bus
->unique_name
);
674 return log_error_errno(r
, "Failed to append unique name to NameAcquired message: %m");
676 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
678 return log_error_errno(r
, "Failed to append sender to NameAcquired message: %m");
680 r
= sd_bus_message_set_destination(n
, p
->destination_bus
->unique_name
);
682 return log_error_errno(r
, "Failed to set destination for NameAcquired message: %m");
684 r
= bus_seal_synthetic_message(p
->local_bus
, n
);
686 return log_error_errno(r
, "Failed to seal NameAcquired message: %m");
688 r
= sd_bus_send(p
->local_bus
, n
, NULL
);
690 return log_error_errno(r
, "Failed to send NameAcquired message: %m");
695 static int patch_sender(sd_bus
*a
, sd_bus_message
*m
) {
696 char **well_known
= NULL
;
706 /* We will change the sender of messages from the bus driver
707 * so that they originate from the bus driver. This is a
708 * speciality originating from dbus1, where the bus driver did
709 * not have a unique id, but only the well-known name. */
711 c
= sd_bus_message_get_creds(m
);
715 r
= sd_bus_creds_get_well_known_names(c
, &well_known
);
719 if (strv_contains(well_known
, "org.freedesktop.DBus"))
720 m
->sender
= "org.freedesktop.DBus";
725 static int proxy_process_destination_to_local(Proxy
*p
) {
726 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
727 bool matched
, matched_synthetic
;
733 * Usually, we would just take any message that the bus passes to us
734 * and forward it to the local connection. However, there are actually
735 * applications that fail if they receive broadcasts that they didn't
736 * subscribe to. Therefore, we actually emulate a real broadcast
737 * matching here, and discard any broadcasts that weren't matched. Our
738 * match-handlers remembers whether a message was matched by any rule,
739 * by marking it in @p->message_matched.
742 r
= sd_bus_process(p
->destination_bus
, &m
);
744 matched
= p
->message_matched
;
745 matched_synthetic
= p
->synthetic_matched
;
746 p
->message_matched
= false;
747 p
->synthetic_matched
= false;
749 if (r
== -ECONNRESET
|| r
== -ENOTCONN
) /* Treat 'connection reset by peer' as clean exit condition */
752 log_error_errno(r
, "Failed to process destination bus: %m");
760 /* We officially got EOF, let's quit */
761 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected"))
764 r
= synthesize_name_acquired(p
, p
->destination_bus
, p
->local_bus
, m
);
765 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
768 return log_error_errno(r
, "Failed to synthesize message: %m");
770 /* discard broadcasts that were not matched by any MATCH rule */
771 if (!matched
&& !sd_bus_message_get_destination(m
)) {
772 if (!matched_synthetic
)
773 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",
774 p
->local_creds
.uid
, p
->local_creds
.gid
, p
->local_creds
.pid
, bus_message_type_to_string(m
->header
->type
),
775 strna(m
->path
), strna(m
->interface
), strna(m
->member
), strna(m
->sender
), strna(m
->destination
));
779 patch_sender(p
->destination_bus
, m
);
782 r
= process_policy(p
->destination_bus
, p
->local_bus
, m
, p
->policy
, &p
->local_creds
, p
->owned_names
);
783 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
786 return log_error_errno(r
, "Failed to process policy: %m");
791 r
= sd_bus_send(p
->local_bus
, m
, NULL
);
793 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
796 /* If the peer tries to send a reply and it is
797 * rejected with EBADSLT by the kernel, we ignore the
798 * error. This catches cases where the original
799 * method-call didn't had EXPECT_REPLY set, but the
800 * proxy-peer still sends a reply. This is allowed in
801 * dbus1, but not in kdbus. We don't want to track
802 * reply-windows in the proxy, so we simply ignore
803 * EBADSLT for all replies. The only downside is, that
804 * callers are no longer notified if their replies are
805 * dropped. However, this is equivalent to the
806 * caller's timeout to expire, so this should be
807 * acceptable. Nobody sane sends replies without a
808 * matching method-call, so nobody should care. */
810 /* FIXME: remove -EPERM when kdbus is updated */
811 if ((r
== -EPERM
|| r
== -EBADSLT
) && m
->reply_cookie
> 0)
814 /* Return the error to the client, if we can */
815 synthetic_reply_method_errnof(m
, r
, "Failed to forward message we got from destination: %m");
817 /* if local dbus1 peer does not dispatch its queue, warn only once */
818 if (!p
->queue_overflow
)
819 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
);
820 p
->queue_overflow
= true;
823 "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",
824 p
->local_creds
.uid
, p
->local_creds
.gid
, bus_message_type_to_string(m
->header
->type
),
825 strna(m
->destination
), strna(m
->path
), strna(m
->interface
), strna(m
->member
));
830 p
->queue_overflow
= false;
834 static int proxy_process_local_to_destination(Proxy
*p
) {
835 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
840 r
= sd_bus_process(p
->local_bus
, &m
);
841 if (r
== -ECONNRESET
|| r
== -ENOTCONN
) /* Treat 'connection reset by peer' as clean exit condition */
844 log_error_errno(r
, "Failed to process local bus: %m");
852 /* We officially got EOF, let's quit */
853 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected"))
856 r
= process_hello(p
, m
);
857 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
860 return log_error_errno(r
, "Failed to process HELLO: %m");
864 r
= bus_proxy_process_driver(p
, p
->destination_bus
, p
->local_bus
, m
, p
->policy
, &p
->local_creds
, p
->owned_names
);
865 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
868 return log_error_errno(r
, "Failed to process driver calls: %m");
874 r
= process_policy(p
->local_bus
, p
->destination_bus
, m
, p
->policy
, &p
->local_creds
, p
->owned_names
);
875 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
878 return log_error_errno(r
, "Failed to process policy: %m");
883 r
= sd_bus_send(p
->destination_bus
, m
, NULL
);
885 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
888 /* The name database changed since the policy check, hence let's check again */
892 /* see above why EBADSLT is ignored for replies */
893 if ((r
== -EPERM
|| r
== -EBADSLT
) && m
->reply_cookie
> 0)
896 synthetic_reply_method_errnof(m
, r
, "Failed to forward message we got from local: %m");
898 "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",
899 p
->local_creds
.uid
, p
->local_creds
.gid
, bus_message_type_to_string(m
->header
->type
),
900 strna(m
->destination
), strna(m
->path
), strna(m
->interface
), strna(m
->member
));
910 int proxy_match(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
913 p
->message_matched
= true;
914 return 0; /* make sure to continue processing it in further handlers */
917 int proxy_run(Proxy
*p
) {
926 /* Read messages from bus, to pass them on to our client */
927 r
= proxy_process_destination_to_local(p
);
928 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
936 /* Read messages from our client, to pass them on to the bus */
937 r
= proxy_process_local_to_destination(p
);
938 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)
947 if (r
== -ECONNRESET
|| r
== -ENOTCONN
)