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
, &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 r
= sd_bus_message_new_method_return(call
, &m
);
410 return synthetic_reply_method_errno(call
, r
, NULL
);
412 r
= sd_bus_message_append_strv(m
, l
);
414 return synthetic_reply_method_errno(call
, r
, NULL
);
416 return synthetic_driver_send(call
->bus
, m
);
419 static int get_creds_by_name(sd_bus
*bus
, const char *name
, uint64_t mask
, sd_bus_creds
**_creds
, sd_bus_error
*error
) {
420 _cleanup_bus_creds_unref_ sd_bus_creds
*c
= NULL
;
427 r
= sd_bus_get_name_creds(bus
, name
, mask
, &c
);
428 if (r
== -ESRCH
|| r
== -ENXIO
)
429 return sd_bus_error_setf(error
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Name %s is currently not owned by anyone.", name
);
433 if ((c
->mask
& mask
) != mask
)
442 static int get_creds_by_message(sd_bus
*bus
, sd_bus_message
*m
, uint64_t mask
, sd_bus_creds
**_creds
, sd_bus_error
*error
) {
450 r
= sd_bus_message_read(m
, "s", &name
);
454 return get_creds_by_name(bus
, name
, mask
, _creds
, error
);
457 static int process_driver(sd_bus
*a
, sd_bus
*b
, sd_bus_message
*m
, Policy
*policy
, const struct ucred
*ucred
, Set
*owned_names
) {
467 if (!streq_ptr(sd_bus_message_get_destination(m
), "org.freedesktop.DBus"))
470 /* The "Hello()" call is is handled in process_hello() */
472 if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus.Introspectable", "Introspect")) {
474 if (!sd_bus_message_has_signature(m
, ""))
475 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
477 return synthetic_reply_method_return(m
, "s",
478 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
479 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
481 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
482 " <method name=\"Introspect\">\n"
483 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
486 " <interface name=\"org.freedesktop.DBus\">\n"
487 " <method name=\"AddMatch\">\n"
488 " <arg type=\"s\" direction=\"in\"/>\n"
490 " <method name=\"RemoveMatch\">\n"
491 " <arg type=\"s\" direction=\"in\"/>\n"
493 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
494 " <arg type=\"s\" direction=\"in\"/>\n"
495 " <arg type=\"ay\" direction=\"out\"/>\n"
497 " <method name=\"GetConnectionUnixProcessID\">\n"
498 " <arg type=\"s\" direction=\"in\"/>\n"
499 " <arg type=\"u\" direction=\"out\"/>\n"
501 " <method name=\"GetConnectionUnixUser\">\n"
502 " <arg type=\"s\" direction=\"in\"/>\n"
503 " <arg type=\"u\" direction=\"out\"/>\n"
505 " <method name=\"GetId\">\n"
506 " <arg type=\"s\" direction=\"out\"/>\n"
508 " <method name=\"GetNameOwner\">\n"
509 " <arg type=\"s\" direction=\"in\"/>\n"
510 " <arg type=\"s\" direction=\"out\"/>\n"
512 " <method name=\"Hello\">\n"
513 " <arg type=\"s\" direction=\"out\"/>\n"
515 " <method name=\"ListActivatableNames\">\n"
516 " <arg type=\"as\" direction=\"out\"/>\n"
518 " <method name=\"ListNames\">\n"
519 " <arg type=\"as\" direction=\"out\"/>\n"
521 " <method name=\"ListQueuedOwners\">\n"
522 " <arg type=\"s\" direction=\"in\"/>\n"
523 " <arg type=\"as\" direction=\"out\"/>\n"
525 " <method name=\"NameHasOwner\">\n"
526 " <arg type=\"s\" direction=\"in\"/>\n"
527 " <arg type=\"b\" direction=\"out\"/>\n"
529 " <method name=\"ReleaseName\">\n"
530 " <arg type=\"s\" direction=\"in\"/>\n"
531 " <arg type=\"u\" direction=\"out\"/>\n"
533 " <method name=\"ReloadConfig\">\n"
535 " <method name=\"RequestName\">\n"
536 " <arg type=\"s\" direction=\"in\"/>\n"
537 " <arg type=\"u\" direction=\"in\"/>\n"
538 " <arg type=\"u\" direction=\"out\"/>\n"
540 " <method name=\"StartServiceByName\">\n"
541 " <arg type=\"s\" direction=\"in\"/>\n"
542 " <arg type=\"u\" direction=\"in\"/>\n"
543 " <arg type=\"u\" direction=\"out\"/>\n"
545 " <method name=\"UpdateActivationEnvironment\">\n"
546 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
548 " <signal name=\"NameAcquired\">\n"
549 " <arg type=\"s\"/>\n"
551 " <signal name=\"NameLost\">\n"
552 " <arg type=\"s\"/>\n"
554 " <signal name=\"NameOwnerChanged\">\n"
555 " <arg type=\"s\"/>\n"
556 " <arg type=\"s\"/>\n"
557 " <arg type=\"s\"/>\n"
562 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "AddMatch")) {
565 if (!sd_bus_message_has_signature(m
, "s"))
566 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
568 r
= sd_bus_message_read(m
, "s", &match
);
570 return synthetic_reply_method_errno(m
, r
, NULL
);
572 r
= sd_bus_add_match(a
, NULL
, match
, NULL
, NULL
);
574 return synthetic_reply_method_errno(m
, r
, NULL
);
576 return synthetic_reply_method_return(m
, NULL
);
578 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "RemoveMatch")) {
581 if (!sd_bus_message_has_signature(m
, "s"))
582 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
584 r
= sd_bus_message_read(m
, "s", &match
);
586 return synthetic_reply_method_errno(m
, r
, NULL
);
588 r
= bus_remove_match_by_string(a
, match
, NULL
, NULL
);
590 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND
, "Match rule not found"));
592 return synthetic_reply_method_errno(m
, r
, NULL
);
594 return synthetic_reply_method_return(m
, NULL
);
596 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
597 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
598 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
600 if (!sd_bus_message_has_signature(m
, "s"))
601 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
603 r
= get_creds_by_message(a
, m
, SD_BUS_CREDS_SELINUX_CONTEXT
, &creds
, &error
);
605 return synthetic_reply_method_errno(m
, r
, &error
);
607 return synthetic_reply_method_return(m
, "y", creds
->label
, strlen(creds
->label
));
609 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
610 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
611 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
613 if (!sd_bus_message_has_signature(m
, "s"))
614 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
616 r
= get_creds_by_message(a
, m
, SD_BUS_CREDS_PID
, &creds
, &error
);
618 return synthetic_reply_method_errno(m
, r
, &error
);
620 return synthetic_reply_method_return(m
, "u", (uint32_t) creds
->pid
);
622 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
623 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
624 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
626 if (!sd_bus_message_has_signature(m
, "s"))
627 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
629 r
= get_creds_by_message(a
, m
, SD_BUS_CREDS_UID
, &creds
, &error
);
631 return synthetic_reply_method_errno(m
, r
, &error
);
633 return synthetic_reply_method_return(m
, "u", (uint32_t) creds
->uid
);
635 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetId")) {
636 sd_id128_t server_id
;
637 char buf
[SD_ID128_STRING_MAX
];
639 if (!sd_bus_message_has_signature(m
, ""))
640 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
642 r
= sd_bus_get_bus_id(a
, &server_id
);
644 return synthetic_reply_method_errno(m
, r
, NULL
);
646 return synthetic_reply_method_return(m
, "s", sd_id128_to_string(server_id
, buf
));
648 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "GetNameOwner")) {
650 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
651 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
653 if (!sd_bus_message_has_signature(m
, "s"))
654 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
656 r
= sd_bus_message_read(m
, "s", &name
);
658 return synthetic_reply_method_errno(m
, r
, NULL
);
660 if (streq(name
, "org.freedesktop.DBus"))
661 return synthetic_reply_method_return(m
, "s", "org.freedesktop.DBus");
663 r
= get_creds_by_name(a
, name
, SD_BUS_CREDS_UNIQUE_NAME
, &creds
, &error
);
665 return synthetic_reply_method_errno(m
, r
, &error
);
667 return synthetic_reply_method_return(m
, "s", creds
->unique_name
);
669 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ListActivatableNames")) {
670 _cleanup_strv_free_
char **names
= NULL
;
672 if (!sd_bus_message_has_signature(m
, ""))
673 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
675 r
= sd_bus_list_names(a
, NULL
, &names
);
677 return synthetic_reply_method_errno(m
, r
, NULL
);
679 /* Let's sort the names list to make it stable */
682 return synthetic_reply_return_strv(m
, names
);
684 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ListNames")) {
685 _cleanup_strv_free_
char **names
= NULL
;
687 if (!sd_bus_message_has_signature(m
, ""))
688 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
690 r
= sd_bus_list_names(a
, &names
, NULL
);
692 return synthetic_reply_method_errno(m
, r
, NULL
);
694 r
= strv_extend(&names
, "org.freedesktop.DBus");
696 return synthetic_reply_method_errno(m
, r
, NULL
);
698 /* Let's sort the names list to make it stable */
701 return synthetic_reply_return_strv(m
, names
);
703 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ListQueuedOwners")) {
704 struct kdbus_cmd_name_list cmd
= {};
705 struct kdbus_name_list
*name_list
;
706 struct kdbus_name_info
*name
;
707 _cleanup_strv_free_
char **owners
= NULL
;
708 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
712 if (!sd_bus_message_has_signature(m
, "s"))
713 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
715 r
= sd_bus_message_read(m
, "s", &arg0
);
717 return synthetic_reply_method_errno(m
, r
, NULL
);
719 r
= sd_bus_get_name_creds(a
, arg0
, 0, NULL
);
720 if (r
== -ESRCH
|| r
== -ENXIO
) {
721 sd_bus_error_setf(&error
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Could not get owners of name '%s': no such name.", arg0
);
722 return synthetic_reply_method_errno(m
, r
, &error
);
725 return synthetic_reply_method_errno(m
, r
, NULL
);
727 cmd
.flags
= KDBUS_NAME_LIST_QUEUED
;
728 r
= ioctl(a
->input_fd
, KDBUS_CMD_NAME_LIST
, &cmd
);
730 return synthetic_reply_method_errno(m
, -errno
, NULL
);
732 name_list
= (struct kdbus_name_list
*) ((uint8_t *) a
->kdbus_buffer
+ cmd
.offset
);
734 KDBUS_ITEM_FOREACH(name
, name_list
, names
) {
735 const char *entry_name
= NULL
;
736 struct kdbus_item
*item
;
739 KDBUS_ITEM_FOREACH(item
, name
, items
)
740 if (item
->type
== KDBUS_ITEM_OWNED_NAME
)
741 entry_name
= item
->name
.name
;
743 if (!streq_ptr(entry_name
, arg0
))
746 if (asprintf(&n
, ":1.%llu", (unsigned long long) name
->owner_id
) < 0) {
751 r
= strv_consume(&owners
, n
);
758 r
= bus_kernel_cmd_free(a
, cmd
.offset
);
760 return synthetic_reply_method_errno(m
, r
, NULL
);
763 return synthetic_reply_method_errno(m
, err
, NULL
);
765 return synthetic_reply_return_strv(m
, owners
);
767 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "NameHasOwner")) {
770 if (!sd_bus_message_has_signature(m
, "s"))
771 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
773 r
= sd_bus_message_read(m
, "s", &name
);
775 return synthetic_reply_method_errno(m
, r
, NULL
);
777 if (streq(name
, "org.freedesktop.DBus"))
778 return synthetic_reply_method_return(m
, "b", true);
780 r
= sd_bus_get_name_creds(a
, name
, 0, NULL
);
781 if (r
< 0 && r
!= -ESRCH
&& r
!= -ENXIO
)
782 return synthetic_reply_method_errno(m
, r
, NULL
);
784 return synthetic_reply_method_return(m
, "b", r
>= 0);
786 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ReleaseName")) {
789 if (!sd_bus_message_has_signature(m
, "s"))
790 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
792 r
= sd_bus_message_read(m
, "s", &name
);
794 return synthetic_reply_method_errno(m
, r
, NULL
);
796 r
= sd_bus_release_name(a
, name
);
799 return synthetic_reply_method_return(m
, "u", BUS_NAME_NON_EXISTENT
);
800 if (r
== -EADDRINUSE
)
801 return synthetic_reply_method_return(m
, "u", BUS_NAME_NOT_OWNER
);
803 return synthetic_reply_method_errno(m
, r
, NULL
);
806 set_remove(owned_names
, (char*) name
);
808 return synthetic_reply_method_return(m
, "u", BUS_NAME_RELEASED
);
810 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "ReloadConfig")) {
811 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
813 if (!sd_bus_message_has_signature(m
, ""))
814 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
816 r
= sd_bus_error_setf(&error
, SD_BUS_ERROR_NOT_SUPPORTED
, "%s() is not supported", sd_bus_message_get_member(m
));
818 return synthetic_reply_method_errno(m
, r
, &error
);
820 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "RequestName")) {
822 uint32_t flags
, param
;
825 if (!sd_bus_message_has_signature(m
, "su"))
826 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
828 r
= sd_bus_message_read(m
, "su", &name
, &flags
);
830 return synthetic_reply_method_errno(m
, r
, NULL
);
832 if (streq(name
, "org.freedesktop.DBus"))
833 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
,
834 "Connection is not allowed to own the org.freedesktop.DBus service."));
836 if (policy
&& !policy_check_own(policy
, ucred
->uid
, ucred
->gid
, name
))
837 return synthetic_reply_method_errno(m
, -EPERM
, NULL
);
839 if ((flags
& ~(BUS_NAME_ALLOW_REPLACEMENT
|BUS_NAME_REPLACE_EXISTING
|BUS_NAME_DO_NOT_QUEUE
)) != 0)
840 return synthetic_reply_method_errno(m
, -EINVAL
, NULL
);
843 if (flags
& BUS_NAME_ALLOW_REPLACEMENT
)
844 param
|= SD_BUS_NAME_ALLOW_REPLACEMENT
;
845 if (flags
& BUS_NAME_REPLACE_EXISTING
)
846 param
|= SD_BUS_NAME_REPLACE_EXISTING
;
847 if (!(flags
& BUS_NAME_DO_NOT_QUEUE
))
848 param
|= SD_BUS_NAME_QUEUE
;
850 r
= set_put_strdup(owned_names
, name
);
852 return synthetic_reply_method_errno(m
, r
, NULL
);
854 r
= sd_bus_request_name(a
, name
, param
);
857 return synthetic_reply_method_return(m
, "u", BUS_NAME_ALREADY_OWNER
);
859 set_remove(owned_names
, (char*) name
);
862 return synthetic_reply_method_return(m
, "u", BUS_NAME_EXISTS
);
863 return synthetic_reply_method_errno(m
, r
, NULL
);
869 return synthetic_reply_method_return(m
, "u", BUS_NAME_IN_QUEUE
);
871 return synthetic_reply_method_return(m
, "u", BUS_NAME_PRIMARY_OWNER
);
873 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "StartServiceByName")) {
874 _cleanup_bus_message_unref_ sd_bus_message
*msg
= NULL
;
878 if (!sd_bus_message_has_signature(m
, "su"))
879 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
881 r
= sd_bus_message_read(m
, "su", &name
, &flags
);
883 return synthetic_reply_method_errno(m
, r
, NULL
);
886 return synthetic_reply_method_errno(m
, -EINVAL
, NULL
);
888 r
= sd_bus_get_name_creds(a
, name
, 0, NULL
);
889 if (r
>= 0 || streq(name
, "org.freedesktop.DBus"))
890 return synthetic_reply_method_return(m
, "u", BUS_START_REPLY_ALREADY_RUNNING
);
892 return synthetic_reply_method_errno(m
, r
, NULL
);
894 r
= sd_bus_message_new_method_call(
899 "org.freedesktop.DBus.Peer",
902 return synthetic_reply_method_errno(m
, r
, NULL
);
904 r
= sd_bus_send(a
, msg
, NULL
);
906 return synthetic_reply_method_errno(m
, r
, NULL
);
908 return synthetic_reply_method_return(m
, "u", BUS_START_REPLY_SUCCESS
);
910 } else if (sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
911 _cleanup_bus_message_unref_ sd_bus_message
*msg
= NULL
;
912 _cleanup_strv_free_
char **args
= NULL
;
914 if (!sd_bus_message_has_signature(m
, "a{ss}"))
915 return synthetic_reply_method_error(m
, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS
, "Invalid parameters"));
917 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{ss}");
919 return synthetic_reply_method_errno(m
, r
, NULL
);
921 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "ss")) > 0) {
922 _cleanup_free_
char *s
= NULL
;
926 r
= sd_bus_message_read(m
, "ss", &key
, &value
);
928 return synthetic_reply_method_errno(m
, r
, NULL
);
930 s
= strjoin(key
, "=", value
, NULL
);
932 return synthetic_reply_method_errno(m
, -ENOMEM
, NULL
);
934 r
= strv_extend(&args
, s
);
936 return synthetic_reply_method_errno(m
, r
, NULL
);
938 r
= sd_bus_message_exit_container(m
);
940 return synthetic_reply_method_errno(m
, r
, NULL
);
943 r
= sd_bus_message_exit_container(m
);
945 return synthetic_reply_method_errno(m
, r
, NULL
);
948 return synthetic_reply_method_errno(m
, -EINVAL
, NULL
);
950 r
= sd_bus_message_new_method_call(
953 "org.freedesktop.systemd1",
954 "/org/freedesktop/systemd1",
955 "org.freedesktop.systemd1.Manager",
958 return synthetic_reply_method_errno(m
, r
, NULL
);
960 r
= sd_bus_message_append_strv(msg
, args
);
962 return synthetic_reply_method_errno(m
, r
, NULL
);
964 r
= sd_bus_call(a
, msg
, 0, NULL
, NULL
);
966 return synthetic_reply_method_errno(m
, r
, NULL
);
968 return synthetic_reply_method_return(m
, NULL
);
971 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
973 r
= sd_bus_error_setf(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
, "Unknown method '%s'.", m
->member
);
975 return synthetic_reply_method_errno(m
, r
, &error
);
979 static int handle_policy_error(sd_bus_message
*m
, int r
) {
980 if (r
== -ESRCH
|| r
== -ENXIO
)
981 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_NAME_HAS_NO_OWNER
, "Name %s is currently not owned by anyone.", m
->destination
);
986 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 if (from
->is_kernel
) {
997 uid_t sender_uid
= UID_INVALID
;
998 gid_t sender_gid
= GID_INVALID
;
999 char **sender_names
= NULL
;
1000 bool granted
= false;
1002 /* Driver messages are always OK */
1003 if (streq_ptr(m
->sender
, "org.freedesktop.DBus"))
1006 /* The message came from the kernel, and is sent to our legacy client. */
1007 sd_bus_creds_get_well_known_names(&m
->creds
, &sender_names
);
1009 (void) sd_bus_creds_get_uid(&m
->creds
, &sender_uid
);
1010 (void) sd_bus_creds_get_gid(&m
->creds
, &sender_gid
);
1012 /* First check whether the sender can send the message to our name */
1013 if (set_isempty(owned_names
)) {
1014 if (policy_check_send(policy
, sender_uid
, sender_gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
))
1020 SET_FOREACH(n
, owned_names
, i
)
1021 if (policy_check_send(policy
, sender_uid
, sender_gid
, m
->header
->type
, n
, m
->path
, m
->interface
, m
->member
)) {
1028 /* Then check whether us (the recipient) can receive from the sender's name */
1029 if (strv_isempty(sender_names
)) {
1030 if (policy_check_recv(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
))
1035 STRV_FOREACH(n
, sender_names
) {
1036 if (policy_check_recv(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, *n
, m
->path
, m
->interface
, m
->member
))
1042 /* Return an error back to the caller */
1043 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1044 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML receiver policy.");
1046 /* Return 1, indicating that the message shall not be processed any further */
1050 if (to
->is_kernel
) {
1051 _cleanup_bus_creds_unref_ sd_bus_creds
*destination_creds
= NULL
;
1052 uid_t destination_uid
= UID_INVALID
;
1053 gid_t destination_gid
= GID_INVALID
;
1054 const char *destination_unique
= NULL
;
1055 char **destination_names
= NULL
;
1056 bool granted
= false;
1058 /* Driver messages are always OK */
1059 if (streq_ptr(m
->destination
, "org.freedesktop.DBus"))
1062 /* The message came from the legacy client, and is sent to kdbus. */
1063 if (m
->destination
) {
1064 r
= bus_get_name_creds_kdbus(to
, m
->destination
,
1065 SD_BUS_CREDS_WELL_KNOWN_NAMES
|SD_BUS_CREDS_UNIQUE_NAME
|
1066 SD_BUS_CREDS_UID
|SD_BUS_CREDS_GID
|SD_BUS_CREDS_PID
,
1067 true, &destination_creds
);
1069 return handle_policy_error(m
, r
);
1071 r
= sd_bus_creds_get_unique_name(destination_creds
, &destination_unique
);
1073 return handle_policy_error(m
, r
);
1075 sd_bus_creds_get_well_known_names(destination_creds
, &destination_names
);
1077 (void) sd_bus_creds_get_uid(destination_creds
, &destination_uid
);
1078 (void) sd_bus_creds_get_gid(destination_creds
, &destination_gid
);
1081 /* First check if we (the sender) can send to this name */
1082 if (strv_isempty(destination_names
)) {
1083 if (policy_check_send(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
))
1088 STRV_FOREACH(n
, destination_names
) {
1089 if (policy_check_send(policy
, our_ucred
->uid
, our_ucred
->gid
, m
->header
->type
, *n
, m
->path
, m
->interface
, m
->member
)) {
1091 /* If we made a receiver decision,
1092 then remember which name's policy
1093 we used, and to which unique ID it
1094 mapped when we made the
1095 decision. Then, let's pass this to
1096 the kernel when sending the
1097 message, so that it refuses the
1098 operation should the name and
1099 unique ID not map to each other
1102 r
= free_and_strdup(&m
->destination_ptr
, *n
);
1106 r
= bus_kernel_parse_unique_name(destination_unique
, &m
->verify_destination_id
);
1116 /* Then check if the recipient can receive from our name */
1118 if (set_isempty(owned_names
)) {
1119 if (policy_check_recv(policy
, destination_uid
, destination_gid
, m
->header
->type
, NULL
, m
->path
, m
->interface
, m
->member
))
1125 SET_FOREACH(n
, owned_names
, i
)
1126 if (policy_check_recv(policy
, destination_uid
, destination_gid
, m
->header
->type
, n
, m
->path
, m
->interface
, m
->member
))
1131 /* Return an error back to the caller */
1132 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1133 return synthetic_reply_method_errorf(m
, SD_BUS_ERROR_ACCESS_DENIED
, "Access prohibited by XML sender policy.");
1135 /* Return 1, indicating that the message shall not be processed any further */
1142 static int process_hello(sd_bus
*a
, sd_bus
*b
, sd_bus_message
*m
, bool *got_hello
) {
1143 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
1152 /* As reaction to hello we need to respond with two messages:
1153 * the callback reply and the NameAcquired for the unique
1154 * name, since hello is otherwise obsolete on kdbus. */
1157 sd_bus_message_is_method_call(m
, "org.freedesktop.DBus", "Hello") &&
1158 streq_ptr(m
->destination
, "org.freedesktop.DBus");
1165 log_error("First packet isn't hello (it's %s.%s), aborting.", m
->interface
, m
->member
);
1170 log_error("Got duplicate hello, aborting.");
1179 r
= sd_bus_message_new_method_return(m
, &n
);
1181 return log_error_errno(r
, "Failed to generate HELLO reply: %m");
1183 r
= sd_bus_message_append(n
, "s", a
->unique_name
);
1185 return log_error_errno(r
, "Failed to append unique name to HELLO reply: %m");
1187 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
1189 return log_error_errno(r
, "Failed to append sender to HELLO reply: %m");
1191 r
= bus_seal_synthetic_message(b
, n
);
1193 return log_error_errno(r
, "Failed to seal HELLO reply: %m");
1195 r
= sd_bus_send(b
, n
, NULL
);
1197 return log_error_errno(r
, "Failed to send HELLO reply: %m");
1199 n
= sd_bus_message_unref(n
);
1200 r
= sd_bus_message_new_signal(
1203 "/org/freedesktop/DBus",
1204 "org.freedesktop.DBus",
1207 return log_error_errno(r
, "Failed to allocate initial NameAcquired message: %m");
1209 r
= sd_bus_message_append(n
, "s", a
->unique_name
);
1211 return log_error_errno(r
, "Failed to append unique name to NameAcquired message: %m");
1213 r
= bus_message_append_sender(n
, "org.freedesktop.DBus");
1215 return log_error_errno(r
, "Failed to append sender to NameAcquired message: %m");
1217 r
= bus_seal_synthetic_message(b
, n
);
1219 return log_error_errno(r
, "Failed to seal NameAcquired message: %m");
1221 r
= sd_bus_send(b
, n
, NULL
);
1223 return log_error_errno(r
, "Failed to send NameAcquired message: %m");
1228 static int patch_sender(sd_bus
*a
, sd_bus_message
*m
) {
1229 char **well_known
= NULL
;
1239 /* We will change the sender of messages from the bus driver
1240 * so that they originate from the bus driver. This is a
1241 * speciality originating from dbus1, where the bus driver did
1242 * not have a unique id, but only the well-known name. */
1244 c
= sd_bus_message_get_creds(m
);
1248 r
= sd_bus_creds_get_well_known_names(c
, &well_known
);
1252 if (strv_contains(well_known
, "org.freedesktop.DBus"))
1253 m
->sender
= "org.freedesktop.DBus";
1258 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid
, const char *new_label
) {
1262 if (!mac_smack_use())
1265 if (new_label
&& its_pid
> 0)
1266 r
= mac_smack_apply_pid(its_pid
, new_label
);
1268 k
= drop_capability(CAP_MAC_ADMIN
);
1269 return r
< 0 ? r
: k
;
1275 int main(int argc
, char *argv
[]) {
1277 _cleanup_bus_close_unref_ sd_bus
*a
= NULL
, *b
= NULL
;
1278 sd_id128_t server_id
;
1279 int r
, in_fd
, out_fd
;
1280 bool got_hello
= false;
1282 struct ucred ucred
= {};
1283 _cleanup_free_
char *peersec
= NULL
;
1284 Policy policy_buffer
= {}, *policy
= NULL
;
1285 _cleanup_set_free_free_ Set
*owned_names
= NULL
;
1287 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG
);
1288 log_parse_environment();
1291 r
= parse_argv(argc
, argv
);
1295 r
= sd_listen_fds(0);
1297 in_fd
= STDIN_FILENO
;
1298 out_fd
= STDOUT_FILENO
;
1299 } else if (r
== 1) {
1300 in_fd
= SD_LISTEN_FDS_START
;
1301 out_fd
= SD_LISTEN_FDS_START
;
1303 log_error("Illegal number of file descriptors passed");
1308 sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
1309 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
1312 (void) getpeercred(in_fd
, &ucred
);
1313 (void) getpeersec(in_fd
, &peersec
);
1315 r
= mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec
);
1317 log_warning_errno(r
, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec
);
1320 if (arg_drop_privileges
) {
1321 const char *user
= "systemd-bus-proxy";
1325 r
= get_user_creds(&user
, &uid
, &gid
, NULL
, NULL
);
1327 log_error_errno(r
, "Cannot resolve user name %s: %m", user
);
1331 r
= drop_privileges(uid
, gid
, 1ULL << CAP_IPC_OWNER
);
1336 owned_names
= set_new(&string_hash_ops
);
1344 log_error_errno(r
, "Failed to allocate bus: %m");
1348 r
= sd_bus_set_description(a
, "sd-proxy");
1350 log_error_errno(r
, "Failed to set bus name: %m");
1354 r
= sd_bus_set_address(a
, arg_address
);
1356 log_error_errno(r
, "Failed to set address to connect to: %m");
1360 r
= sd_bus_negotiate_fds(a
, is_unix
);
1362 log_error_errno(r
, "Failed to set FD negotiation: %m");
1366 r
= sd_bus_negotiate_creds(a
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_GID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
1368 log_error_errno(r
, "Failed to set credential negotiation: %m");
1372 if (ucred
.pid
> 0) {
1373 a
->fake_pids
.pid
= ucred
.pid
;
1374 a
->fake_pids_valid
= true;
1376 a
->fake_creds
.uid
= ucred
.uid
;
1377 a
->fake_creds
.euid
= UID_INVALID
;
1378 a
->fake_creds
.suid
= UID_INVALID
;
1379 a
->fake_creds
.fsuid
= UID_INVALID
;
1380 a
->fake_creds
.gid
= ucred
.gid
;
1381 a
->fake_creds
.egid
= GID_INVALID
;
1382 a
->fake_creds
.sgid
= GID_INVALID
;
1383 a
->fake_creds
.fsgid
= GID_INVALID
;
1384 a
->fake_creds_valid
= true;
1388 a
->fake_label
= peersec
;
1392 a
->manual_peer_interface
= true;
1394 r
= sd_bus_start(a
);
1396 log_error_errno(r
, "Failed to start bus client: %m");
1400 r
= sd_bus_get_bus_id(a
, &server_id
);
1402 log_error_errno(r
, "Failed to get server ID: %m");
1407 if (!arg_configuration
) {
1410 r
= sd_bus_get_scope(a
, &scope
);
1412 log_error_errno(r
, "Couldn't determine bus scope: %m");
1416 if (streq(scope
, "system"))
1417 arg_configuration
= strv_new(
1418 "/etc/dbus-1/system.conf",
1419 "/etc/dbus-1/system.d/",
1420 "/etc/dbus-1/system-local.conf",
1422 else if (streq(scope
, "user"))
1423 arg_configuration
= strv_new(
1424 "/etc/dbus-1/session.conf",
1425 "/etc/dbus-1/session.d/",
1426 "/etc/dbus-1/session-local.conf",
1429 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope
);
1433 if (!arg_configuration
) {
1439 r
= policy_load(&policy_buffer
, arg_configuration
);
1441 log_error_errno(r
, "Failed to load policy: %m");
1445 policy
= &policy_buffer
;
1446 /* policy_dump(policy); */
1448 if (!policy_check_hello(policy
, ucred
.uid
, ucred
.gid
)) {
1449 r
= log_error_errno(EPERM
, "Policy denied connection.");
1456 log_error_errno(r
, "Failed to allocate bus: %m");
1460 r
= sd_bus_set_fd(b
, in_fd
, out_fd
);
1462 log_error_errno(r
, "Failed to set fds: %m");
1466 r
= sd_bus_set_server(b
, 1, server_id
);
1468 log_error_errno(r
, "Failed to set server mode: %m");
1472 r
= sd_bus_negotiate_fds(b
, is_unix
);
1474 log_error_errno(r
, "Failed to set FD negotiation: %m");
1478 r
= sd_bus_negotiate_creds(b
, true, SD_BUS_CREDS_UID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_GID
|SD_BUS_CREDS_SELINUX_CONTEXT
);
1480 log_error_errno(r
, "Failed to set credential negotiation: %m");
1484 r
= sd_bus_set_anonymous(b
, true);
1486 log_error_errno(r
, "Failed to set anonymous authentication: %m");
1490 b
->manual_peer_interface
= true;
1492 r
= sd_bus_start(b
);
1494 log_error_errno(r
, "Failed to start bus client: %m");
1498 r
= rename_service(a
, b
);
1500 log_debug_errno(r
, "Failed to rename process: %m");
1503 _cleanup_free_
char *match
= NULL
;
1506 r
= sd_bus_get_unique_name(a
, &unique
);
1508 log_error_errno(r
, "Failed to get unique name: %m");
1512 match
= strjoin("type='signal',"
1513 "sender='org.freedesktop.DBus',"
1514 "path='/org/freedesktop/DBus',"
1515 "interface='org.freedesktop.DBus',"
1516 "member='NameOwnerChanged',"
1526 r
= sd_bus_add_match(a
, NULL
, match
, NULL
, NULL
);
1528 log_error_errno(r
, "Failed to add match for NameLost: %m");
1533 match
= strjoin("type='signal',"
1534 "sender='org.freedesktop.DBus',"
1535 "path='/org/freedesktop/DBus',"
1536 "interface='org.freedesktop.DBus',"
1537 "member='NameOwnerChanged',"
1547 r
= sd_bus_add_match(a
, NULL
, match
, NULL
, NULL
);
1549 log_error_errno(r
, "Failed to add match for NameAcquired: %m");
1555 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
1556 int events_a
, events_b
, fd
;
1557 uint64_t timeout_a
, timeout_b
, t
;
1558 struct timespec _ts
, *ts
;
1559 struct pollfd
*pollfd
;
1563 /* Read messages from bus, to pass them on to our client */
1565 r
= sd_bus_process(a
, &m
);
1567 /* treat 'connection reset by peer' as clean exit condition */
1568 if (r
== -ECONNRESET
)
1571 log_error_errno(r
, "Failed to process bus a: %m");
1577 bool processed
= false;
1579 /* We officially got EOF, let's quit */
1580 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected")) {
1585 k
= synthesize_name_acquired(a
, b
, m
);
1588 log_error_errno(r
, "Failed to synthesize message: %m");
1595 k
= process_policy(a
, b
, m
, policy
, &ucred
, owned_names
);
1598 log_error_errno(r
, "Failed to process policy: %m");
1607 k
= sd_bus_send(b
, m
, NULL
);
1609 if (k
== -ECONNRESET
)
1613 log_error_errno(r
, "Failed to send message to client: %m");
1626 /* Read messages from our client, to pass them on to the bus */
1627 r
= sd_bus_process(b
, &m
);
1629 /* treat 'connection reset by peer' as clean exit condition */
1630 if (r
== -ECONNRESET
)
1633 log_error_errno(r
, "Failed to process bus b: %m");
1639 bool processed
= false;
1641 /* We officially got EOF, let's quit */
1642 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected")) {
1647 k
= process_hello(a
, b
, m
, &got_hello
);
1650 log_error_errno(r
, "Failed to process HELLO: %m");
1658 k
= process_driver(a
, b
, m
, policy
, &ucred
, owned_names
);
1661 log_error_errno(r
, "Failed to process driver calls: %m");
1672 k
= process_policy(b
, a
, m
, policy
, &ucred
, owned_names
);
1675 log_error_errno(r
, "Failed to process policy: %m");
1684 k
= sd_bus_send(a
, m
, NULL
);
1687 /* The name database changed since the policy check, hence let's check again */
1689 else if (k
== -ECONNRESET
)
1693 log_error_errno(r
, "Failed to send message to bus: %m");
1709 fd
= sd_bus_get_fd(a
);
1711 log_error_errno(r
, "Failed to get fd: %m");
1715 events_a
= sd_bus_get_events(a
);
1717 log_error_errno(r
, "Failed to get events mask: %m");
1721 r
= sd_bus_get_timeout(a
, &timeout_a
);
1723 log_error_errno(r
, "Failed to get timeout: %m");
1727 events_b
= sd_bus_get_events(b
);
1729 log_error_errno(r
, "Failed to get events mask: %m");
1733 r
= sd_bus_get_timeout(b
, &timeout_b
);
1735 log_error_errno(r
, "Failed to get timeout: %m");
1740 if (t
== (uint64_t) -1 || (timeout_b
!= (uint64_t) -1 && timeout_b
< timeout_a
))
1743 if (t
== (uint64_t) -1)
1748 nw
= now(CLOCK_MONOTONIC
);
1754 ts
= timespec_store(&_ts
, t
);
1757 pollfd
= (struct pollfd
[3]) {
1758 {.fd
= fd
, .events
= events_a
, },
1759 {.fd
= in_fd
, .events
= events_b
& POLLIN
, },
1760 {.fd
= out_fd
, .events
= events_b
& POLLOUT
, }
1763 r
= ppoll(pollfd
, 3, ts
, NULL
);
1765 log_error_errno(errno
, "ppoll() failed: %m");
1773 "STATUS=Shutting down.");
1775 policy_free(&policy_buffer
);
1776 strv_free(arg_configuration
);
1779 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;