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/>.
25 #include <sys/socket.h>
27 #include <sys/types.h>
38 #include "socket-util.h"
39 #include "sd-daemon.h"
41 #include "bus-internal.h"
42 #include "bus-message.h"
47 #include "capability.h"
48 #include "bus-control.h"
49 #include "smack-util.h"
51 #include "bus-xml-policy.h"
54 #include "synthesize.h"
56 static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
57 _cleanup_bus_close_unref_ sd_bus *b = NULL;
62 return log_error_errno(r, "Failed to allocate bus: %m");
64 r = sd_bus_set_description(b, "sd-proxy");
66 return log_error_errno(r, "Failed to set bus name: %m");
68 r = sd_bus_set_address(b, destination);
70 return log_error_errno(r, "Failed to set address to connect to: %m");
72 r = sd_bus_negotiate_fds(b, negotiate_fds);
74 return log_error_errno(r, "Failed to set FD negotiation: %m");
76 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
78 return log_error_errno(r, "Failed to set credential negotiation: %m");
80 if (p->local_creds.pid > 0) {
81 b->fake_pids.pid = p->local_creds.pid;
82 b->fake_pids_valid = true;
84 b->fake_creds.uid = UID_INVALID;
85 b->fake_creds.euid = p->local_creds.uid;
86 b->fake_creds.suid = UID_INVALID;
87 b->fake_creds.fsuid = UID_INVALID;
88 b->fake_creds.gid = GID_INVALID;
89 b->fake_creds.egid = p->local_creds.gid;
90 b->fake_creds.sgid = GID_INVALID;
91 b->fake_creds.fsgid = GID_INVALID;
92 b->fake_creds_valid = true;
96 b->fake_label = strdup(local_sec);
101 b->manual_peer_interface = true;
105 return log_error_errno(r, "Failed to start bus client: %m");
107 p->destination_bus = b;
112 static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fds) {
113 _cleanup_bus_close_unref_ sd_bus *b = NULL;
114 sd_id128_t server_id;
119 return log_error_errno(r, "Failed to allocate bus: %m");
121 r = sd_bus_set_fd(b, in_fd, out_fd);
123 return log_error_errno(r, "Failed to set fds: %m");
125 r = sd_bus_get_bus_id(p->destination_bus, &server_id);
127 return log_error_errno(r, "Failed to get server ID: %m");
129 r = sd_bus_set_server(b, 1, server_id);
131 return log_error_errno(r, "Failed to set server mode: %m");
133 r = sd_bus_negotiate_fds(b, negotiate_fds);
135 return log_error_errno(r, "Failed to set FD negotiation: %m");
137 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
139 return log_error_errno(r, "Failed to set credential negotiation: %m");
141 r = sd_bus_set_anonymous(b, true);
143 return log_error_errno(r, "Failed to set anonymous authentication: %m");
145 b->manual_peer_interface = true;
149 return log_error_errno(r, "Failed to start bus client: %m");
156 static int proxy_prepare_matches(Proxy *p) {
157 _cleanup_free_ char *match = NULL;
161 if (!p->destination_bus->is_kernel)
164 r = sd_bus_get_unique_name(p->destination_bus, &unique);
166 return log_error_errno(r, "Failed to get unique name: %m");
168 match = strjoin("type='signal',"
169 "sender='org.freedesktop.DBus',"
170 "path='/org/freedesktop/DBus',"
171 "interface='org.freedesktop.DBus',"
172 "member='NameOwnerChanged',"
180 r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL);
182 return log_error_errno(r, "Failed to add match for NameLost: %m");
185 match = strjoin("type='signal',"
186 "sender='org.freedesktop.DBus',"
187 "path='/org/freedesktop/DBus',"
188 "interface='org.freedesktop.DBus',"
189 "member='NameOwnerChanged',"
197 r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL);
199 return log_error_errno(r, "Failed to add match for NameAcquired: %m");
204 int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
205 _cleanup_(proxy_freep) Proxy *p = NULL;
206 _cleanup_free_ char *local_sec = NULL;
215 p->local_out = out_fd;
217 p->owned_names = set_new(&string_hash_ops);
221 is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
222 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
225 (void) getpeercred(in_fd, &p->local_creds);
226 (void) getpeersec(in_fd, &local_sec);
229 r = proxy_create_destination(p, destination, local_sec, is_unix);
233 r = proxy_create_local(p, in_fd, out_fd, is_unix);
237 r = proxy_prepare_matches(p);
246 Proxy *proxy_free(Proxy *p) {
250 sd_bus_close_unrefp(&p->local_bus);
251 sd_bus_close_unrefp(&p->destination_bus);
252 set_free_free(p->owned_names);
258 int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
259 _cleanup_strv_free_ char **strv = NULL;
266 /* no need to load legacy policy if destination is not kdbus */
267 if (!p->destination_bus->is_kernel)
272 policy = shared_policy_acquire(sp);
274 /* policy already pre-loaded */
275 shared_policy_release(sp, policy);
279 if (!configuration) {
282 r = sd_bus_get_scope(p->destination_bus, &scope);
284 return log_error_errno(r, "Couldn't determine bus scope: %m");
286 if (streq(scope, "system"))
287 strv = strv_new("/etc/dbus-1/system.conf",
288 "/etc/dbus-1/system.d/",
289 "/etc/dbus-1/system-local.conf",
291 else if (streq(scope, "user"))
292 strv = strv_new("/etc/dbus-1/session.conf",
293 "/etc/dbus-1/session.d/",
294 "/etc/dbus-1/session-local.conf",
297 return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
302 configuration = strv;
305 return shared_policy_preload(sp, configuration);
308 int proxy_hello_policy(Proxy *p, uid_t original_uid) {
317 policy = shared_policy_acquire(p->policy);
319 if (p->local_creds.uid == original_uid)
320 log_debug("Permitting access, since bus owner matches bus client.");
321 else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
322 log_debug("Permitting access due to XML policy.");
324 r = log_error_errno(EPERM, "Policy denied connection.");
326 shared_policy_release(p->policy, policy);
331 static int proxy_wait(Proxy *p) {
332 uint64_t timeout_destination, timeout_local, t;
333 int events_destination, events_local, fd;
334 struct timespec _ts, *ts;
335 struct pollfd *pollfd;
340 fd = sd_bus_get_fd(p->destination_bus);
342 return log_error_errno(fd, "Failed to get fd: %m");
344 events_destination = sd_bus_get_events(p->destination_bus);
345 if (events_destination < 0)
346 return log_error_errno(events_destination, "Failed to get events mask: %m");
348 r = sd_bus_get_timeout(p->destination_bus, &timeout_destination);
350 return log_error_errno(r, "Failed to get timeout: %m");
352 events_local = sd_bus_get_events(p->local_bus);
353 if (events_local < 0)
354 return log_error_errno(events_local, "Failed to get events mask: %m");
356 r = sd_bus_get_timeout(p->local_bus, &timeout_local);
358 return log_error_errno(r, "Failed to get timeout: %m");
360 t = timeout_destination;
361 if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination))
364 if (t == (uint64_t) -1)
369 nw = now(CLOCK_MONOTONIC);
375 ts = timespec_store(&_ts, t);
378 pollfd = (struct pollfd[3]) {
379 { .fd = fd, .events = events_destination, },
380 { .fd = p->local_in, .events = events_local & POLLIN, },
381 { .fd = p->local_out, .events = events_local & POLLOUT, },
384 r = ppoll(pollfd, 3, ts, NULL);
386 return log_error_errno(errno, "ppoll() failed: %m");
391 static int handle_policy_error(sd_bus_message *m, int r) {
392 if (r == -ESRCH || r == -ENXIO)
393 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
398 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) {
409 * dbus-1 distinguishes expected and non-expected replies by tracking
410 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
411 * on expected replies, unless explicitly specified. But we dont track
412 * method-calls, thus, we cannot know whether a reply is expected.
413 * Fortunately, the kdbus forbids non-expected replies, so we can safely
414 * ignore any policy on those and let the kernel deal with it.
416 * TODO: To be correct, we should only ignore policy-tags that are
417 * applied on non-expected replies. However, so far we don't parse those
418 * tags so we let everything pass. I haven't seen a DENY policy tag on
419 * expected-replies, ever, so don't bother..
421 if (m->reply_cookie > 0)
424 if (from->is_kernel) {
425 uid_t sender_uid = UID_INVALID;
426 gid_t sender_gid = GID_INVALID;
427 char **sender_names = NULL;
429 /* Driver messages are always OK */
430 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
433 /* The message came from the kernel, and is sent to our legacy client. */
434 (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
436 (void) sd_bus_creds_get_euid(&m->creds, &sender_uid);
437 (void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
439 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
440 _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
442 /* If the message came from another legacy
443 * client, then the message creds will be
444 * missing, simply because on legacy clients
445 * per-message creds were unknown. In this
446 * case, query the creds of the peer
449 r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
451 return handle_policy_error(m, r);
453 (void) sd_bus_creds_get_euid(sender_creds, &sender_uid);
454 (void) sd_bus_creds_get_egid(sender_creds, &sender_gid);
457 /* First check whether the sender can send the message to our name */
458 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) &&
459 policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false))
462 /* Return an error back to the caller */
463 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
464 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
466 /* Return 1, indicating that the message shall not be processed any further */
471 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
472 uid_t destination_uid = UID_INVALID;
473 gid_t destination_gid = GID_INVALID;
474 const char *destination_unique = NULL;
475 char **destination_names = NULL;
478 /* Driver messages are always OK */
479 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
482 /* The message came from the legacy client, and is sent to kdbus. */
483 if (m->destination) {
484 r = bus_get_name_creds_kdbus(to, m->destination,
485 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
486 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID,
487 true, &destination_creds);
489 return handle_policy_error(m, r);
491 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
493 return handle_policy_error(m, r);
495 (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
497 (void) sd_bus_creds_get_euid(destination_creds, &destination_uid);
498 (void) sd_bus_creds_get_egid(destination_creds, &destination_gid);
501 /* First check if we (the sender) can send to this name */
502 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)) {
504 /* If we made a receiver decision, then remember which
505 * name's policy we used, and to which unique ID it
506 * mapped when we made the decision. Then, let's pass
507 * this to the kernel when sending the message, so that
508 * it refuses the operation should the name and unique
509 * ID not map to each other anymore. */
511 r = free_and_strdup(&m->destination_ptr, n);
515 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
520 if (sd_bus_message_is_signal(m, NULL, NULL)) {
521 /* If we forward a signal from dbus-1 to kdbus,
522 * we have no idea who the recipient is.
523 * Therefore, we cannot apply any dbus-1
524 * receiver policies that match on receiver
525 * credentials. We know sd-bus always sets
526 * KDBUS_MSG_SIGNAL, so the kernel applies
527 * receiver policies to the message. Therefore,
528 * skip policy checks in this case. */
530 } else if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) {
535 /* Return an error back to the caller */
536 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
537 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
539 /* Return 1, indicating that the message shall not be processed any further */
546 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
552 policy = shared_policy_acquire(sp);
553 r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
554 shared_policy_release(sp, policy);
559 static int process_hello(Proxy *p, sd_bus_message *m) {
560 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
567 /* As reaction to hello we need to respond with two messages:
568 * the callback reply and the NameAcquired for the unique
569 * name, since hello is otherwise obsolete on kdbus. */
572 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
573 streq_ptr(m->destination, "org.freedesktop.DBus");
579 return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
583 return log_error_errno(EIO, "Got duplicate hello, aborting.");
587 if (!p->destination_bus->is_kernel)
590 r = sd_bus_message_new_method_return(m, &n);
592 return log_error_errno(r, "Failed to generate HELLO reply: %m");
594 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
596 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
598 r = bus_message_append_sender(n, "org.freedesktop.DBus");
600 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
602 r = bus_seal_synthetic_message(p->local_bus, n);
604 return log_error_errno(r, "Failed to seal HELLO reply: %m");
606 r = sd_bus_send(p->local_bus, n, NULL);
608 return log_error_errno(r, "Failed to send HELLO reply: %m");
610 n = sd_bus_message_unref(n);
611 r = sd_bus_message_new_signal(
614 "/org/freedesktop/DBus",
615 "org.freedesktop.DBus",
618 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
620 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
622 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
624 r = bus_message_append_sender(n, "org.freedesktop.DBus");
626 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
628 r = bus_seal_synthetic_message(p->local_bus, n);
630 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
632 r = sd_bus_send(p->local_bus, n, NULL);
634 return log_error_errno(r, "Failed to send NameAcquired message: %m");
639 static int patch_sender(sd_bus *a, sd_bus_message *m) {
640 char **well_known = NULL;
650 /* We will change the sender of messages from the bus driver
651 * so that they originate from the bus driver. This is a
652 * speciality originating from dbus1, where the bus driver did
653 * not have a unique id, but only the well-known name. */
655 c = sd_bus_message_get_creds(m);
659 r = sd_bus_creds_get_well_known_names(c, &well_known);
663 if (strv_contains(well_known, "org.freedesktop.DBus"))
664 m->sender = "org.freedesktop.DBus";
669 static int proxy_process_destination_to_local(Proxy *p) {
670 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
675 r = sd_bus_process(p->destination_bus, &m);
676 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
679 log_error_errno(r, "Failed to process destination bus: %m");
687 /* We officially got EOF, let's quit */
688 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
691 r = synthesize_name_acquired(p->destination_bus, p->local_bus, m);
692 if (r == -ECONNRESET || r == -ENOTCONN)
695 return log_error_errno(r, "Failed to synthesize message: %m");
697 patch_sender(p->destination_bus, m);
700 r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
701 if (r == -ECONNRESET || r == -ENOTCONN)
704 return log_error_errno(r, "Failed to process policy: %m");
709 r = sd_bus_send(p->local_bus, m, NULL);
711 if (r == -ECONNRESET || r == -ENOTCONN)
714 /* If the peer tries to send a reply and it is
715 * rejected with EPERM by the kernel, we ignore the
716 * error. This catches cases where the original
717 * method-call didn't had EXPECT_REPLY set, but the
718 * proxy-peer still sends a reply. This is allowed in
719 * dbus1, but not in kdbus. We don't want to track
720 * reply-windows in the proxy, so we simply ignore
721 * EPERM for all replies. The only downside is, that
722 * callers are no longer notified if their replies are
723 * dropped. However, this is equivalent to the
724 * caller's timeout to expire, so this should be
725 * acceptable. Nobody sane sends replies without a
726 * matching method-call, so nobody should care. */
727 if (r == -EPERM && m->reply_cookie > 0)
730 /* Return the error to the client, if we can */
731 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m");
733 "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",
734 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
735 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
742 static int proxy_process_local_to_destination(Proxy *p) {
743 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
748 r = sd_bus_process(p->local_bus, &m);
749 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
752 log_error_errno(r, "Failed to process local 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 = process_hello(p, m);
765 if (r == -ECONNRESET || r == -ENOTCONN)
768 return log_error_errno(r, "Failed to process HELLO: %m");
772 r = bus_proxy_process_driver(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
773 if (r == -ECONNRESET || r == -ENOTCONN)
776 return log_error_errno(r, "Failed to process driver calls: %m");
782 r = process_policy(p->local_bus, p->destination_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->destination_bus, m, NULL);
793 if (r == -ECONNRESET || r == -ENOTCONN)
796 /* The name database changed since the policy check, hence let's check again */
800 /* see above why EPERM is ignored for replies */
801 if (r == -EPERM && m->reply_cookie > 0)
804 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
806 "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",
807 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
808 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
818 int proxy_run(Proxy *p) {
827 /* Read messages from bus, to pass them on to our client */
828 r = proxy_process_destination_to_local(p);
829 if (r == -ECONNRESET || r == -ENOTCONN)
837 /* Read messages from our client, to pass them on to the bus */
838 r = proxy_process_local_to_destination(p);
839 if (r == -ECONNRESET || r == -ENOTCONN)
848 if (r == -ECONNRESET || r == -ENOTCONN)