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) {
995 if (from->is_kernel) {
996 uid_t sender_uid = UID_INVALID;
997 gid_t sender_gid = GID_INVALID;
998 char **sender_names = NULL;
999 bool granted = false;
1001 /* Driver messages are always OK */
1002 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
1005 /* The message came from the kernel, and is sent to our legacy client. */
1006 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
1008 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
1009 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
1011 /* First check whether the sender can send the message to our name */
1012 if (set_isempty(owned_names)) {
1013 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
1019 SET_FOREACH(n, owned_names, i)
1020 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1027 /* Then check whether us (the recipient) can receive from the sender's name */
1028 if (strv_isempty(sender_names)) {
1029 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1034 STRV_FOREACH(n, sender_names) {
1035 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1041 /* Return an error back to the caller */
1042 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1043 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1045 /* Return 1, indicating that the message shall not be processed any further */
1049 if (to->is_kernel) {
1050 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1051 uid_t destination_uid = UID_INVALID;
1052 gid_t destination_gid = GID_INVALID;
1053 const char *destination_unique = NULL;
1054 char **destination_names = NULL;
1055 bool granted = false;
1057 /* Driver messages are always OK */
1058 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1061 /* The message came from the legacy client, and is sent to kdbus. */
1062 if (m->destination) {
1063 r = bus_get_name_creds_kdbus(to, m->destination,
1064 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1065 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1066 true, &destination_creds);
1068 return handle_policy_error(m, r);
1070 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1072 return handle_policy_error(m, r);
1074 sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1076 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1077 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1080 /* First check if we (the sender) can send to this name */
1081 if (strv_isempty(destination_names)) {
1082 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1087 STRV_FOREACH(n, destination_names) {
1088 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1090 /* If we made a receiver decision,
1091 then remember which name's policy
1092 we used, and to which unique ID it
1093 mapped when we made the
1094 decision. Then, let's pass this to
1095 the kernel when sending the
1096 message, so that it refuses the
1097 operation should the name and
1098 unique ID not map to each other
1101 r = free_and_strdup(&m->destination_ptr, *n);
1105 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1115 /* Then check if the recipient can receive from our name */
1117 if (set_isempty(owned_names)) {
1118 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1124 SET_FOREACH(n, owned_names, i)
1125 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1130 /* Return an error back to the caller */
1131 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1132 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1134 /* Return 1, indicating that the message shall not be processed any further */
1141 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1142 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1151 /* As reaction to hello we need to respond with two messages:
1152 * the callback reply and the NameAcquired for the unique
1153 * name, since hello is otherwise obsolete on kdbus. */
1156 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1157 streq_ptr(m->destination, "org.freedesktop.DBus");
1164 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1169 log_error("Got duplicate hello, aborting.");
1178 r = sd_bus_message_new_method_return(m, &n);
1180 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1182 r = sd_bus_message_append(n, "s", a->unique_name);
1184 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1186 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1188 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1190 r = bus_seal_synthetic_message(b, n);
1192 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1194 r = sd_bus_send(b, n, NULL);
1196 return log_error_errno(r, "Failed to send HELLO reply: %m");
1198 n = sd_bus_message_unref(n);
1199 r = sd_bus_message_new_signal(
1202 "/org/freedesktop/DBus",
1203 "org.freedesktop.DBus",
1206 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1208 r = sd_bus_message_append(n, "s", a->unique_name);
1210 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1212 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1214 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1216 r = bus_seal_synthetic_message(b, n);
1218 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1220 r = sd_bus_send(b, n, NULL);
1222 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1227 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1228 char **well_known = NULL;
1238 /* We will change the sender of messages from the bus driver
1239 * so that they originate from the bus driver. This is a
1240 * speciality originating from dbus1, where the bus driver did
1241 * not have a unique id, but only the well-known name. */
1243 c = sd_bus_message_get_creds(m);
1247 r = sd_bus_creds_get_well_known_names(c, &well_known);
1251 if (strv_contains(well_known, "org.freedesktop.DBus"))
1252 m->sender = "org.freedesktop.DBus";
1257 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
1261 if (!mac_smack_use())
1264 if (new_label && its_pid > 0)
1265 r = mac_smack_apply_pid(its_pid, new_label);
1267 k = drop_capability(CAP_MAC_ADMIN);
1268 return r < 0 ? r : k;
1274 int main(int argc, char *argv[]) {
1276 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1277 sd_id128_t server_id;
1278 int r, in_fd, out_fd;
1279 bool got_hello = false;
1281 struct ucred ucred = {};
1282 _cleanup_free_ char *peersec = NULL;
1283 Policy policy_buffer = {}, *policy = NULL;
1284 _cleanup_set_free_free_ Set *owned_names = NULL;
1286 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1287 log_parse_environment();
1290 r = parse_argv(argc, argv);
1294 r = sd_listen_fds(0);
1296 in_fd = STDIN_FILENO;
1297 out_fd = STDOUT_FILENO;
1298 } else if (r == 1) {
1299 in_fd = SD_LISTEN_FDS_START;
1300 out_fd = SD_LISTEN_FDS_START;
1302 log_error("Illegal number of file descriptors passed");
1307 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1308 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1311 (void) getpeercred(in_fd, &ucred);
1312 (void) getpeersec(in_fd, &peersec);
1314 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
1316 log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
1319 if (arg_drop_privileges) {
1320 const char *user = "systemd-bus-proxy";
1324 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1326 log_error_errno(r, "Cannot resolve user name %s: %m", user);
1330 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1335 owned_names = set_new(&string_hash_ops);
1343 log_error_errno(r, "Failed to allocate bus: %m");
1347 r = sd_bus_set_description(a, "sd-proxy");
1349 log_error_errno(r, "Failed to set bus name: %m");
1353 r = sd_bus_set_address(a, arg_address);
1355 log_error_errno(r, "Failed to set address to connect to: %m");
1359 r = sd_bus_negotiate_fds(a, is_unix);
1361 log_error_errno(r, "Failed to set FD negotiation: %m");
1365 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1367 log_error_errno(r, "Failed to set credential negotiation: %m");
1371 if (ucred.pid > 0) {
1372 a->fake_pids.pid = ucred.pid;
1373 a->fake_pids_valid = true;
1375 a->fake_creds.uid = ucred.uid;
1376 a->fake_creds.euid = UID_INVALID;
1377 a->fake_creds.suid = UID_INVALID;
1378 a->fake_creds.fsuid = UID_INVALID;
1379 a->fake_creds.gid = ucred.gid;
1380 a->fake_creds.egid = GID_INVALID;
1381 a->fake_creds.sgid = GID_INVALID;
1382 a->fake_creds.fsgid = GID_INVALID;
1383 a->fake_creds_valid = true;
1387 a->fake_label = peersec;
1391 a->manual_peer_interface = true;
1393 r = sd_bus_start(a);
1395 log_error_errno(r, "Failed to start bus client: %m");
1399 r = sd_bus_get_bus_id(a, &server_id);
1401 log_error_errno(r, "Failed to get server ID: %m");
1406 if (!arg_configuration) {
1409 r = sd_bus_get_scope(a, &scope);
1411 log_error_errno(r, "Couldn't determine bus scope: %m");
1415 if (streq(scope, "system"))
1416 arg_configuration = strv_new(
1417 "/etc/dbus-1/system.conf",
1418 "/etc/dbus-1/system.d/",
1419 "/etc/dbus-1/system-local.conf",
1421 else if (streq(scope, "user"))
1422 arg_configuration = strv_new(
1423 "/etc/dbus-1/session.conf",
1424 "/etc/dbus-1/session.d/",
1425 "/etc/dbus-1/session-local.conf",
1428 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1432 if (!arg_configuration) {
1438 r = policy_load(&policy_buffer, arg_configuration);
1440 log_error_errno(r, "Failed to load policy: %m");
1444 policy = &policy_buffer;
1445 /* policy_dump(policy); */
1447 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1448 r = log_error_errno(EPERM, "Policy denied connection.");
1455 log_error_errno(r, "Failed to allocate bus: %m");
1459 r = sd_bus_set_fd(b, in_fd, out_fd);
1461 log_error_errno(r, "Failed to set fds: %m");
1465 r = sd_bus_set_server(b, 1, server_id);
1467 log_error_errno(r, "Failed to set server mode: %m");
1471 r = sd_bus_negotiate_fds(b, is_unix);
1473 log_error_errno(r, "Failed to set FD negotiation: %m");
1477 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1479 log_error_errno(r, "Failed to set credential negotiation: %m");
1483 r = sd_bus_set_anonymous(b, true);
1485 log_error_errno(r, "Failed to set anonymous authentication: %m");
1489 b->manual_peer_interface = true;
1491 r = sd_bus_start(b);
1493 log_error_errno(r, "Failed to start bus client: %m");
1497 r = rename_service(a, b);
1499 log_debug_errno(r, "Failed to rename process: %m");
1502 _cleanup_free_ char *match = NULL;
1505 r = sd_bus_get_unique_name(a, &unique);
1507 log_error_errno(r, "Failed to get unique name: %m");
1511 match = strjoin("type='signal',"
1512 "sender='org.freedesktop.DBus',"
1513 "path='/org/freedesktop/DBus',"
1514 "interface='org.freedesktop.DBus',"
1515 "member='NameOwnerChanged',"
1525 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1527 log_error_errno(r, "Failed to add match for NameLost: %m");
1532 match = strjoin("type='signal',"
1533 "sender='org.freedesktop.DBus',"
1534 "path='/org/freedesktop/DBus',"
1535 "interface='org.freedesktop.DBus',"
1536 "member='NameOwnerChanged',"
1546 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1548 log_error_errno(r, "Failed to add match for NameAcquired: %m");
1554 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1555 int events_a, events_b, fd;
1556 uint64_t timeout_a, timeout_b, t;
1557 struct timespec _ts, *ts;
1558 struct pollfd *pollfd;
1562 /* Read messages from bus, to pass them on to our client */
1564 r = sd_bus_process(a, &m);
1566 /* treat 'connection reset by peer' as clean exit condition */
1567 if (r == -ECONNRESET)
1570 log_error_errno(r, "Failed to process bus a: %m");
1576 bool processed = false;
1578 /* We officially got EOF, let's quit */
1579 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1584 k = synthesize_name_acquired(a, b, m);
1587 log_error_errno(r, "Failed to synthesize message: %m");
1594 k = process_policy(a, b, m, policy, &ucred, owned_names);
1597 log_error_errno(r, "Failed to process policy: %m");
1606 k = sd_bus_send(b, m, NULL);
1608 if (k == -ECONNRESET) {
1611 } else if (k == -EPERM && m->reply_cookie > 0) {
1612 /* If the peer tries to send a reply and it is rejected with EPERM
1613 * by the kernel, we ignore the error. This catches cases where the
1614 * original method-call didn't had EXPECT_REPLY set, but the proxy-peer
1615 * still sends a reply. This is allowed in dbus1, but not in kdbus. We
1616 * don't want to track reply-windows in the proxy, so we simply ignore
1617 * EPERM for all replies. The only downside is, that callers are no
1618 * longer notified if their replies are dropped. However, this is
1619 * equivalent to the caller's timeout to expire, so this should be
1620 * acceptable. Nobody sane sends replies without a matching method-call,
1621 * so nobody should care. */
1625 log_error_errno(r, "Failed to send message to client: %m");
1637 /* Read messages from our client, to pass them on to the bus */
1638 r = sd_bus_process(b, &m);
1640 /* treat 'connection reset by peer' as clean exit condition */
1641 if (r == -ECONNRESET)
1644 log_error_errno(r, "Failed to process bus b: %m");
1650 bool processed = false;
1652 /* We officially got EOF, let's quit */
1653 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1658 k = process_hello(a, b, m, &got_hello);
1661 log_error_errno(r, "Failed to process HELLO: %m");
1669 k = process_driver(a, b, m, policy, &ucred, owned_names);
1672 log_error_errno(r, "Failed to process driver calls: %m");
1683 k = process_policy(b, a, m, policy, &ucred, owned_names);
1686 log_error_errno(r, "Failed to process policy: %m");
1695 k = sd_bus_send(a, m, NULL);
1697 if (k == -EREMCHG) {
1698 /* The name database changed since the policy check, hence let's check again */
1700 } else if (k == -ECONNRESET) {
1703 } else if (k == -EPERM && m->reply_cookie > 0) {
1704 /* see above why EPERM is ignored for replies */
1708 log_error_errno(r, "Failed to send message to bus: %m");
1723 fd = sd_bus_get_fd(a);
1725 log_error_errno(r, "Failed to get fd: %m");
1729 events_a = sd_bus_get_events(a);
1731 log_error_errno(r, "Failed to get events mask: %m");
1735 r = sd_bus_get_timeout(a, &timeout_a);
1737 log_error_errno(r, "Failed to get timeout: %m");
1741 events_b = sd_bus_get_events(b);
1743 log_error_errno(r, "Failed to get events mask: %m");
1747 r = sd_bus_get_timeout(b, &timeout_b);
1749 log_error_errno(r, "Failed to get timeout: %m");
1754 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1757 if (t == (uint64_t) -1)
1762 nw = now(CLOCK_MONOTONIC);
1768 ts = timespec_store(&_ts, t);
1771 pollfd = (struct pollfd[3]) {
1772 {.fd = fd, .events = events_a, },
1773 {.fd = in_fd, .events = events_b & POLLIN, },
1774 {.fd = out_fd, .events = events_b & POLLOUT, }
1777 r = ppoll(pollfd, 3, ts, NULL);
1779 log_error_errno(errno, "ppoll() failed: %m");
1787 "STATUS=Shutting down.");
1789 policy_free(&policy_buffer);
1790 strv_free(arg_configuration);
1793 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;