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
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/socket.h>
26 #include <sys/types.h>
37 #include "socket-util.h"
38 #include "sd-daemon.h"
40 #include "bus-internal.h"
41 #include "bus-message.h"
46 #include "capability.h"
47 #include "bus-control.h"
48 #include "smack-util.h"
50 #include "bus-xml-policy.h"
52 static char *arg_address
= NULL
;
53 static char *arg_command_line_buffer
= NULL
;
54 static bool arg_drop_privileges
= false;
55 static char **arg_configuration
= NULL
;
57 static int help(void) {
59 printf("%s [OPTIONS...]\n\n"
60 "Connect STDIO or a socket to a given bus address.\n\n"
61 " -h --help Show this help\n"
62 " --version Show package version\n"
63 " --drop-privileges Drop privileges\n"
64 " --configuration=PATH Configuration file or directory\n"
65 " --machine=MACHINE Connect to specified machine\n"
66 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
67 " (default: " DEFAULT_SYSTEM_BUS_ADDRESS
")\n",
68 program_invocation_short_name
);
73 static int parse_argv(int argc
, char *argv
[]) {
83 static const struct option options
[] = {
84 { "help", no_argument
, NULL
, 'h' },
85 { "version", no_argument
, NULL
, ARG_VERSION
},
86 { "address", required_argument
, NULL
, ARG_ADDRESS
},
87 { "drop-privileges", no_argument
, NULL
, ARG_DROP_PRIVILEGES
},
88 { "configuration", required_argument
, NULL
, ARG_CONFIGURATION
},
89 { "machine", required_argument
, NULL
, ARG_MACHINE
},
98 while ((c
= getopt_long(argc
, argv
, "h", options
, NULL
)) >= 0)
107 puts(PACKAGE_STRING
);
108 puts(SYSTEMD_FEATURES
);
123 case ARG_DROP_PRIVILEGES
:
124 arg_drop_privileges
= true;
127 case ARG_CONFIGURATION
:
128 r
= strv_extend(&arg_configuration
, optarg
);
134 _cleanup_free_
char *e
= NULL
;
137 e
= bus_address_escape(optarg
);
142 a
= strjoin("x-machine-kernel:machine=", e
, ";x-machine-unix:machine=", e
, NULL
);
144 a
= strjoin("x-machine-unix:machine=", e
, NULL
);
159 assert_not_reached("Unhandled option");
162 /* If the first command line argument is only "x" characters
163 * we'll write who we are talking to into it, so that "ps" is
165 arg_command_line_buffer
= argv
[optind
];
166 if (argc
> optind
+ 1 || (arg_command_line_buffer
&& !in_charset(arg_command_line_buffer
, "x"))) {
167 log_error("Too many arguments");
172 arg_address
= strdup(DEFAULT_SYSTEM_BUS_ADDRESS
);
180 static int rename_service(sd_bus
*a
, sd_bus
*b
) {
181 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
182 _cleanup_free_
char *p
= NULL
, *name
= NULL
;
192 r
= sd_bus_get_owner_creds(b
, SD_BUS_CREDS_UID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_CMDLINE
|SD_BUS_CREDS_COMM
|SD_BUS_CREDS_AUGMENT
, &creds
);
196 r
= sd_bus_creds_get_uid(creds
, &uid
);
200 r
= sd_bus_creds_get_pid(creds
, &pid
);
204 r
= sd_bus_creds_get_cmdline(creds
, &cmdline
);
208 r
= sd_bus_creds_get_comm(creds
, &comm
);
212 name
= uid_to_name(uid
);
216 p
= strv_join(cmdline
, " ");
220 /* The status string gets the full command line ... */
222 "STATUS=Processing requests from client PID "PID_FMT
" (%s); UID "UID_FMT
" (%s)",
226 /* ... and the argv line only the short comm */
227 if (arg_command_line_buffer
) {
230 m
= strlen(arg_command_line_buffer
);
231 w
= snprintf(arg_command_line_buffer
, m
,
232 "[PID "PID_FMT
"/%s; UID "UID_FMT
"/%s]",
237 memzero(arg_command_line_buffer
+ w
, m
- w
);
240 log_debug("Running on behalf of PID "PID_FMT
" (%s), UID "UID_FMT
" (%s), %s",
248 static int synthesize_name_acquired(sd_bus
*a
, sd_bus
*b
, sd_bus_message
*m
) {
249 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
250 const char *name
, *old_owner
, *new_owner
;
257 /* If we get NameOwnerChanged for our own name, we need to
258 * synthesize NameLost/NameAcquired, since socket clients need
259 * that, even though it is obsoleted on kdbus */
264 if (!sd_bus_message_is_signal(m
, "org.freedesktop.DBus", "NameOwnerChanged") ||
265 !streq_ptr(m
->path
, "/org/freedesktop/DBus") ||
266 !streq_ptr(m
->sender
, "org.freedesktop.DBus"))
269 r
= sd_bus_message_read(m
, "sss", &name
, &old_owner
, &new_owner
);
273 r
= sd_bus_message_rewind(m
, true);
277 if (streq(old_owner
, a
->unique_name
)) {
279 r
= sd_bus_message_new_signal(
282 "/org/freedesktop/DBus",
283 "org.freedesktop.DBus",
286 } else if (streq(new_owner
, a
->unique_name
)) {
288 r
= sd_bus_message_new_signal(
291 "/org/freedesktop/DBus",
292 "org.freedesktop.DBus",
300 r
= sd_bus_message_append(n
, "s", name
);
304 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
308 r
= bus_seal_synthetic_message(b
, n
);
312 return sd_bus_send(b
, n
, NULL
);
315 static int synthetic_driver_send(sd_bus
*b
, sd_bus_message
*m
) {
321 r
= bus_message_append_sender(m
, "org.freedesktop.DBus");
325 r
= bus_seal_synthetic_message(b
, m
);
329 return sd_bus_send(b
, m
, NULL
);
332 static int synthetic_reply_method_error(sd_bus_message
*call
, const sd_bus_error
*e
) {
333 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
338 if (call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)
341 r
= sd_bus_message_new_method_error(call
, &m
, e
);
345 return synthetic_driver_send(call
->bus
, m
);
348 static int synthetic_reply_method_errorf(sd_bus_message
*call
, const char *name
, const char *format
, ...) {
349 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
352 va_start(ap
, format
);
353 bus_error_setfv(&error
, name
, format
, ap
);
356 return synthetic_reply_method_error(call
, &error
);
359 static int synthetic_reply_method_errno(sd_bus_message
*call
, int error
, const sd_bus_error
*p
) {
361 _cleanup_bus_error_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
365 if (call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)
368 if (sd_bus_error_is_set(p
))
369 return synthetic_reply_method_error(call
, p
);
371 sd_bus_error_set_errno(&berror
, error
);
373 return synthetic_reply_method_error(call
, &berror
);
376 static int synthetic_reply_method_return(sd_bus_message
*call
, const char *types
, ...) {
377 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
382 if (call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)
385 r
= sd_bus_message_new_method_return(call
, &m
);
389 if (!isempty(types
)) {
393 r
= bus_message_append_ap(m
, types
, ap
);
399 return synthetic_driver_send(call
->bus
, m
);
402 static int synthetic_reply_return_strv(sd_bus_message
*call
, char **l
) {
403 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
408 if (call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)
411 r
= sd_bus_message_new_method_return(call
, &m
);
413 return synthetic_reply_method_errno(call
, r
, NULL
);
415 r
= sd_bus_message_append_strv(m
, l
);
417 return synthetic_reply_method_errno(call
, r
, NULL
);
419 return synthetic_driver_send(call
->bus
, m
);
422 static int get_creds_by_name(sd_bus
*bus
, const char *name
, uint64_t mask
, sd_bus_creds
**_creds
, sd_bus_error
*error
) {
423 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
430 r
= sd_bus_get_name_creds(bus
, name
, mask
, &c
);
431 if (r
== -ESRCH
|| r
== -ENXIO
)
432 return sd_bus_error_setf(error
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Name %s is currently not owned by anyone.", name
);
436 if ((c
->mask
& mask
) != mask
)
445 static int get_creds_by_message(sd_bus
*bus
, sd_bus_message
*m
, uint64_t mask
, sd_bus_creds
**_creds
, sd_bus_error
*error
) {
453 r
= sd_bus_message_read(m
, "s", &name
);
457 return get_creds_by_name(bus
, name
, mask
, _creds
, error
);
460 static int process_driver(sd_bus
*a
, sd_bus
*b
, sd_bus_message
*m
, Policy
*policy
, const struct ucred
*ucred
, Set
*owned_names
) {
470 if (!streq_ptr(sd_bus_message_get_destination(m
), "org.freedesktop.DBus"))
473 /* The "Hello()" call is is handled in process_hello() */
475 if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus.Introspectable", "Introspect")) {
477 if (!sd_bus_message_has_signature(m
, ""))
478 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
480 return synthetic_reply_method_return(m
, "s",
481 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
482 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
484 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
485 " <method name=\"Introspect\">\n"
486 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
489 " <interface name=\"org.freedesktop.DBus\">\n"
490 " <method name=\"AddMatch\">\n"
491 " <arg type=\"s\" direction=\"in\"/>\n"
493 " <method name=\"RemoveMatch\">\n"
494 " <arg type=\"s\" direction=\"in\"/>\n"
496 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
497 " <arg type=\"s\" direction=\"in\"/>\n"
498 " <arg type=\"ay\" direction=\"out\"/>\n"
500 " <method name=\"GetConnectionUnixProcessID\">\n"
501 " <arg type=\"s\" direction=\"in\"/>\n"
502 " <arg type=\"u\" direction=\"out\"/>\n"
504 " <method name=\"GetConnectionUnixUser\">\n"
505 " <arg type=\"s\" direction=\"in\"/>\n"
506 " <arg type=\"u\" direction=\"out\"/>\n"
508 " <method name=\"GetId\">\n"
509 " <arg type=\"s\" direction=\"out\"/>\n"
511 " <method name=\"GetNameOwner\">\n"
512 " <arg type=\"s\" direction=\"in\"/>\n"
513 " <arg type=\"s\" direction=\"out\"/>\n"
515 " <method name=\"Hello\">\n"
516 " <arg type=\"s\" direction=\"out\"/>\n"
518 " <method name=\"ListActivatableNames\">\n"
519 " <arg type=\"as\" direction=\"out\"/>\n"
521 " <method name=\"ListNames\">\n"
522 " <arg type=\"as\" direction=\"out\"/>\n"
524 " <method name=\"ListQueuedOwners\">\n"
525 " <arg type=\"s\" direction=\"in\"/>\n"
526 " <arg type=\"as\" direction=\"out\"/>\n"
528 " <method name=\"NameHasOwner\">\n"
529 " <arg type=\"s\" direction=\"in\"/>\n"
530 " <arg type=\"b\" direction=\"out\"/>\n"
532 " <method name=\"ReleaseName\">\n"
533 " <arg type=\"s\" direction=\"in\"/>\n"
534 " <arg type=\"u\" direction=\"out\"/>\n"
536 " <method name=\"ReloadConfig\">\n"
538 " <method name=\"RequestName\">\n"
539 " <arg type=\"s\" direction=\"in\"/>\n"
540 " <arg type=\"u\" direction=\"in\"/>\n"
541 " <arg type=\"u\" direction=\"out\"/>\n"
543 " <method name=\"StartServiceByName\">\n"
544 " <arg type=\"s\" direction=\"in\"/>\n"
545 " <arg type=\"u\" direction=\"in\"/>\n"
546 " <arg type=\"u\" direction=\"out\"/>\n"
548 " <method name=\"UpdateActivationEnvironment\">\n"
549 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
551 " <signal name=\"NameAcquired\">\n"
552 " <arg type=\"s\"/>\n"
554 " <signal name=\"NameLost\">\n"
555 " <arg type=\"s\"/>\n"
557 " <signal name=\"NameOwnerChanged\">\n"
558 " <arg type=\"s\"/>\n"
559 " <arg type=\"s\"/>\n"
560 " <arg type=\"s\"/>\n"
565 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "AddMatch")) {
568 if (!sd_bus_message_has_signature(m
, "s"))
569 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
571 r
= sd_bus_message_read(m
, "s", &match
);
573 return synthetic_reply_method_errno(m
, r
, NULL
);
575 r
= sd_bus_add_match(a
, NULL
, match
, NULL
, NULL
);
577 return synthetic_reply_method_errno(m
, r
, NULL
);
579 return synthetic_reply_method_return(m
, NULL
);
581 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "RemoveMatch")) {
584 if (!sd_bus_message_has_signature(m
, "s"))
585 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
587 r
= sd_bus_message_read(m
, "s", &match
);
589 return synthetic_reply_method_errno(m
, r
, NULL
);
591 r
= bus_remove_match_by_string(a
, match
, NULL
, NULL
);
593 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND
, "Match rule not found"));
595 return synthetic_reply_method_errno(m
, r
, NULL
);
597 return synthetic_reply_method_return(m
, NULL
);
599 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
600 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
601 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
603 if (!sd_bus_message_has_signature(m
, "s"))
604 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
606 r
= get_creds_by_message(a
, m
, SD_BUS_CREDS_SELINUX_CONTEXT
, &creds
, &error
);
608 return synthetic_reply_method_errno(m
, r
, &error
);
610 return synthetic_reply_method_return(m
, "y", creds
->label
, strlen(creds
->label
));
612 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
613 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
614 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
616 if (!sd_bus_message_has_signature(m
, "s"))
617 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
619 r
= get_creds_by_message(a
, m
, SD_BUS_CREDS_PID
, &creds
, &error
);
621 return synthetic_reply_method_errno(m
, r
, &error
);
623 return synthetic_reply_method_return(m
, "u", (uint32_t) creds
->pid
);
625 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
626 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
627 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
629 if (!sd_bus_message_has_signature(m
, "s"))
630 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
632 r
= get_creds_by_message(a
, m
, SD_BUS_CREDS_UID
, &creds
, &error
);
634 return synthetic_reply_method_errno(m
, r
, &error
);
636 return synthetic_reply_method_return(m
, "u", (uint32_t) creds
->uid
);
638 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetId")) {
639 sd_id128_t server_id
;
640 char buf
[SD_ID128_STRING_MAX
];
642 if (!sd_bus_message_has_signature(m
, ""))
643 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
645 r
= sd_bus_get_bus_id(a
, &server_id
);
647 return synthetic_reply_method_errno(m
, r
, NULL
);
649 return synthetic_reply_method_return(m
, "s", sd_id128_to_string(server_id
, buf
));
651 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetNameOwner")) {
653 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
654 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
656 if (!sd_bus_message_has_signature(m
, "s"))
657 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
659 r
= sd_bus_message_read(m
, "s", &name
);
661 return synthetic_reply_method_errno(m
, r
, NULL
);
663 if (streq(name
, "org.freedesktop.DBus"))
664 return synthetic_reply_method_return(m
, "s", "org.freedesktop.DBus");
666 r
= get_creds_by_name(a
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
, &error
);
668 return synthetic_reply_method_errno(m
, r
, &error
);
670 return synthetic_reply_method_return(m
, "s", creds
->unique_name
);
672 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ListActivatableNames")) {
673 _cleanup_strv_free_
char **names
= NULL
;
675 if (!sd_bus_message_has_signature(m
, ""))
676 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
678 r
= sd_bus_list_names(a
, NULL
, &names
);
680 return synthetic_reply_method_errno(m
, r
, NULL
);
682 /* Let's sort the names list to make it stable */
685 return synthetic_reply_return_strv(m
, names
);
687 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ListNames")) {
688 _cleanup_strv_free_
char **names
= NULL
;
690 if (!sd_bus_message_has_signature(m
, ""))
691 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
693 r
= sd_bus_list_names(a
, &names
, NULL
);
695 return synthetic_reply_method_errno(m
, r
, NULL
);
697 r
= strv_extend(&names
, "org.freedesktop.DBus");
699 return synthetic_reply_method_errno(m
, r
, NULL
);
701 /* Let's sort the names list to make it stable */
704 return synthetic_reply_return_strv(m
, names
);
706 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ListQueuedOwners")) {
707 struct kdbus_cmd_name_list cmd
= {};
708 struct kdbus_name_list
*name_list
;
709 struct kdbus_name_info
*name
;
710 _cleanup_strv_free_
char **owners
= NULL
;
711 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
715 if (!sd_bus_message_has_signature(m
, "s"))
716 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
718 r
= sd_bus_message_read(m
, "s", &arg0
);
720 return synthetic_reply_method_errno(m
, r
, NULL
);
722 r
= sd_bus_get_name_creds(a
, arg0
, 0, NULL
);
723 if (r
== -ESRCH
|| r
== -ENXIO
) {
724 sd_bus_error_setf(&error
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Could not get owners of name '%s': no such name.", arg0
);
725 return synthetic_reply_method_errno(m
, r
, &error
);
728 return synthetic_reply_method_errno(m
, r
, NULL
);
730 cmd
.flags
= KDBUS_NAME_LIST_QUEUED
;
731 r
= ioctl(a
->input_fd
, KDBUS_CMD_NAME_LIST
, &cmd
);
733 return synthetic_reply_method_errno(m
, -errno
, NULL
);
735 name_list
= (struct kdbus_name_list
*) ((uint8_t *) a
->kdbus_buffer
+ cmd
.offset
);
737 KDBUS_ITEM_FOREACH(name
, name_list
, names
) {
738 const char *entry_name
= NULL
;
739 struct kdbus_item
*item
;
742 KDBUS_ITEM_FOREACH(item
, name
, items
)
743 if (item
->type
== KDBUS_ITEM_OWNED_NAME
)
744 entry_name
= item
->name
.name
;
746 if (!streq_ptr(entry_name
, arg0
))
749 if (asprintf(&n
, ":1.%llu", (unsigned long long) name
->owner_id
) < 0) {
754 r
= strv_consume(&owners
, n
);
761 r
= bus_kernel_cmd_free(a
, cmd
.offset
);
763 return synthetic_reply_method_errno(m
, r
, NULL
);
766 return synthetic_reply_method_errno(m
, err
, NULL
);
768 return synthetic_reply_return_strv(m
, owners
);
770 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "NameHasOwner")) {
773 if (!sd_bus_message_has_signature(m
, "s"))
774 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
776 r
= sd_bus_message_read(m
, "s", &name
);
778 return synthetic_reply_method_errno(m
, r
, NULL
);
780 if (streq(name
, "org.freedesktop.DBus"))
781 return synthetic_reply_method_return(m
, "b", true);
783 r
= sd_bus_get_name_creds(a
, name
, 0, NULL
);
784 if (r
< 0 && r
!= -ESRCH
&& r
!= -ENXIO
)
785 return synthetic_reply_method_errno(m
, r
, NULL
);
787 return synthetic_reply_method_return(m
, "b", r
>= 0);
789 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ReleaseName")) {
792 if (!sd_bus_message_has_signature(m
, "s"))
793 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
795 r
= sd_bus_message_read(m
, "s", &name
);
797 return synthetic_reply_method_errno(m
, r
, NULL
);
799 r
= sd_bus_release_name(a
, name
);
802 return synthetic_reply_method_return(m
, "u", BUS_NAME_NON_EXISTENT
);
803 if (r
== -EADDRINUSE
)
804 return synthetic_reply_method_return(m
, "u", BUS_NAME_NOT_OWNER
);
806 return synthetic_reply_method_errno(m
, r
, NULL
);
809 set_remove(owned_names
, (char*) name
);
811 return synthetic_reply_method_return(m
, "u", BUS_NAME_RELEASED
);
813 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ReloadConfig")) {
814 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
816 if (!sd_bus_message_has_signature(m
, ""))
817 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
819 r
= sd_bus_error_setf(&error
, SD_BUS_ERROR_NOT_SUPPORTED
, "%s() is not supported", sd_bus_message_get_member(m
));
821 return synthetic_reply_method_errno(m
, r
, &error
);
823 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "RequestName")) {
825 uint32_t flags
, param
;
828 if (!sd_bus_message_has_signature(m
, "su"))
829 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
831 r
= sd_bus_message_read(m
, "su", &name
, &flags
);
833 return synthetic_reply_method_errno(m
, r
, NULL
);
835 if (policy
&& !policy_check_own(policy
, ucred
->uid
, ucred
->gid
, name
))
836 return synthetic_reply_method_errno(m
, -EPERM
, NULL
);
838 if ((flags
& ~(BUS_NAME_ALLOW_REPLACEMENT
|BUS_NAME_REPLACE_EXISTING
|BUS_NAME_DO_NOT_QUEUE
)) != 0)
839 return synthetic_reply_method_errno(m
, -EINVAL
, NULL
);
842 if (flags
& BUS_NAME_ALLOW_REPLACEMENT
)
843 param
|= SD_BUS_NAME_ALLOW_REPLACEMENT
;
844 if (flags
& BUS_NAME_REPLACE_EXISTING
)
845 param
|= SD_BUS_NAME_REPLACE_EXISTING
;
846 if (!(flags
& BUS_NAME_DO_NOT_QUEUE
))
847 param
|= SD_BUS_NAME_QUEUE
;
849 r
= set_put_strdup(owned_names
, name
);
851 return synthetic_reply_method_errno(m
, r
, NULL
);
853 r
= sd_bus_request_name(a
, name
, param
);
856 return synthetic_reply_method_return(m
, "u", BUS_NAME_ALREADY_OWNER
);
858 set_remove(owned_names
, (char*) name
);
861 return synthetic_reply_method_return(m
, "u", BUS_NAME_EXISTS
);
862 return synthetic_reply_method_errno(m
, r
, NULL
);
868 return synthetic_reply_method_return(m
, "u", BUS_NAME_IN_QUEUE
);
870 return synthetic_reply_method_return(m
, "u", BUS_NAME_PRIMARY_OWNER
);
872 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "StartServiceByName")) {
873 _cleanup_bus_message_unref_ sd_bus_message
*msg
= NULL
;
877 if (!sd_bus_message_has_signature(m
, "su"))
878 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
880 r
= sd_bus_message_read(m
, "su", &name
, &flags
);
882 return synthetic_reply_method_errno(m
, r
, NULL
);
885 return synthetic_reply_method_errno(m
, -EINVAL
, NULL
);
887 r
= sd_bus_get_name_creds(a
, name
, 0, NULL
);
888 if (r
>= 0 || streq(name
, "org.freedesktop.DBus"))
889 return synthetic_reply_method_return(m
, "u", BUS_START_REPLY_ALREADY_RUNNING
);
891 return synthetic_reply_method_errno(m
, r
, NULL
);
893 r
= sd_bus_message_new_method_call(
898 "org.freedesktop.DBus.Peer",
901 return synthetic_reply_method_errno(m
, r
, NULL
);
903 r
= sd_bus_send(a
, msg
, NULL
);
905 return synthetic_reply_method_errno(m
, r
, NULL
);
907 return synthetic_reply_method_return(m
, "u", BUS_START_REPLY_SUCCESS
);
909 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
910 _cleanup_bus_message_unref_ sd_bus_message
*msg
= NULL
;
911 _cleanup_strv_free_
char **args
= NULL
;
913 if (!sd_bus_message_has_signature(m
, "a{ss}"))
914 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
916 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{ss}");
918 return synthetic_reply_method_errno(m
, r
, NULL
);
920 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "ss")) > 0) {
921 _cleanup_free_
char *s
= NULL
;
925 r
= sd_bus_message_read(m
, "ss", &key
, &value
);
927 return synthetic_reply_method_errno(m
, r
, NULL
);
929 s
= strjoin(key
, "=", value
, NULL
);
931 return synthetic_reply_method_errno(m
, -ENOMEM
, NULL
);
933 r
= strv_extend(&args
, s
);
935 return synthetic_reply_method_errno(m
, r
, NULL
);
937 r
= sd_bus_message_exit_container(m
);
939 return synthetic_reply_method_errno(m
, r
, NULL
);
942 r
= sd_bus_message_exit_container(m
);
944 return synthetic_reply_method_errno(m
, r
, NULL
);
947 return synthetic_reply_method_errno(m
, -EINVAL
, NULL
);
949 r
= sd_bus_message_new_method_call(
952 "org.freedesktop.systemd1",
953 "/org/freedesktop/systemd1",
954 "org.freedesktop.systemd1.Manager",
957 return synthetic_reply_method_errno(m
, r
, NULL
);
959 r
= sd_bus_message_append_strv(msg
, args
);
961 return synthetic_reply_method_errno(m
, r
, NULL
);
963 r
= sd_bus_call(a
, msg
, 0, NULL
, NULL
);
965 return synthetic_reply_method_errno(m
, r
, NULL
);
967 return synthetic_reply_method_return(m
, NULL
);
970 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
972 r
= sd_bus_error_setf(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
, "Unknown method '%s'.", m
->member
);
974 return synthetic_reply_method_errno(m
, r
, &error
);
978 static int handle_policy_error(sd_bus_message
*m
, int r
) {
979 if (r
== -ESRCH
|| r
== -ENXIO
)
980 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Name %s is currently not owned by anyone.", m
->destination
);
985 static int process_policy(sd_bus
*from
, sd_bus
*to
, sd_bus_message
*m
, Policy
*policy
, const struct ucred
*our_ucred
, Set
*owned_names
) {
996 * dbus-1 distinguishes expected and non-expected replies by tracking
997 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
998 * on expected replies, unless explicitly specified. But we dont track
999 * method-calls, thus, we cannot know whether a reply is expected.
1000 * Fortunately, the kdbus forbids non-expected replies, so we can safely
1001 * ignore any policy on those and let the kernel deal with it.
1003 * TODO: To be correct, we should only ignore policy-tags that are
1004 * applied on non-expected replies. However, so far we don't parse those
1005 * tags so we let everything pass. I haven't seen a DENY policy tag on
1006 * expected-replies, ever, so don't bother..
1008 if (m
->reply_cookie
> 0)
1011 if (from
->is_kernel
) {
1012 uid_t sender_uid
= UID_INVALID
;
1013 gid_t sender_gid
= GID_INVALID
;
1014 char **sender_names
= NULL
;
1015 bool granted
= false;
1017 /* Driver messages are always OK */
1018 if (streq_ptr(m
->sender
, "org.freedesktop.DBus"))
1021 /* The message came from the kernel, and is sent to our legacy client. */
1022 sd_bus_creds_get_well_known_names(&m
->creds
, &sender_names
);
1024 (void) sd_bus_creds_get_uid(&m
->creds
, &sender_uid
);
1025 (void) sd_bus_creds_get_gid(&m
->creds
, &sender_gid
);
1027 if (sender_uid
== UID_INVALID
|| sender_gid
== GID_INVALID
) {
1028 _cleanup_bus_creds_unref_ sd_bus_creds
*sender_creds
= NULL
;
1030 /* If the message came from another legacy
1031 * client, then the message creds will be
1032 * missing, simply because on legacy clients
1033 * per-message creds were unknown. In this
1034 * case, query the creds of the peer
1037 r
= bus_get_name_creds_kdbus(from
, m
->sender
, SD_BUS_CREDS_UID
|SD_BUS_CREDS_GID
, true, &sender_creds
);
1039 return handle_policy_error(m
, r
);
1041 (void) sd_bus_creds_get_uid(sender_creds
, &sender_uid
);
1042 (void) sd_bus_creds_get_gid(sender_creds
, &sender_gid
);
1045 /* First check whether the sender can send the message to our name */
1046 if (set_isempty(owned_names
)) {
1047 if (policy_check_send(policy
, sender_uid
, sender_gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
, false))
1053 SET_FOREACH(n
, owned_names
, i
)
1054 if (policy_check_send(policy
, sender_uid
, sender_gid
, m
->header
->type
, n
, m
->path
, m
->interface
, m
->member
, false)) {
1061 /* Then check whether us (the recipient) can receive from the sender's name */
1062 if (strv_isempty(sender_names
)) {
1063 if (policy_check_recv(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
, false))
1068 STRV_FOREACH(n
, sender_names
) {
1069 if (policy_check_recv(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, *n
, m
->path
, m
->interface
, m
->member
, false))
1075 /* Return an error back to the caller */
1076 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1077 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML receiver policy.");
1079 /* Return 1, indicating that the message shall not be processed any further */
1083 if (to
->is_kernel
) {
1084 _cleanup_bus_creds_unref_ sd_bus_creds
*destination_creds
= NULL
;
1085 uid_t destination_uid
= UID_INVALID
;
1086 gid_t destination_gid
= GID_INVALID
;
1087 const char *destination_unique
= NULL
;
1088 char **destination_names
= NULL
;
1089 bool granted
= false;
1091 /* Driver messages are always OK */
1092 if (streq_ptr(m
->destination
, "org.freedesktop.DBus"))
1095 /* The message came from the legacy client, and is sent to kdbus. */
1096 if (m
->destination
) {
1097 r
= bus_get_name_creds_kdbus(to
, m
->destination
,
1098 SD_BUS_CREDS_WELL_KNOWN_NAMES
|SD_BUS_CREDS_UNIQUE_NAME
|
1099 SD_BUS_CREDS_UID
|SD_BUS_CREDS_GID
|SD_BUS_CREDS_PID
,
1100 true, &destination_creds
);
1102 return handle_policy_error(m
, r
);
1104 r
= sd_bus_creds_get_unique_name(destination_creds
, &destination_unique
);
1106 return handle_policy_error(m
, r
);
1108 sd_bus_creds_get_well_known_names(destination_creds
, &destination_names
);
1110 (void) sd_bus_creds_get_uid(destination_creds
, &destination_uid
);
1111 (void) sd_bus_creds_get_gid(destination_creds
, &destination_gid
);
1114 /* First check if we (the sender) can send to this name */
1115 if (strv_isempty(destination_names
)) {
1116 if (policy_check_send(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
, true))
1121 STRV_FOREACH(n
, destination_names
) {
1122 if (policy_check_send(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, *n
, m
->path
, m
->interface
, m
->member
, true)) {
1124 /* If we made a receiver decision,
1125 then remember which name's policy
1126 we used, and to which unique ID it
1127 mapped when we made the
1128 decision. Then, let's pass this to
1129 the kernel when sending the
1130 message, so that it refuses the
1131 operation should the name and
1132 unique ID not map to each other
1135 r
= free_and_strdup(&m
->destination_ptr
, *n
);
1139 r
= bus_kernel_parse_unique_name(destination_unique
, &m
->verify_destination_id
);
1149 /* Then check if the recipient can receive from our name */
1151 if (sd_bus_message_is_signal(m
, NULL
, NULL
)) {
1152 /* If we forward a signal from dbus-1 to kdbus,
1153 * we have no idea who the recipient is.
1154 * Therefore, we cannot apply any dbus-1
1155 * receiver policies that match on receiver
1156 * credentials. We know sd-bus always sets
1157 * KDBUS_MSG_SIGNAL, so the kernel applies
1158 * receiver policies to the message. Therefore,
1159 * skip policy checks in this case. */
1161 } else if (set_isempty(owned_names
)) {
1162 if (policy_check_recv(policy
, destination_uid
, destination_gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
, true))
1168 SET_FOREACH(n
, owned_names
, i
)
1169 if (policy_check_recv(policy
, destination_uid
, destination_gid
, m
->header
->type
, n
, m
->path
, m
->interface
, m
->member
, true))
1174 /* Return an error back to the caller */
1175 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1176 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML sender policy.");
1178 /* Return 1, indicating that the message shall not be processed any further */
1185 static int process_hello(sd_bus
*a
, sd_bus
*b
, sd_bus_message
*m
, bool *got_hello
) {
1186 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
1195 /* As reaction to hello we need to respond with two messages:
1196 * the callback reply and the NameAcquired for the unique
1197 * name, since hello is otherwise obsolete on kdbus. */
1200 sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "Hello") &&
1201 streq_ptr(m
->destination
, "org.freedesktop.DBus");
1208 log_error("First packet isn't hello (it's %s.%s), aborting.", m
->interface
, m
->member
);
1213 log_error("Got duplicate hello, aborting.");
1222 r
= sd_bus_message_new_method_return(m
, &n
);
1224 return log_error_errno(r
, "Failed to generate HELLO reply: %m");
1226 r
= sd_bus_message_append(n
, "s", a
->unique_name
);
1228 return log_error_errno(r
, "Failed to append unique name to HELLO reply: %m");
1230 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
1232 return log_error_errno(r
, "Failed to append sender to HELLO reply: %m");
1234 r
= bus_seal_synthetic_message(b
, n
);
1236 return log_error_errno(r
, "Failed to seal HELLO reply: %m");
1238 r
= sd_bus_send(b
, n
, NULL
);
1240 return log_error_errno(r
, "Failed to send HELLO reply: %m");
1242 n
= sd_bus_message_unref(n
);
1243 r
= sd_bus_message_new_signal(
1246 "/org/freedesktop/DBus",
1247 "org.freedesktop.DBus",
1250 return log_error_errno(r
, "Failed to allocate initial NameAcquired message: %m");
1252 r
= sd_bus_message_append(n
, "s", a
->unique_name
);
1254 return log_error_errno(r
, "Failed to append unique name to NameAcquired message: %m");
1256 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
1258 return log_error_errno(r
, "Failed to append sender to NameAcquired message: %m");
1260 r
= bus_seal_synthetic_message(b
, n
);
1262 return log_error_errno(r
, "Failed to seal NameAcquired message: %m");
1264 r
= sd_bus_send(b
, n
, NULL
);
1266 return log_error_errno(r
, "Failed to send NameAcquired message: %m");
1271 static int patch_sender(sd_bus
*a
, sd_bus_message
*m
) {
1272 char **well_known
= NULL
;
1282 /* We will change the sender of messages from the bus driver
1283 * so that they originate from the bus driver. This is a
1284 * speciality originating from dbus1, where the bus driver did
1285 * not have a unique id, but only the well-known name. */
1287 c
= sd_bus_message_get_creds(m
);
1291 r
= sd_bus_creds_get_well_known_names(c
, &well_known
);
1295 if (strv_contains(well_known
, "org.freedesktop.DBus"))
1296 m
->sender
= "org.freedesktop.DBus";
1301 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid
, const char *new_label
) {
1305 if (!mac_smack_use())
1308 if (new_label
&& its_pid
> 0)
1309 r
= mac_smack_apply_pid(its_pid
, new_label
);
1311 k
= drop_capability(CAP_MAC_ADMIN
);
1312 return r
< 0 ? r
: k
;
1318 int main(int argc
, char *argv
[]) {
1320 _cleanup_bus_close_unref_ sd_bus
*a
= NULL
, *b
= NULL
;
1321 sd_id128_t server_id
;
1322 int r
, in_fd
, out_fd
;
1323 bool got_hello
= false;
1325 struct ucred ucred
= {};
1326 _cleanup_free_
char *peersec
= NULL
;
1327 Policy policy_buffer
= {}, *policy
= NULL
;
1328 _cleanup_set_free_free_ Set
*owned_names
= NULL
;
1331 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG
);
1332 log_parse_environment();
1335 r
= parse_argv(argc
, argv
);
1339 r
= sd_listen_fds(0);
1341 in_fd
= STDIN_FILENO
;
1342 out_fd
= STDOUT_FILENO
;
1343 } else if (r
== 1) {
1344 in_fd
= SD_LISTEN_FDS_START
;
1345 out_fd
= SD_LISTEN_FDS_START
;
1347 log_error("Illegal number of file descriptors passed");
1351 original_uid
= getuid();
1354 sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
1355 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
1358 (void) getpeercred(in_fd
, &ucred
);
1359 (void) getpeersec(in_fd
, &peersec
);
1361 r
= mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec
);
1363 log_warning_errno(r
, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec
);
1366 if (arg_drop_privileges
) {
1367 const char *user
= "systemd-bus-proxy";
1371 r
= get_user_creds(&user
, &uid
, &gid
, NULL
, NULL
);
1373 log_error_errno(r
, "Cannot resolve user name %s: %m", user
);
1377 r
= drop_privileges(uid
, gid
, 1ULL << CAP_IPC_OWNER
);
1382 owned_names
= set_new(&string_hash_ops
);
1390 log_error_errno(r
, "Failed to allocate bus: %m");
1394 r
= sd_bus_set_description(a
, "sd-proxy");
1396 log_error_errno(r
, "Failed to set bus name: %m");
1400 r
= sd_bus_set_address(a
, arg_address
);
1402 log_error_errno(r
, "Failed to set address to connect to: %m");
1406 r
= sd_bus_negotiate_fds(a
, is_unix
);
1408 log_error_errno(r
, "Failed to set FD negotiation: %m");
1412 r
= sd_bus_negotiate_creds(a
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_GID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
1414 log_error_errno(r
, "Failed to set credential negotiation: %m");
1418 if (ucred
.pid
> 0) {
1419 a
->fake_pids
.pid
= ucred
.pid
;
1420 a
->fake_pids_valid
= true;
1422 a
->fake_creds
.uid
= ucred
.uid
;
1423 a
->fake_creds
.euid
= UID_INVALID
;
1424 a
->fake_creds
.suid
= UID_INVALID
;
1425 a
->fake_creds
.fsuid
= UID_INVALID
;
1426 a
->fake_creds
.gid
= ucred
.gid
;
1427 a
->fake_creds
.egid
= GID_INVALID
;
1428 a
->fake_creds
.sgid
= GID_INVALID
;
1429 a
->fake_creds
.fsgid
= GID_INVALID
;
1430 a
->fake_creds_valid
= true;
1434 a
->fake_label
= peersec
;
1438 a
->manual_peer_interface
= true;
1440 r
= sd_bus_start(a
);
1442 log_error_errno(r
, "Failed to start bus client: %m");
1446 r
= sd_bus_get_bus_id(a
, &server_id
);
1448 log_error_errno(r
, "Failed to get server ID: %m");
1453 if (!arg_configuration
) {
1456 r
= sd_bus_get_scope(a
, &scope
);
1458 log_error_errno(r
, "Couldn't determine bus scope: %m");
1462 if (streq(scope
, "system"))
1463 arg_configuration
= strv_new(
1464 "/etc/dbus-1/system.conf",
1465 "/etc/dbus-1/system.d/",
1466 "/etc/dbus-1/system-local.conf",
1468 else if (streq(scope
, "user"))
1469 arg_configuration
= strv_new(
1470 "/etc/dbus-1/session.conf",
1471 "/etc/dbus-1/session.d/",
1472 "/etc/dbus-1/session-local.conf",
1475 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope
);
1479 if (!arg_configuration
) {
1485 r
= policy_load(&policy_buffer
, arg_configuration
);
1487 log_error_errno(r
, "Failed to load policy: %m");
1491 policy
= &policy_buffer
;
1492 /* policy_dump(policy); */
1494 if (ucred
.uid
== original_uid
)
1495 log_debug("Permitting access, since bus owner matches bus client.");
1496 else if (policy_check_hello(policy
, ucred
.uid
, ucred
.gid
))
1497 log_debug("Permitting access due to XML policy.");
1499 r
= log_error_errno(EPERM
, "Policy denied connection.");
1506 log_error_errno(r
, "Failed to allocate bus: %m");
1510 r
= sd_bus_set_fd(b
, in_fd
, out_fd
);
1512 log_error_errno(r
, "Failed to set fds: %m");
1516 r
= sd_bus_set_server(b
, 1, server_id
);
1518 log_error_errno(r
, "Failed to set server mode: %m");
1522 r
= sd_bus_negotiate_fds(b
, is_unix
);
1524 log_error_errno(r
, "Failed to set FD negotiation: %m");
1528 r
= sd_bus_negotiate_creds(b
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_GID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
1530 log_error_errno(r
, "Failed to set credential negotiation: %m");
1534 r
= sd_bus_set_anonymous(b
, true);
1536 log_error_errno(r
, "Failed to set anonymous authentication: %m");
1540 b
->manual_peer_interface
= true;
1542 r
= sd_bus_start(b
);
1544 log_error_errno(r
, "Failed to start bus client: %m");
1548 r
= rename_service(a
, b
);
1550 log_debug_errno(r
, "Failed to rename process: %m");
1553 _cleanup_free_
char *match
= NULL
;
1556 r
= sd_bus_get_unique_name(a
, &unique
);
1558 log_error_errno(r
, "Failed to get unique name: %m");
1562 match
= strjoin("type='signal',"
1563 "sender='org.freedesktop.DBus',"
1564 "path='/org/freedesktop/DBus',"
1565 "interface='org.freedesktop.DBus',"
1566 "member='NameOwnerChanged',"
1576 r
= sd_bus_add_match(a
, NULL
, match
, NULL
, NULL
);
1578 log_error_errno(r
, "Failed to add match for NameLost: %m");
1583 match
= strjoin("type='signal',"
1584 "sender='org.freedesktop.DBus',"
1585 "path='/org/freedesktop/DBus',"
1586 "interface='org.freedesktop.DBus',"
1587 "member='NameOwnerChanged',"
1597 r
= sd_bus_add_match(a
, NULL
, match
, NULL
, NULL
);
1599 log_error_errno(r
, "Failed to add match for NameAcquired: %m");
1605 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
1606 int events_a
, events_b
, fd
;
1607 uint64_t timeout_a
, timeout_b
, t
;
1608 struct timespec _ts
, *ts
;
1609 struct pollfd
*pollfd
;
1613 /* Read messages from bus, to pass them on to our client */
1615 r
= sd_bus_process(a
, &m
);
1617 /* treat 'connection reset by peer' as clean exit condition */
1618 if (r
== -ECONNRESET
)
1621 log_error_errno(r
, "Failed to process bus a: %m");
1627 bool processed
= false;
1629 /* We officially got EOF, let's quit */
1630 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected")) {
1635 k
= synthesize_name_acquired(a
, b
, m
);
1638 log_error_errno(r
, "Failed to synthesize message: %m");
1645 k
= process_policy(a
, b
, m
, policy
, &ucred
, owned_names
);
1648 log_error_errno(r
, "Failed to process policy: %m");
1657 k
= sd_bus_send(b
, m
, NULL
);
1659 if (k
== -ECONNRESET
) {
1662 } else if (k
== -EPERM
&& m
->reply_cookie
> 0) {
1663 /* If the peer tries to send a reply and it is rejected with EPERM
1664 * by the kernel, we ignore the error. This catches cases where the
1665 * original method-call didn't had EXPECT_REPLY set, but the proxy-peer
1666 * still sends a reply. This is allowed in dbus1, but not in kdbus. We
1667 * don't want to track reply-windows in the proxy, so we simply ignore
1668 * EPERM for all replies. The only downside is, that callers are no
1669 * longer notified if their replies are dropped. However, this is
1670 * equivalent to the caller's timeout to expire, so this should be
1671 * acceptable. Nobody sane sends replies without a matching method-call,
1672 * so nobody should care. */
1676 log_error_errno(r
, "Failed to send message to client: %m");
1688 /* Read messages from our client, to pass them on to the bus */
1689 r
= sd_bus_process(b
, &m
);
1691 /* treat 'connection reset by peer' as clean exit condition */
1692 if (r
== -ECONNRESET
)
1695 log_error_errno(r
, "Failed to process bus b: %m");
1701 bool processed
= false;
1703 /* We officially got EOF, let's quit */
1704 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected")) {
1709 k
= process_hello(a
, b
, m
, &got_hello
);
1712 log_error_errno(r
, "Failed to process HELLO: %m");
1720 k
= process_driver(a
, b
, m
, policy
, &ucred
, owned_names
);
1723 log_error_errno(r
, "Failed to process driver calls: %m");
1734 k
= process_policy(b
, a
, m
, policy
, &ucred
, owned_names
);
1737 log_error_errno(r
, "Failed to process policy: %m");
1746 k
= sd_bus_send(a
, m
, NULL
);
1748 if (k
== -EREMCHG
) {
1749 /* The name database changed since the policy check, hence let's check again */
1751 } else if (k
== -ECONNRESET
) {
1754 } else if (k
== -EPERM
&& m
->reply_cookie
> 0) {
1755 /* see above why EPERM is ignored for replies */
1759 log_error_errno(r
, "Failed to send message to bus: %m");
1774 fd
= sd_bus_get_fd(a
);
1776 log_error_errno(r
, "Failed to get fd: %m");
1780 events_a
= sd_bus_get_events(a
);
1782 log_error_errno(r
, "Failed to get events mask: %m");
1786 r
= sd_bus_get_timeout(a
, &timeout_a
);
1788 log_error_errno(r
, "Failed to get timeout: %m");
1792 events_b
= sd_bus_get_events(b
);
1794 log_error_errno(r
, "Failed to get events mask: %m");
1798 r
= sd_bus_get_timeout(b
, &timeout_b
);
1800 log_error_errno(r
, "Failed to get timeout: %m");
1805 if (t
== (uint64_t) -1 || (timeout_b
!= (uint64_t) -1 && timeout_b
< timeout_a
))
1808 if (t
== (uint64_t) -1)
1813 nw
= now(CLOCK_MONOTONIC
);
1819 ts
= timespec_store(&_ts
, t
);
1822 pollfd
= (struct pollfd
[3]) {
1823 {.fd
= fd
, .events
= events_a
, },
1824 {.fd
= in_fd
, .events
= events_b
& POLLIN
, },
1825 {.fd
= out_fd
, .events
= events_b
& POLLOUT
, }
1828 r
= ppoll(pollfd
, 3, ts
, NULL
);
1830 log_error_errno(errno
, "ppoll() failed: %m");
1838 "STATUS=Shutting down.");
1840 policy_free(&policy_buffer
);
1841 strv_free(arg_configuration
);
1844 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;