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 (policy && !policy_check_own(policy, ucred->uid, ucred->gid, name))
833 return synthetic_reply_method_errno(m, -EPERM, NULL);
835 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
836 return synthetic_reply_method_errno(m, -EINVAL, NULL);
839 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
840 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
841 if (flags & BUS_NAME_REPLACE_EXISTING)
842 param |= SD_BUS_NAME_REPLACE_EXISTING;
843 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
844 param |= SD_BUS_NAME_QUEUE;
846 r = set_put_strdup(owned_names, name);
848 return synthetic_reply_method_errno(m, r, NULL);
850 r = sd_bus_request_name(a, name, param);
853 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
855 set_remove(owned_names, (char*) name);
858 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
859 return synthetic_reply_method_errno(m, r, NULL);
865 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
867 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
869 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
870 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
874 if (!sd_bus_message_has_signature(m, "su"))
875 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
877 r = sd_bus_message_read(m, "su", &name, &flags);
879 return synthetic_reply_method_errno(m, r, NULL);
882 return synthetic_reply_method_errno(m, -EINVAL, NULL);
884 r = sd_bus_get_name_creds(a, name, 0, NULL);
885 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
886 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
888 return synthetic_reply_method_errno(m, r, NULL);
890 r = sd_bus_message_new_method_call(
895 "org.freedesktop.DBus.Peer",
898 return synthetic_reply_method_errno(m, r, NULL);
900 r = sd_bus_send(a, msg, NULL);
902 return synthetic_reply_method_errno(m, r, NULL);
904 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
906 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
907 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
908 _cleanup_strv_free_ char **args = NULL;
910 if (!sd_bus_message_has_signature(m, "a{ss}"))
911 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
913 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
915 return synthetic_reply_method_errno(m, r, NULL);
917 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
918 _cleanup_free_ char *s = NULL;
922 r = sd_bus_message_read(m, "ss", &key, &value);
924 return synthetic_reply_method_errno(m, r, NULL);
926 s = strjoin(key, "=", value, NULL);
928 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
930 r = strv_extend(&args, s);
932 return synthetic_reply_method_errno(m, r, NULL);
934 r = sd_bus_message_exit_container(m);
936 return synthetic_reply_method_errno(m, r, NULL);
939 r = sd_bus_message_exit_container(m);
941 return synthetic_reply_method_errno(m, r, NULL);
944 return synthetic_reply_method_errno(m, -EINVAL, NULL);
946 r = sd_bus_message_new_method_call(
949 "org.freedesktop.systemd1",
950 "/org/freedesktop/systemd1",
951 "org.freedesktop.systemd1.Manager",
954 return synthetic_reply_method_errno(m, r, NULL);
956 r = sd_bus_message_append_strv(msg, args);
958 return synthetic_reply_method_errno(m, r, NULL);
960 r = sd_bus_call(a, msg, 0, NULL, NULL);
962 return synthetic_reply_method_errno(m, r, NULL);
964 return synthetic_reply_method_return(m, NULL);
967 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
971 return synthetic_reply_method_errno(m, r, &error);
975 static int handle_policy_error(sd_bus_message *m, int r) {
976 if (r == -ESRCH || r == -ENXIO)
977 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
982 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
992 if (from->is_kernel) {
993 uid_t sender_uid = UID_INVALID;
994 gid_t sender_gid = GID_INVALID;
995 char **sender_names = NULL;
996 bool granted = false;
998 /* Driver messages are always OK */
999 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
1002 /* The message came from the kernel, and is sent to our legacy client. */
1003 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
1005 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
1006 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
1008 /* First check whether the sender can send the message to our name */
1009 if (set_isempty(owned_names)) {
1010 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
1016 SET_FOREACH(n, owned_names, i)
1017 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1024 /* Then check whether us (the recipient) can receive from the sender's name */
1025 if (strv_isempty(sender_names)) {
1026 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1031 STRV_FOREACH(n, sender_names) {
1032 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1038 /* Return an error back to the caller */
1039 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1040 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1042 /* Return 1, indicating that the message shall not be processed any further */
1046 if (to->is_kernel) {
1047 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1048 uid_t destination_uid = UID_INVALID;
1049 gid_t destination_gid = GID_INVALID;
1050 const char *destination_unique = NULL;
1051 char **destination_names = NULL;
1052 bool granted = false;
1054 /* Driver messages are always OK */
1055 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1058 /* The message came from the legacy client, and is sent to kdbus. */
1059 if (m->destination) {
1060 r = bus_get_name_creds_kdbus(to, m->destination,
1061 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1062 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1063 true, &destination_creds);
1065 return handle_policy_error(m, r);
1067 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1069 return handle_policy_error(m, r);
1071 sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1073 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1074 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1077 /* First check if we (the sender) can send to this name */
1078 if (strv_isempty(destination_names)) {
1079 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1084 STRV_FOREACH(n, destination_names) {
1085 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1087 /* If we made a receiver decision,
1088 then remember which name's policy
1089 we used, and to which unique ID it
1090 mapped when we made the
1091 decision. Then, let's pass this to
1092 the kernel when sending the
1093 message, so that it refuses the
1094 operation should the name and
1095 unique ID not map to each other
1098 r = free_and_strdup(&m->destination_ptr, *n);
1102 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1112 /* Then check if the recipient can receive from our name */
1114 if (set_isempty(owned_names)) {
1115 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1121 SET_FOREACH(n, owned_names, i)
1122 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1127 /* Return an error back to the caller */
1128 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1129 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1131 /* Return 1, indicating that the message shall not be processed any further */
1138 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1139 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1148 /* As reaction to hello we need to respond with two messages:
1149 * the callback reply and the NameAcquired for the unique
1150 * name, since hello is otherwise obsolete on kdbus. */
1153 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1154 streq_ptr(m->destination, "org.freedesktop.DBus");
1161 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1166 log_error("Got duplicate hello, aborting.");
1175 r = sd_bus_message_new_method_return(m, &n);
1177 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1179 r = sd_bus_message_append(n, "s", a->unique_name);
1181 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1183 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1185 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1187 r = bus_seal_synthetic_message(b, n);
1189 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1191 r = sd_bus_send(b, n, NULL);
1193 return log_error_errno(r, "Failed to send HELLO reply: %m");
1195 n = sd_bus_message_unref(n);
1196 r = sd_bus_message_new_signal(
1199 "/org/freedesktop/DBus",
1200 "org.freedesktop.DBus",
1203 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1205 r = sd_bus_message_append(n, "s", a->unique_name);
1207 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1209 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1211 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1213 r = bus_seal_synthetic_message(b, n);
1215 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1217 r = sd_bus_send(b, n, NULL);
1219 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1224 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1225 char **well_known = NULL;
1235 /* We will change the sender of messages from the bus driver
1236 * so that they originate from the bus driver. This is a
1237 * speciality originating from dbus1, where the bus driver did
1238 * not have a unique id, but only the well-known name. */
1240 c = sd_bus_message_get_creds(m);
1244 r = sd_bus_creds_get_well_known_names(c, &well_known);
1248 if (strv_contains(well_known, "org.freedesktop.DBus"))
1249 m->sender = "org.freedesktop.DBus";
1254 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
1258 if (!mac_smack_use())
1261 if (new_label && its_pid > 0)
1262 r = mac_smack_apply_pid(its_pid, new_label);
1264 k = drop_capability(CAP_MAC_ADMIN);
1265 return r < 0 ? r : k;
1271 int main(int argc, char *argv[]) {
1273 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1274 sd_id128_t server_id;
1275 int r, in_fd, out_fd;
1276 bool got_hello = false;
1278 struct ucred ucred = {};
1279 _cleanup_free_ char *peersec = NULL;
1280 Policy policy_buffer = {}, *policy = NULL;
1281 _cleanup_set_free_free_ Set *owned_names = NULL;
1283 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1284 log_parse_environment();
1287 r = parse_argv(argc, argv);
1291 r = sd_listen_fds(0);
1293 in_fd = STDIN_FILENO;
1294 out_fd = STDOUT_FILENO;
1295 } else if (r == 1) {
1296 in_fd = SD_LISTEN_FDS_START;
1297 out_fd = SD_LISTEN_FDS_START;
1299 log_error("Illegal number of file descriptors passed");
1304 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1305 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1308 (void) getpeercred(in_fd, &ucred);
1309 (void) getpeersec(in_fd, &peersec);
1311 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
1313 log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
1316 if (arg_drop_privileges) {
1317 const char *user = "systemd-bus-proxy";
1321 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1323 log_error_errno(r, "Cannot resolve user name %s: %m", user);
1327 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1332 owned_names = set_new(&string_hash_ops);
1340 log_error_errno(r, "Failed to allocate bus: %m");
1344 r = sd_bus_set_description(a, "sd-proxy");
1346 log_error_errno(r, "Failed to set bus name: %m");
1350 r = sd_bus_set_address(a, arg_address);
1352 log_error_errno(r, "Failed to set address to connect to: %m");
1356 r = sd_bus_negotiate_fds(a, is_unix);
1358 log_error_errno(r, "Failed to set FD negotiation: %m");
1362 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1364 log_error_errno(r, "Failed to set credential negotiation: %m");
1368 if (ucred.pid > 0) {
1369 a->fake_pids.pid = ucred.pid;
1370 a->fake_pids_valid = true;
1372 a->fake_creds.uid = ucred.uid;
1373 a->fake_creds.euid = UID_INVALID;
1374 a->fake_creds.suid = UID_INVALID;
1375 a->fake_creds.fsuid = UID_INVALID;
1376 a->fake_creds.gid = ucred.gid;
1377 a->fake_creds.egid = GID_INVALID;
1378 a->fake_creds.sgid = GID_INVALID;
1379 a->fake_creds.fsgid = GID_INVALID;
1380 a->fake_creds_valid = true;
1384 a->fake_label = peersec;
1388 a->manual_peer_interface = true;
1390 r = sd_bus_start(a);
1392 log_error_errno(r, "Failed to start bus client: %m");
1396 r = sd_bus_get_bus_id(a, &server_id);
1398 log_error_errno(r, "Failed to get server ID: %m");
1403 if (!arg_configuration) {
1406 r = sd_bus_get_scope(a, &scope);
1408 log_error_errno(r, "Couldn't determine bus scope: %m");
1412 if (streq(scope, "system"))
1413 arg_configuration = strv_new(
1414 "/etc/dbus-1/system.conf",
1415 "/etc/dbus-1/system.d/",
1416 "/etc/dbus-1/system-local.conf",
1418 else if (streq(scope, "user"))
1419 arg_configuration = strv_new(
1420 "/etc/dbus-1/session.conf",
1421 "/etc/dbus-1/session.d/",
1422 "/etc/dbus-1/session-local.conf",
1425 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1429 if (!arg_configuration) {
1435 r = policy_load(&policy_buffer, arg_configuration);
1437 log_error_errno(r, "Failed to load policy: %m");
1441 policy = &policy_buffer;
1442 /* policy_dump(policy); */
1444 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1445 r = log_error_errno(EPERM, "Policy denied connection.");
1452 log_error_errno(r, "Failed to allocate bus: %m");
1456 r = sd_bus_set_fd(b, in_fd, out_fd);
1458 log_error_errno(r, "Failed to set fds: %m");
1462 r = sd_bus_set_server(b, 1, server_id);
1464 log_error_errno(r, "Failed to set server mode: %m");
1468 r = sd_bus_negotiate_fds(b, is_unix);
1470 log_error_errno(r, "Failed to set FD negotiation: %m");
1474 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1476 log_error_errno(r, "Failed to set credential negotiation: %m");
1480 r = sd_bus_set_anonymous(b, true);
1482 log_error_errno(r, "Failed to set anonymous authentication: %m");
1486 b->manual_peer_interface = true;
1488 r = sd_bus_start(b);
1490 log_error_errno(r, "Failed to start bus client: %m");
1494 r = rename_service(a, b);
1496 log_debug_errno(r, "Failed to rename process: %m");
1499 _cleanup_free_ char *match = NULL;
1502 r = sd_bus_get_unique_name(a, &unique);
1504 log_error_errno(r, "Failed to get unique name: %m");
1508 match = strjoin("type='signal',"
1509 "sender='org.freedesktop.DBus',"
1510 "path='/org/freedesktop/DBus',"
1511 "interface='org.freedesktop.DBus',"
1512 "member='NameOwnerChanged',"
1522 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1524 log_error_errno(r, "Failed to add match for NameLost: %m");
1529 match = strjoin("type='signal',"
1530 "sender='org.freedesktop.DBus',"
1531 "path='/org/freedesktop/DBus',"
1532 "interface='org.freedesktop.DBus',"
1533 "member='NameOwnerChanged',"
1543 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1545 log_error_errno(r, "Failed to add match for NameAcquired: %m");
1551 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1552 int events_a, events_b, fd;
1553 uint64_t timeout_a, timeout_b, t;
1554 struct timespec _ts, *ts;
1555 struct pollfd *pollfd;
1559 /* Read messages from bus, to pass them on to our client */
1561 r = sd_bus_process(a, &m);
1563 /* treat 'connection reset by peer' as clean exit condition */
1564 if (r == -ECONNRESET)
1567 log_error_errno(r, "Failed to process bus a: %m");
1573 bool processed = false;
1575 /* We officially got EOF, let's quit */
1576 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1581 k = synthesize_name_acquired(a, b, m);
1584 log_error_errno(r, "Failed to synthesize message: %m");
1591 k = process_policy(a, b, m, policy, &ucred, owned_names);
1594 log_error_errno(r, "Failed to process policy: %m");
1603 k = sd_bus_send(b, m, NULL);
1605 if (k == -ECONNRESET)
1609 log_error_errno(r, "Failed to send message to client: %m");
1622 /* Read messages from our client, to pass them on to the bus */
1623 r = sd_bus_process(b, &m);
1625 /* treat 'connection reset by peer' as clean exit condition */
1626 if (r == -ECONNRESET)
1629 log_error_errno(r, "Failed to process bus b: %m");
1635 bool processed = false;
1637 /* We officially got EOF, let's quit */
1638 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1643 k = process_hello(a, b, m, &got_hello);
1646 log_error_errno(r, "Failed to process HELLO: %m");
1654 k = process_driver(a, b, m, policy, &ucred, owned_names);
1657 log_error_errno(r, "Failed to process driver calls: %m");
1668 k = process_policy(b, a, m, policy, &ucred, owned_names);
1671 log_error_errno(r, "Failed to process policy: %m");
1680 k = sd_bus_send(a, m, NULL);
1683 /* The name database changed since the policy check, hence let's check again */
1685 else if (k == -ECONNRESET)
1689 log_error_errno(r, "Failed to send message to bus: %m");
1705 fd = sd_bus_get_fd(a);
1707 log_error_errno(r, "Failed to get fd: %m");
1711 events_a = sd_bus_get_events(a);
1713 log_error_errno(r, "Failed to get events mask: %m");
1717 r = sd_bus_get_timeout(a, &timeout_a);
1719 log_error_errno(r, "Failed to get timeout: %m");
1723 events_b = sd_bus_get_events(b);
1725 log_error_errno(r, "Failed to get events mask: %m");
1729 r = sd_bus_get_timeout(b, &timeout_b);
1731 log_error_errno(r, "Failed to get timeout: %m");
1736 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1739 if (t == (uint64_t) -1)
1744 nw = now(CLOCK_MONOTONIC);
1750 ts = timespec_store(&_ts, t);
1753 pollfd = (struct pollfd[3]) {
1754 {.fd = fd, .events = events_a, },
1755 {.fd = in_fd, .events = events_b & POLLIN, },
1756 {.fd = out_fd, .events = events_b & POLLOUT, }
1759 r = ppoll(pollfd, 3, ts, NULL);
1761 log_error_errno(errno, "ppoll() failed: %m");
1769 "STATUS=Shutting down.");
1771 policy_free(&policy_buffer);
1772 strv_free(arg_configuration);
1775 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;