LCOV - code coverage report
Current view: top level - core - dbus.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 121 712 17.0 %
Date: 2019-08-22 15:41:25 Functions: 13 42 31.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <sys/epoll.h>
       5             : #include <unistd.h>
       6             : 
       7             : #include "sd-bus.h"
       8             : 
       9             : #include "alloc-util.h"
      10             : #include "bus-common-errors.h"
      11             : #include "bus-error.h"
      12             : #include "bus-internal.h"
      13             : #include "bus-util.h"
      14             : #include "dbus-automount.h"
      15             : #include "dbus-cgroup.h"
      16             : #include "dbus-device.h"
      17             : #include "dbus-execute.h"
      18             : #include "dbus-job.h"
      19             : #include "dbus-kill.h"
      20             : #include "dbus-manager.h"
      21             : #include "dbus-mount.h"
      22             : #include "dbus-path.h"
      23             : #include "dbus-scope.h"
      24             : #include "dbus-service.h"
      25             : #include "dbus-slice.h"
      26             : #include "dbus-socket.h"
      27             : #include "dbus-swap.h"
      28             : #include "dbus-target.h"
      29             : #include "dbus-timer.h"
      30             : #include "dbus-unit.h"
      31             : #include "dbus.h"
      32             : #include "fd-util.h"
      33             : #include "fs-util.h"
      34             : #include "log.h"
      35             : #include "missing.h"
      36             : #include "mkdir.h"
      37             : #include "process-util.h"
      38             : #include "selinux-access.h"
      39             : #include "serialize.h"
      40             : #include "service.h"
      41             : #include "special.h"
      42             : #include "string-util.h"
      43             : #include "strv.h"
      44             : #include "strxcpyx.h"
      45             : #include "user-util.h"
      46             : 
      47             : #define CONNECTIONS_MAX 4096
      48             : 
      49             : static void destroy_bus(Manager *m, sd_bus **bus);
      50             : 
      51           0 : int bus_send_pending_reload_message(Manager *m) {
      52             :         int r;
      53             : 
      54           0 :         assert(m);
      55             : 
      56           0 :         if (!m->pending_reload_message)
      57           0 :                 return 0;
      58             : 
      59             :         /* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting
      60             :          * to queue another message. */
      61             : 
      62           0 :         r = sd_bus_send(NULL, m->pending_reload_message, NULL);
      63           0 :         if (r < 0)
      64           0 :                 log_warning_errno(r, "Failed to send queued message, ignoring: %m");
      65             : 
      66           0 :         m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message);
      67             : 
      68           0 :         return 0;
      69             : }
      70             : 
      71           0 : int bus_forward_agent_released(Manager *m, const char *path) {
      72             :         int r;
      73             : 
      74           0 :         assert(m);
      75           0 :         assert(path);
      76             : 
      77           0 :         if (!MANAGER_IS_SYSTEM(m))
      78           0 :                 return 0;
      79             : 
      80           0 :         if (!m->system_bus)
      81           0 :                 return 0;
      82             : 
      83             :         /* If we are running a system instance we forward the agent message on the system bus, so that the user
      84             :          * instances get notified about this, too */
      85             : 
      86           0 :         r = sd_bus_emit_signal(m->system_bus,
      87             :                                "/org/freedesktop/systemd1/agent",
      88             :                                "org.freedesktop.systemd1.Agent",
      89             :                                "Released",
      90             :                                "s", path);
      91           0 :         if (r < 0)
      92           0 :                 return log_debug_errno(r, "Failed to propagate agent release message: %m");
      93             : 
      94           0 :         return 1;
      95             : }
      96             : 
      97           0 : static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
      98           0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
      99           0 :         Manager *m = userdata;
     100             :         const char *cgroup;
     101             :         uid_t sender_uid;
     102             :         int r;
     103             : 
     104           0 :         assert(message);
     105           0 :         assert(m);
     106             : 
     107             :         /* only accept org.freedesktop.systemd1.Agent from UID=0 */
     108           0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
     109           0 :         if (r < 0)
     110           0 :                 return r;
     111             : 
     112           0 :         r = sd_bus_creds_get_euid(creds, &sender_uid);
     113           0 :         if (r < 0 || sender_uid != 0)
     114           0 :                 return 0;
     115             : 
     116             :         /* parse 'cgroup-empty' notification */
     117           0 :         r = sd_bus_message_read(message, "s", &cgroup);
     118           0 :         if (r < 0) {
     119           0 :                 bus_log_parse_error(r);
     120           0 :                 return 0;
     121             :         }
     122             : 
     123           0 :         manager_notify_cgroup_empty(m, cgroup);
     124           0 :         return 0;
     125             : }
     126             : 
     127           0 : static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     128           0 :         Manager *m = userdata;
     129             :         sd_bus *bus;
     130             : 
     131           0 :         assert(message);
     132           0 :         assert(m);
     133           0 :         assert_se(bus = sd_bus_message_get_bus(message));
     134             : 
     135           0 :         if (bus == m->api_bus)
     136           0 :                 bus_done_api(m);
     137           0 :         if (bus == m->system_bus)
     138           0 :                 bus_done_system(m);
     139             : 
     140           0 :         if (set_remove(m->private_buses, bus)) {
     141           0 :                 log_debug("Got disconnect on private connection.");
     142           0 :                 destroy_bus(m, &bus);
     143             :         }
     144             : 
     145           0 :         return 0;
     146             : }
     147             : 
     148           0 : static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
     149           0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     150           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     151           0 :         Manager *m = userdata;
     152             :         const char *name;
     153             :         Unit *u;
     154             :         int r;
     155             : 
     156           0 :         assert(message);
     157           0 :         assert(m);
     158             : 
     159           0 :         r = sd_bus_message_read(message, "s", &name);
     160           0 :         if (r < 0) {
     161           0 :                 bus_log_parse_error(r);
     162           0 :                 return 0;
     163             :         }
     164             : 
     165           0 :         if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
     166           0 :             manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
     167           0 :                 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
     168           0 :                 goto failed;
     169             :         }
     170             : 
     171           0 :         r = manager_load_unit(m, name, NULL, &error, &u);
     172           0 :         if (r < 0)
     173           0 :                 goto failed;
     174             : 
     175           0 :         if (u->refuse_manual_start) {
     176           0 :                 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
     177           0 :                 goto failed;
     178             :         }
     179             : 
     180           0 :         r = manager_add_job(m, JOB_START, u, JOB_REPLACE, NULL, &error, NULL);
     181           0 :         if (r < 0)
     182           0 :                 goto failed;
     183             : 
     184             :         /* Successfully queued, that's it for us */
     185           0 :         return 0;
     186             : 
     187           0 : failed:
     188           0 :         if (!sd_bus_error_is_set(&error))
     189           0 :                 sd_bus_error_set_errno(&error, r);
     190             : 
     191           0 :         log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
     192             : 
     193           0 :         r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
     194           0 :         if (r < 0) {
     195           0 :                 bus_log_create_error(r);
     196           0 :                 return 0;
     197             :         }
     198             : 
     199           0 :         r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
     200           0 :         if (r < 0) {
     201           0 :                 bus_log_create_error(r);
     202           0 :                 return 0;
     203             :         }
     204             : 
     205           0 :         r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL);
     206           0 :         if (r < 0)
     207           0 :                 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
     208             : 
     209           0 :         return 0;
     210             : }
     211             : 
     212             : #if HAVE_SELINUX
     213           0 : static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     214           0 :         Manager *m = userdata;
     215             :         const char *verb, *path;
     216           0 :         Unit *u = NULL;
     217             :         Job *j;
     218             :         int r;
     219             : 
     220           0 :         assert(message);
     221             : 
     222             :         /* Our own method calls are all protected individually with
     223             :          * selinux checks, but the built-in interfaces need to be
     224             :          * protected too. */
     225             : 
     226           0 :         if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
     227           0 :                 verb = "reload";
     228           0 :         else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
     229           0 :                  sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
     230           0 :                  sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
     231           0 :                  sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
     232           0 :                 verb = "status";
     233             :         else
     234           0 :                 return 0;
     235             : 
     236           0 :         path = sd_bus_message_get_path(message);
     237             : 
     238           0 :         if (object_path_startswith("/org/freedesktop/systemd1", path)) {
     239           0 :                 r = mac_selinux_access_check(message, verb, error);
     240           0 :                 if (r < 0)
     241           0 :                         return r;
     242             : 
     243           0 :                 return 0;
     244             :         }
     245             : 
     246           0 :         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
     247           0 :                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     248             :                 pid_t pid;
     249             : 
     250           0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
     251           0 :                 if (r < 0)
     252           0 :                         return 0;
     253             : 
     254           0 :                 r = sd_bus_creds_get_pid(creds, &pid);
     255           0 :                 if (r < 0)
     256           0 :                         return 0;
     257             : 
     258           0 :                 u = manager_get_unit_by_pid(m, pid);
     259             :         } else {
     260           0 :                 r = manager_get_job_from_dbus_path(m, path, &j);
     261           0 :                 if (r >= 0)
     262           0 :                         u = j->unit;
     263             :                 else
     264           0 :                         manager_load_unit_from_dbus_path(m, path, NULL, &u);
     265             :         }
     266           0 :         if (!u)
     267           0 :                 return 0;
     268             : 
     269           0 :         r = mac_selinux_unit_access_check(u, message, verb, error);
     270           0 :         if (r < 0)
     271           0 :                 return r;
     272             : 
     273           0 :         return 0;
     274             : }
     275             : #endif
     276             : 
     277           0 : static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     278           0 :         Manager *m = userdata;
     279             :         Job *j;
     280             :         int r;
     281             : 
     282           0 :         assert(bus);
     283           0 :         assert(path);
     284           0 :         assert(interface);
     285           0 :         assert(found);
     286           0 :         assert(m);
     287             : 
     288           0 :         r = manager_get_job_from_dbus_path(m, path, &j);
     289           0 :         if (r < 0)
     290           0 :                 return 0;
     291             : 
     292           0 :         *found = j;
     293           0 :         return 1;
     294             : }
     295             : 
     296           0 : static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
     297           0 :         Unit *u = NULL;  /* just to appease gcc, initialization is not really necessary */
     298             :         int r;
     299             : 
     300           0 :         assert(m);
     301           0 :         assert(bus);
     302           0 :         assert(path);
     303             : 
     304           0 :         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
     305           0 :                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     306             :                 sd_bus_message *message;
     307             :                 pid_t pid;
     308             : 
     309           0 :                 message = sd_bus_get_current_message(bus);
     310           0 :                 if (!message)
     311           0 :                         return 0;
     312             : 
     313           0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
     314           0 :                 if (r < 0)
     315           0 :                         return r;
     316             : 
     317           0 :                 r = sd_bus_creds_get_pid(creds, &pid);
     318           0 :                 if (r < 0)
     319           0 :                         return r;
     320             : 
     321           0 :                 u = manager_get_unit_by_pid(m, pid);
     322           0 :                 if (!u)
     323           0 :                         return 0;
     324             :         } else {
     325           0 :                 r = manager_load_unit_from_dbus_path(m, path, error, &u);
     326           0 :                 if (r < 0)
     327           0 :                         return 0;
     328           0 :                 assert(u);
     329             :         }
     330             : 
     331           0 :         *unit = u;
     332           0 :         return 1;
     333             : }
     334             : 
     335           0 : static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     336           0 :         Manager *m = userdata;
     337             : 
     338           0 :         assert(bus);
     339           0 :         assert(path);
     340           0 :         assert(interface);
     341           0 :         assert(found);
     342           0 :         assert(m);
     343             : 
     344           0 :         return find_unit(m, bus, path, (Unit**) found, error);
     345             : }
     346             : 
     347           0 : static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     348           0 :         Manager *m = userdata;
     349             :         Unit *u;
     350             :         int r;
     351             : 
     352           0 :         assert(bus);
     353           0 :         assert(path);
     354           0 :         assert(interface);
     355           0 :         assert(found);
     356           0 :         assert(m);
     357             : 
     358           0 :         r = find_unit(m, bus, path, &u, error);
     359           0 :         if (r <= 0)
     360           0 :                 return r;
     361             : 
     362           0 :         if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
     363           0 :                 return 0;
     364             : 
     365           0 :         *found = u;
     366           0 :         return 1;
     367             : }
     368             : 
     369           0 : static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     370           0 :         Manager *m = userdata;
     371             :         Unit *u;
     372             :         int r;
     373             : 
     374           0 :         assert(bus);
     375           0 :         assert(path);
     376           0 :         assert(interface);
     377           0 :         assert(found);
     378           0 :         assert(m);
     379             : 
     380           0 :         r = find_unit(m, bus, path, &u, error);
     381           0 :         if (r <= 0)
     382           0 :                 return r;
     383             : 
     384           0 :         if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
     385           0 :                 return 0;
     386             : 
     387           0 :         if (!UNIT_HAS_CGROUP_CONTEXT(u))
     388           0 :                 return 0;
     389             : 
     390           0 :         *found = u;
     391           0 :         return 1;
     392             : }
     393             : 
     394           0 : static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     395           0 :         Manager *m = userdata;
     396             :         CGroupContext *c;
     397             :         Unit *u;
     398             :         int r;
     399             : 
     400           0 :         assert(bus);
     401           0 :         assert(path);
     402           0 :         assert(interface);
     403           0 :         assert(found);
     404           0 :         assert(m);
     405             : 
     406           0 :         r = find_unit(m, bus, path, &u, error);
     407           0 :         if (r <= 0)
     408           0 :                 return r;
     409             : 
     410           0 :         if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
     411           0 :                 return 0;
     412             : 
     413           0 :         c = unit_get_cgroup_context(u);
     414           0 :         if (!c)
     415           0 :                 return 0;
     416             : 
     417           0 :         *found = c;
     418           0 :         return 1;
     419             : }
     420             : 
     421           0 : static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     422           0 :         Manager *m = userdata;
     423             :         ExecContext *c;
     424             :         Unit *u;
     425             :         int r;
     426             : 
     427           0 :         assert(bus);
     428           0 :         assert(path);
     429           0 :         assert(interface);
     430           0 :         assert(found);
     431           0 :         assert(m);
     432             : 
     433           0 :         r = find_unit(m, bus, path, &u, error);
     434           0 :         if (r <= 0)
     435           0 :                 return r;
     436             : 
     437           0 :         if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
     438           0 :                 return 0;
     439             : 
     440           0 :         c = unit_get_exec_context(u);
     441           0 :         if (!c)
     442           0 :                 return 0;
     443             : 
     444           0 :         *found = c;
     445           0 :         return 1;
     446             : }
     447             : 
     448           0 : static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     449           0 :         Manager *m = userdata;
     450             :         KillContext *c;
     451             :         Unit *u;
     452             :         int r;
     453             : 
     454           0 :         assert(bus);
     455           0 :         assert(path);
     456           0 :         assert(interface);
     457           0 :         assert(found);
     458           0 :         assert(m);
     459             : 
     460           0 :         r = find_unit(m, bus, path, &u, error);
     461           0 :         if (r <= 0)
     462           0 :                 return r;
     463             : 
     464           0 :         if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
     465           0 :                 return 0;
     466             : 
     467           0 :         c = unit_get_kill_context(u);
     468           0 :         if (!c)
     469           0 :                 return 0;
     470             : 
     471           0 :         *found = c;
     472           0 :         return 1;
     473             : }
     474             : 
     475           0 : static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
     476           0 :         _cleanup_strv_free_ char **l = NULL;
     477           0 :         Manager *m = userdata;
     478           0 :         unsigned k = 0;
     479             :         Iterator i;
     480             :         Job *j;
     481             : 
     482           0 :         l = new0(char*, hashmap_size(m->jobs)+1);
     483           0 :         if (!l)
     484           0 :                 return -ENOMEM;
     485             : 
     486           0 :         HASHMAP_FOREACH(j, m->jobs, i) {
     487           0 :                 l[k] = job_dbus_path(j);
     488           0 :                 if (!l[k])
     489           0 :                         return -ENOMEM;
     490             : 
     491           0 :                 k++;
     492             :         }
     493             : 
     494           0 :         assert(hashmap_size(m->jobs) == k);
     495             : 
     496           0 :         *nodes = TAKE_PTR(l);
     497             : 
     498           0 :         return k;
     499             : }
     500             : 
     501           0 : static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
     502           0 :         _cleanup_strv_free_ char **l = NULL;
     503           0 :         Manager *m = userdata;
     504           0 :         unsigned k = 0;
     505             :         Iterator i;
     506             :         Unit *u;
     507             : 
     508           0 :         l = new0(char*, hashmap_size(m->units)+1);
     509           0 :         if (!l)
     510           0 :                 return -ENOMEM;
     511             : 
     512           0 :         HASHMAP_FOREACH(u, m->units, i) {
     513           0 :                 l[k] = unit_dbus_path(u);
     514           0 :                 if (!l[k])
     515           0 :                         return -ENOMEM;
     516             : 
     517           0 :                 k++;
     518             :         }
     519             : 
     520           0 :         *nodes = TAKE_PTR(l);
     521             : 
     522           0 :         return k;
     523             : }
     524             : 
     525           0 : static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
     526             :         UnitType t;
     527             :         int r;
     528             : 
     529           0 :         assert(m);
     530           0 :         assert(bus);
     531             : 
     532             : #if HAVE_SELINUX
     533           0 :         r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
     534           0 :         if (r < 0)
     535           0 :                 return log_error_errno(r, "Failed to add SELinux access filter: %m");
     536             : #endif
     537             : 
     538           0 :         r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
     539           0 :         if (r < 0)
     540           0 :                 return log_error_errno(r, "Failed to register Manager vtable: %m");
     541             : 
     542           0 :         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
     543           0 :         if (r < 0)
     544           0 :                 return log_error_errno(r, "Failed to register Job vtable: %m");
     545             : 
     546           0 :         r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
     547           0 :         if (r < 0)
     548           0 :                 return log_error_errno(r, "Failed to add job enumerator: %m");
     549             : 
     550           0 :         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
     551           0 :         if (r < 0)
     552           0 :                 return log_error_errno(r, "Failed to register Unit vtable: %m");
     553             : 
     554           0 :         r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
     555           0 :         if (r < 0)
     556           0 :                 return log_error_errno(r, "Failed to add job enumerator: %m");
     557             : 
     558           0 :         for (t = 0; t < _UNIT_TYPE_MAX; t++) {
     559             :                 const char *interface;
     560             : 
     561           0 :                 assert_se(interface = unit_dbus_interface_from_type(t));
     562             : 
     563           0 :                 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
     564           0 :                 if (r < 0)
     565           0 :                         return log_error_errno(r, "Failed to register type specific vtable for %s: %m", interface);
     566             : 
     567           0 :                 if (unit_vtable[t]->cgroup_context_offset > 0) {
     568           0 :                         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
     569           0 :                         if (r < 0)
     570           0 :                                 return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", interface);
     571             : 
     572           0 :                         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
     573           0 :                         if (r < 0)
     574           0 :                                 return log_error_errno(r, "Failed to register control group vtable for %s: %m", interface);
     575             :                 }
     576             : 
     577           0 :                 if (unit_vtable[t]->exec_context_offset > 0) {
     578           0 :                         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_exec_vtable, bus_exec_context_find, m);
     579           0 :                         if (r < 0)
     580           0 :                                 return log_error_errno(r, "Failed to register execute vtable for %s: %m", interface);
     581             :                 }
     582             : 
     583           0 :                 if (unit_vtable[t]->kill_context_offset > 0) {
     584           0 :                         r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_kill_vtable, bus_kill_context_find, m);
     585           0 :                         if (r < 0)
     586           0 :                                 return log_error_errno(r, "Failed to register kill vtable for %s: %m", interface);
     587             :                 }
     588             :         }
     589             : 
     590           0 :         return 0;
     591             : }
     592             : 
     593          13 : static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
     594             :         int r;
     595             : 
     596          13 :         assert(m);
     597          13 :         assert(bus);
     598             : 
     599          13 :         r = sd_bus_match_signal_async(
     600             :                         bus,
     601             :                         NULL,
     602             :                         "org.freedesktop.DBus.Local",
     603             :                         "/org/freedesktop/DBus/Local",
     604             :                         "org.freedesktop.DBus.Local",
     605             :                         "Disconnected",
     606             :                         signal_disconnected, NULL, m);
     607          13 :         if (r < 0)
     608           0 :                 return log_error_errno(r, "Failed to request match for Disconnected message: %m");
     609             : 
     610          13 :         return 0;
     611             : }
     612             : 
     613           0 : static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
     614           0 :         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
     615           0 :         _cleanup_close_ int nfd = -1;
     616           0 :         Manager *m = userdata;
     617             :         sd_id128_t id;
     618             :         int r;
     619             : 
     620           0 :         assert(s);
     621           0 :         assert(m);
     622             : 
     623           0 :         nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
     624           0 :         if (nfd < 0) {
     625           0 :                 if (ERRNO_IS_ACCEPT_AGAIN(errno))
     626           0 :                         return 0;
     627             : 
     628           0 :                 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
     629           0 :                 return 0;
     630             :         }
     631             : 
     632           0 :         if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
     633           0 :                 log_warning("Too many concurrent connections, refusing");
     634           0 :                 return 0;
     635             :         }
     636             : 
     637           0 :         r = set_ensure_allocated(&m->private_buses, NULL);
     638           0 :         if (r < 0) {
     639           0 :                 log_oom();
     640           0 :                 return 0;
     641             :         }
     642             : 
     643           0 :         r = sd_bus_new(&bus);
     644           0 :         if (r < 0) {
     645           0 :                 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
     646           0 :                 return 0;
     647             :         }
     648             : 
     649           0 :         (void) sd_bus_set_description(bus, "private-bus-connection");
     650             : 
     651           0 :         r = sd_bus_set_fd(bus, nfd, nfd);
     652           0 :         if (r < 0) {
     653           0 :                 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
     654           0 :                 return 0;
     655             :         }
     656             : 
     657           0 :         nfd = -1;
     658             : 
     659           0 :         r = bus_check_peercred(bus);
     660           0 :         if (r < 0) {
     661           0 :                 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
     662           0 :                 return 0;
     663             :         }
     664             : 
     665           0 :         assert_se(sd_id128_randomize(&id) >= 0);
     666             : 
     667           0 :         r = sd_bus_set_server(bus, 1, id);
     668           0 :         if (r < 0) {
     669           0 :                 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
     670           0 :                 return 0;
     671             :         }
     672             : 
     673           0 :         r = sd_bus_negotiate_creds(bus, 1,
     674             :                                    SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
     675             :                                    SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
     676             :                                    SD_BUS_CREDS_SELINUX_CONTEXT);
     677           0 :         if (r < 0) {
     678           0 :                 log_warning_errno(r, "Failed to enable credentials for new connection: %m");
     679           0 :                 return 0;
     680             :         }
     681             : 
     682           0 :         r = sd_bus_set_sender(bus, "org.freedesktop.systemd1");
     683           0 :         if (r < 0) {
     684           0 :                 log_warning_errno(r, "Failed to set direct connection sender: %m");
     685           0 :                 return 0;
     686             :         }
     687             : 
     688           0 :         r = sd_bus_start(bus);
     689           0 :         if (r < 0) {
     690           0 :                 log_warning_errno(r, "Failed to start new connection bus: %m");
     691           0 :                 return 0;
     692             :         }
     693             : 
     694           0 :         r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
     695           0 :         if (r < 0) {
     696           0 :                 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
     697           0 :                 return 0;
     698             :         }
     699             : 
     700           0 :         r = bus_setup_disconnected_match(m, bus);
     701           0 :         if (r < 0)
     702           0 :                 return 0;
     703             : 
     704           0 :         r = bus_setup_api_vtables(m, bus);
     705           0 :         if (r < 0) {
     706           0 :                 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
     707           0 :                 return 0;
     708             :         }
     709             : 
     710           0 :         r = set_put(m->private_buses, bus);
     711           0 :         if (r < 0) {
     712           0 :                 log_warning_errno(r, "Failed to add new connection bus to set: %m");
     713           0 :                 return 0;
     714             :         }
     715             : 
     716           0 :         bus = NULL;
     717             : 
     718           0 :         log_debug("Accepted new private connection.");
     719             : 
     720           0 :         return 0;
     721             : }
     722             : 
     723           1 : static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata) {
     724           1 :         _cleanup_strv_free_ char **names = NULL;
     725           1 :         Manager *m = userdata;
     726             :         const char *name;
     727             :         Iterator i;
     728             :         Unit *u;
     729             :         int r;
     730             : 
     731           1 :         assert(es);
     732           1 :         assert(m);
     733           1 :         assert(m->sync_bus_names_event_source == es);
     734             : 
     735             :         /* First things first, destroy the defer event so that we aren't triggered again */
     736           1 :         m->sync_bus_names_event_source = sd_event_source_unref(m->sync_bus_names_event_source);
     737             : 
     738             :         /* Let's see if there's anything to do still? */
     739           1 :         if (!m->api_bus)
     740           1 :                 return 0;
     741           0 :         if (hashmap_isempty(m->watch_bus))
     742           0 :                 return 0;
     743             : 
     744             :         /* OK, let's sync up the names. Let's see which names are currently on the bus. */
     745           0 :         r = sd_bus_list_names(m->api_bus, &names, NULL);
     746           0 :         if (r < 0)
     747           0 :                 return log_error_errno(r, "Failed to get initial list of names: %m");
     748             : 
     749             :         /* We have to synchronize the current bus names with the
     750             :          * list of active services. To do this, walk the list of
     751             :          * all units with bus names. */
     752           0 :         HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
     753           0 :                 Service *s = SERVICE(u);
     754             : 
     755           0 :                 assert(s);
     756             : 
     757           0 :                 if (!streq_ptr(s->bus_name, name)) {
     758           0 :                         log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name);
     759           0 :                         continue;
     760             :                 }
     761             : 
     762             :                 /* Check if a service's bus name is in the list of currently
     763             :                  * active names */
     764           0 :                 if (strv_contains(names, name)) {
     765           0 :                         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     766             :                         const char *unique;
     767             : 
     768             :                         /* If it is, determine its current owner */
     769           0 :                         r = sd_bus_get_name_creds(m->api_bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds);
     770           0 :                         if (r < 0) {
     771           0 :                                 log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name);
     772           0 :                                 continue;
     773             :                         }
     774             : 
     775           0 :                         r = sd_bus_creds_get_unique_name(creds, &unique);
     776           0 :                         if (r < 0) {
     777           0 :                                 log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name);
     778           0 :                                 continue;
     779             :                         }
     780             : 
     781             :                         /* Now, let's compare that to the previous bus owner, and
     782             :                          * if it's still the same, all is fine, so just don't
     783             :                          * bother the service. Otherwise, the name has apparently
     784             :                          * changed, so synthesize a name owner changed signal. */
     785             : 
     786           0 :                         if (!streq_ptr(unique, s->bus_name_owner))
     787           0 :                                 UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, unique);
     788             :                 } else {
     789             :                         /* So, the name we're watching is not on the bus.
     790             :                          * This either means it simply hasn't appeared yet,
     791             :                          * or it was lost during the daemon reload.
     792             :                          * Check if the service has a stored name owner,
     793             :                          * and synthesize a name loss signal in this case. */
     794             : 
     795           0 :                         if (s->bus_name_owner)
     796           0 :                                 UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, NULL);
     797             :                 }
     798             :         }
     799             : 
     800           0 :         return 0;
     801             : }
     802             : 
     803          13 : int manager_enqueue_sync_bus_names(Manager *m) {
     804             :         int r;
     805             : 
     806          13 :         assert(m);
     807             : 
     808             :         /* Enqueues a request to synchronize the bus names in a later event loop iteration. The callers generally don't
     809             :          * want us to invoke ->bus_name_owner_change() unit calls from their stack frames as this might result in event
     810             :          * dispatching on its own creating loops, hence we simply create a defer event for the event loop and exit. */
     811             : 
     812          13 :         if (m->sync_bus_names_event_source)
     813           0 :                 return 0;
     814             : 
     815          13 :         r = sd_event_add_defer(m->event, &m->sync_bus_names_event_source, manager_dispatch_sync_bus_names, m);
     816          13 :         if (r < 0)
     817           0 :                 return log_error_errno(r, "Failed to create bus name synchronization event: %m");
     818             : 
     819          13 :         r = sd_event_source_set_priority(m->sync_bus_names_event_source, SD_EVENT_PRIORITY_IDLE);
     820          13 :         if (r < 0)
     821           0 :                 return log_error_errno(r, "Failed to set event priority: %m");
     822             : 
     823          13 :         r = sd_event_source_set_enabled(m->sync_bus_names_event_source, SD_EVENT_ONESHOT);
     824          13 :         if (r < 0)
     825           0 :                 return log_error_errno(r, "Failed to set even to oneshot: %m");
     826             : 
     827          13 :         (void) sd_event_source_set_description(m->sync_bus_names_event_source, "manager-sync-bus-names");
     828          13 :         return 0;
     829             : }
     830             : 
     831           0 : static int bus_setup_api(Manager *m, sd_bus *bus) {
     832             :         Iterator i;
     833             :         char *name;
     834             :         Unit *u;
     835             :         int r;
     836             : 
     837           0 :         assert(m);
     838           0 :         assert(bus);
     839             : 
     840             :         /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
     841           0 :         r = sd_bus_negotiate_creds(bus, 1,
     842             :                                    SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
     843             :                                    SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
     844             :                                    SD_BUS_CREDS_SELINUX_CONTEXT);
     845           0 :         if (r < 0)
     846           0 :                 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
     847             : 
     848           0 :         r = bus_setup_api_vtables(m, bus);
     849           0 :         if (r < 0)
     850           0 :                 return r;
     851             : 
     852           0 :         HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
     853           0 :                 r = unit_install_bus_match(u, bus, name);
     854           0 :                 if (r < 0)
     855           0 :                         log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
     856             :         }
     857             : 
     858           0 :         r = sd_bus_match_signal_async(
     859             :                         bus,
     860             :                         NULL,
     861             :                         "org.freedesktop.DBus",
     862             :                         "/org/freedesktop/DBus",
     863             :                         "org.freedesktop.systemd1.Activator",
     864             :                         "ActivationRequest",
     865             :                         signal_activation_request, NULL, m);
     866           0 :         if (r < 0)
     867           0 :                 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
     868             : 
     869             :         /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
     870             :          * until after the new connection is set up and the name installed to allow clients to synchronously wait for
     871             :          * reexecution to finish */
     872           0 :         r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT, NULL, NULL);
     873           0 :         if (r < 0)
     874           0 :                 return log_error_errno(r, "Failed to request name: %m");
     875             : 
     876           0 :         log_debug("Successfully connected to API bus.");
     877             : 
     878           0 :         return 0;
     879             : }
     880             : 
     881           0 : int bus_init_api(Manager *m) {
     882           0 :         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
     883             :         int r;
     884             : 
     885           0 :         if (m->api_bus)
     886           0 :                 return 0;
     887             : 
     888             :         /* The API and system bus is the same if we are running in system mode */
     889           0 :         if (MANAGER_IS_SYSTEM(m) && m->system_bus)
     890           0 :                 bus = sd_bus_ref(m->system_bus);
     891             :         else {
     892           0 :                 if (MANAGER_IS_SYSTEM(m))
     893           0 :                         r = sd_bus_open_system_with_description(&bus, "bus-api-system");
     894             :                 else
     895           0 :                         r = sd_bus_open_user_with_description(&bus, "bus-api-user");
     896           0 :                 if (r < 0)
     897           0 :                         return log_error_errno(r, "Failed to connect to API bus: %m");
     898             : 
     899           0 :                 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
     900           0 :                 if (r < 0)
     901           0 :                         return log_error_errno(r, "Failed to attach API bus to event loop: %m");
     902             : 
     903           0 :                 r = bus_setup_disconnected_match(m, bus);
     904           0 :                 if (r < 0)
     905           0 :                         return r;
     906             :         }
     907             : 
     908           0 :         r = bus_setup_api(m, bus);
     909           0 :         if (r < 0)
     910           0 :                 return log_error_errno(r, "Failed to set up API bus: %m");
     911             : 
     912           0 :         m->api_bus = TAKE_PTR(bus);
     913             : 
     914           0 :         r = manager_enqueue_sync_bus_names(m);
     915           0 :         if (r < 0)
     916           0 :                 return r;
     917             : 
     918           0 :         return 0;
     919             : }
     920             : 
     921          13 : static int bus_setup_system(Manager *m, sd_bus *bus) {
     922             :         int r;
     923             : 
     924          13 :         assert(m);
     925          13 :         assert(bus);
     926             : 
     927             :         /* if we are a user instance we get the Released message via the system bus */
     928          13 :         if (MANAGER_IS_USER(m)) {
     929          13 :                 r = sd_bus_match_signal_async(
     930             :                                 bus,
     931             :                                 NULL,
     932             :                                 NULL,
     933             :                                 "/org/freedesktop/systemd1/agent",
     934             :                                 "org.freedesktop.systemd1.Agent",
     935             :                                 "Released",
     936             :                                 signal_agent_released, NULL, m);
     937          13 :                 if (r < 0)
     938           0 :                         log_warning_errno(r, "Failed to request Released match on system bus: %m");
     939             :         }
     940             : 
     941          13 :         log_debug("Successfully connected to system bus.");
     942          13 :         return 0;
     943             : }
     944             : 
     945          13 : int bus_init_system(Manager *m) {
     946          13 :         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
     947             :         int r;
     948             : 
     949          13 :         if (m->system_bus)
     950           0 :                 return 0;
     951             : 
     952             :         /* The API and system bus is the same if we are running in system mode */
     953          13 :         if (MANAGER_IS_SYSTEM(m) && m->api_bus)
     954           0 :                 bus = sd_bus_ref(m->api_bus);
     955             :         else {
     956          13 :                 r = sd_bus_open_system_with_description(&bus, "bus-system");
     957          13 :                 if (r < 0)
     958           0 :                         return log_error_errno(r, "Failed to connect to system bus: %m");
     959             : 
     960          13 :                 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
     961          13 :                 if (r < 0)
     962           0 :                         return log_error_errno(r, "Failed to attach system bus to event loop: %m");
     963             : 
     964          13 :                 r = bus_setup_disconnected_match(m, bus);
     965          13 :                 if (r < 0)
     966           0 :                         return r;
     967             :         }
     968             : 
     969          13 :         r = bus_setup_system(m, bus);
     970          13 :         if (r < 0)
     971           0 :                 return log_error_errno(r, "Failed to set up system bus: %m");
     972             : 
     973          13 :         m->system_bus = TAKE_PTR(bus);
     974             : 
     975          13 :         return 0;
     976             : }
     977             : 
     978          13 : int bus_init_private(Manager *m) {
     979          13 :         _cleanup_close_ int fd = -1;
     980          13 :         union sockaddr_union sa = {};
     981             :         sd_event_source *s;
     982             :         int r, salen;
     983             : 
     984          13 :         assert(m);
     985             : 
     986          13 :         if (m->private_listen_fd >= 0)
     987           0 :                 return 0;
     988             : 
     989          13 :         if (MANAGER_IS_SYSTEM(m)) {
     990             : 
     991             :                 /* We want the private bus only when running as init */
     992           0 :                 if (getpid_cached() != 1)
     993           0 :                         return 0;
     994             : 
     995           0 :                 salen = sockaddr_un_set_path(&sa.un, "/run/systemd/private");
     996             :         } else {
     997             :                 const char *e, *joined;
     998             : 
     999          13 :                 e = secure_getenv("XDG_RUNTIME_DIR");
    1000          13 :                 if (!e)
    1001           0 :                         return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
    1002             :                                                "XDG_RUNTIME_DIR is not set, refusing.");
    1003             : 
    1004          65 :                 joined = strjoina(e, "/systemd/private");
    1005          13 :                 salen = sockaddr_un_set_path(&sa.un, joined);
    1006             :         }
    1007          13 :         if (salen < 0)
    1008           0 :                 return log_error_errno(salen, "Can't set path for AF_UNIX socket to bind to: %m");
    1009             : 
    1010          13 :         (void) mkdir_parents_label(sa.un.sun_path, 0755);
    1011          13 :         (void) sockaddr_un_unlink(&sa.un);
    1012             : 
    1013          13 :         fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
    1014          13 :         if (fd < 0)
    1015           0 :                 return log_error_errno(errno, "Failed to allocate private socket: %m");
    1016             : 
    1017          13 :         r = bind(fd, &sa.sa, salen);
    1018          13 :         if (r < 0)
    1019           0 :                 return log_error_errno(errno, "Failed to bind private socket: %m");
    1020             : 
    1021          13 :         r = listen(fd, SOMAXCONN);
    1022          13 :         if (r < 0)
    1023           0 :                 return log_error_errno(errno, "Failed to make private socket listening: %m");
    1024             : 
    1025             :         /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
    1026          13 :         (void) touch(sa.un.sun_path);
    1027             : 
    1028          13 :         r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
    1029          13 :         if (r < 0)
    1030           0 :                 return log_error_errno(r, "Failed to allocate event source: %m");
    1031             : 
    1032          13 :         (void) sd_event_source_set_description(s, "bus-connection");
    1033             : 
    1034          13 :         m->private_listen_fd = TAKE_FD(fd);
    1035          13 :         m->private_listen_event_source = s;
    1036             : 
    1037          13 :         log_debug("Successfully created private D-Bus server.");
    1038             : 
    1039          13 :         return 0;
    1040             : }
    1041             : 
    1042        1790 : static void destroy_bus(Manager *m, sd_bus **bus) {
    1043             :         Iterator i;
    1044             :         Unit *u;
    1045             :         Job *j;
    1046             : 
    1047        1790 :         assert(m);
    1048        1790 :         assert(bus);
    1049             : 
    1050        1790 :         if (!*bus)
    1051        1777 :                 return;
    1052             : 
    1053             :         /* Make sure all bus slots watching names are released. */
    1054          13 :         HASHMAP_FOREACH(u, m->watch_bus, i) {
    1055           0 :                 if (!u->match_bus_slot)
    1056           0 :                         continue;
    1057             : 
    1058           0 :                 if (sd_bus_slot_get_bus(u->match_bus_slot) != *bus)
    1059           0 :                         continue;
    1060             : 
    1061           0 :                 u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
    1062             :         }
    1063             : 
    1064             :         /* Get rid of tracked clients on this bus */
    1065          13 :         if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
    1066           0 :                 m->subscribed = sd_bus_track_unref(m->subscribed);
    1067             : 
    1068          13 :         HASHMAP_FOREACH(j, m->jobs, i)
    1069           0 :                 if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
    1070           0 :                         j->bus_track = sd_bus_track_unref(j->bus_track);
    1071             : 
    1072          13 :         HASHMAP_FOREACH(u, m->units, i)
    1073           0 :                 if (u->bus_track && sd_bus_track_get_bus(u->bus_track) == *bus)
    1074           0 :                         u->bus_track = sd_bus_track_unref(u->bus_track);
    1075             : 
    1076             :         /* Get rid of queued message on this bus */
    1077          13 :         if (m->pending_reload_message && sd_bus_message_get_bus(m->pending_reload_message) == *bus)
    1078           0 :                 m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message);
    1079             : 
    1080             :         /* Possibly flush unwritten data, but only if we are
    1081             :          * unprivileged, since we don't want to sync here */
    1082          13 :         if (!MANAGER_IS_SYSTEM(m))
    1083          13 :                 sd_bus_flush(*bus);
    1084             : 
    1085             :         /* And destroy the object */
    1086          13 :         *bus = sd_bus_close_unref(*bus);
    1087             : }
    1088             : 
    1089        1776 : void bus_done_api(Manager *m) {
    1090        1776 :         destroy_bus(m, &m->api_bus);
    1091        1776 : }
    1092             : 
    1093          14 : void bus_done_system(Manager *m) {
    1094          14 :         destroy_bus(m, &m->system_bus);
    1095          14 : }
    1096             : 
    1097          14 : void bus_done_private(Manager *m) {
    1098             :         sd_bus *b;
    1099             : 
    1100          14 :         assert(m);
    1101             : 
    1102          14 :         while ((b = set_steal_first(m->private_buses)))
    1103           0 :                 destroy_bus(m, &b);
    1104             : 
    1105          14 :         m->private_buses = set_free(m->private_buses);
    1106             : 
    1107          14 :         m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
    1108          14 :         m->private_listen_fd = safe_close(m->private_listen_fd);
    1109          14 : }
    1110             : 
    1111          14 : void bus_done(Manager *m) {
    1112          14 :         assert(m);
    1113             : 
    1114          14 :         bus_done_api(m);
    1115          14 :         bus_done_system(m);
    1116          14 :         bus_done_private(m);
    1117             : 
    1118          14 :         assert(!m->subscribed);
    1119             : 
    1120          14 :         m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
    1121          14 :         bus_verify_polkit_async_registry_free(m->polkit_registry);
    1122          14 : }
    1123             : 
    1124           0 : int bus_fdset_add_all(Manager *m, FDSet *fds) {
    1125             :         Iterator i;
    1126             :         sd_bus *b;
    1127             :         int fd;
    1128             : 
    1129           0 :         assert(m);
    1130           0 :         assert(fds);
    1131             : 
    1132             :         /* When we are about to reexecute we add all D-Bus fds to the
    1133             :          * set to pass over to the newly executed systemd. They won't
    1134             :          * be used there however, except thatt they are closed at the
    1135             :          * very end of deserialization, those making it possible for
    1136             :          * clients to synchronously wait for systemd to reexec by
    1137             :          * simply waiting for disconnection */
    1138             : 
    1139           0 :         if (m->api_bus) {
    1140           0 :                 fd = sd_bus_get_fd(m->api_bus);
    1141           0 :                 if (fd >= 0) {
    1142           0 :                         fd = fdset_put_dup(fds, fd);
    1143           0 :                         if (fd < 0)
    1144           0 :                                 return fd;
    1145             :                 }
    1146             :         }
    1147             : 
    1148           0 :         SET_FOREACH(b, m->private_buses, i) {
    1149           0 :                 fd = sd_bus_get_fd(b);
    1150           0 :                 if (fd >= 0) {
    1151           0 :                         fd = fdset_put_dup(fds, fd);
    1152           0 :                         if (fd < 0)
    1153           0 :                                 return fd;
    1154             :                 }
    1155             :         }
    1156             : 
    1157             :         /* We don't offer any APIs on the system bus (well, unless it
    1158             :          * is the same as the API bus) hence we don't bother with it
    1159             :          * here */
    1160             : 
    1161           0 :         return 0;
    1162             : }
    1163             : 
    1164        2261 : int bus_foreach_bus(
    1165             :                 Manager *m,
    1166             :                 sd_bus_track *subscribed2,
    1167             :                 int (*send_message)(sd_bus *bus, void *userdata),
    1168             :                 void *userdata) {
    1169             : 
    1170             :         Iterator i;
    1171             :         sd_bus *b;
    1172        2261 :         int r, ret = 0;
    1173             : 
    1174             :         /* Send to all direct buses, unconditionally */
    1175        2261 :         SET_FOREACH(b, m->private_buses, i) {
    1176             : 
    1177             :                 /* Don't bother with enqueing these messages to clients that haven't started yet */
    1178           0 :                 if (sd_bus_is_ready(b) <= 0)
    1179           0 :                         continue;
    1180             : 
    1181           0 :                 r = send_message(b, userdata);
    1182           0 :                 if (r < 0)
    1183           0 :                         ret = r;
    1184             :         }
    1185             : 
    1186             :         /* Send to API bus, but only if somebody is subscribed */
    1187        2261 :         if (m->api_bus &&
    1188           0 :             (sd_bus_track_count(m->subscribed) > 0 ||
    1189           0 :              sd_bus_track_count(subscribed2) > 0)) {
    1190           0 :                 r = send_message(m->api_bus, userdata);
    1191           0 :                 if (r < 0)
    1192           0 :                         ret = r;
    1193             :         }
    1194             : 
    1195        2261 :         return ret;
    1196             : }
    1197             : 
    1198           0 : void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
    1199             :         const char *n;
    1200             : 
    1201           0 :         assert(f);
    1202           0 :         assert(prefix);
    1203             : 
    1204           0 :         for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
    1205             :                 int c, j;
    1206             : 
    1207           0 :                 c = sd_bus_track_count_name(t, n);
    1208           0 :                 for (j = 0; j < c; j++)
    1209           0 :                         (void) serialize_item(f, prefix, n);
    1210             :         }
    1211           0 : }
    1212             : 
    1213          13 : int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) {
    1214          13 :         int r = 0;
    1215             : 
    1216          13 :         assert(m);
    1217          13 :         assert(t);
    1218             : 
    1219          13 :         if (strv_isempty(l))
    1220          13 :                 return 0;
    1221             : 
    1222           0 :         if (!m->api_bus)
    1223           0 :                 return 0;
    1224             : 
    1225           0 :         if (!*t) {
    1226           0 :                 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
    1227           0 :                 if (r < 0)
    1228           0 :                         return r;
    1229             :         }
    1230             : 
    1231           0 :         r = sd_bus_track_set_recursive(*t, recursive);
    1232           0 :         if (r < 0)
    1233           0 :                 return r;
    1234             : 
    1235           0 :         return bus_track_add_name_many(*t, l);
    1236             : }
    1237             : 
    1238           0 : int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
    1239           0 :         return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error);
    1240             : }
    1241             : 
    1242           0 : int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
    1243           0 :         return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error);
    1244             : }
    1245             : 
    1246           0 : int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
    1247           0 :         return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error);
    1248             : }
    1249             : 
    1250           0 : int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
    1251           0 :         return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error);
    1252             : }
    1253             : 
    1254           0 : uint64_t manager_bus_n_queued_write(Manager *m) {
    1255           0 :         uint64_t c = 0;
    1256             :         Iterator i;
    1257             :         sd_bus *b;
    1258             :         int r;
    1259             : 
    1260             :         /* Returns the total number of messages queued for writing on all our direct and API buses. */
    1261             : 
    1262           0 :         SET_FOREACH(b, m->private_buses, i) {
    1263             :                 uint64_t k;
    1264             : 
    1265           0 :                 r = sd_bus_get_n_queued_write(b, &k);
    1266           0 :                 if (r < 0)
    1267           0 :                         log_debug_errno(r, "Failed to query queued messages for private bus: %m");
    1268             :                 else
    1269           0 :                         c += k;
    1270             :         }
    1271             : 
    1272           0 :         if (m->api_bus) {
    1273             :                 uint64_t k;
    1274             : 
    1275           0 :                 r = sd_bus_get_n_queued_write(m->api_bus, &k);
    1276           0 :                 if (r < 0)
    1277           0 :                         log_debug_errno(r, "Failed to query queued messages for API bus: %m");
    1278             :                 else
    1279           0 :                         c += k;
    1280             :         }
    1281             : 
    1282           0 :         return c;
    1283             : }
    1284             : 
    1285           0 : static void vtable_dump_bus_properties(FILE *f, const sd_bus_vtable *table) {
    1286             :         const sd_bus_vtable *i;
    1287             : 
    1288           0 :         for (i = table; i->type != _SD_BUS_VTABLE_END; i++) {
    1289           0 :                 if (!IN_SET(i->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY) ||
    1290           0 :                     (i->flags & (SD_BUS_VTABLE_DEPRECATED | SD_BUS_VTABLE_HIDDEN)) != 0)
    1291           0 :                         continue;
    1292             : 
    1293           0 :                 fprintf(f, "%s\n", i->x.property.member);
    1294             :         }
    1295           0 : }
    1296             : 
    1297           0 : void dump_bus_properties(FILE *f) {
    1298           0 :         assert(f);
    1299             : 
    1300           0 :         vtable_dump_bus_properties(f, bus_automount_vtable);
    1301           0 :         vtable_dump_bus_properties(f, bus_cgroup_vtable);
    1302           0 :         vtable_dump_bus_properties(f, bus_device_vtable);
    1303           0 :         vtable_dump_bus_properties(f, bus_exec_vtable);
    1304           0 :         vtable_dump_bus_properties(f, bus_job_vtable);
    1305           0 :         vtable_dump_bus_properties(f, bus_kill_vtable);
    1306           0 :         vtable_dump_bus_properties(f, bus_manager_vtable);
    1307           0 :         vtable_dump_bus_properties(f, bus_mount_vtable);
    1308           0 :         vtable_dump_bus_properties(f, bus_path_vtable);
    1309           0 :         vtable_dump_bus_properties(f, bus_scope_vtable);
    1310           0 :         vtable_dump_bus_properties(f, bus_service_vtable);
    1311           0 :         vtable_dump_bus_properties(f, bus_slice_vtable);
    1312           0 :         vtable_dump_bus_properties(f, bus_socket_vtable);
    1313           0 :         vtable_dump_bus_properties(f, bus_swap_vtable);
    1314           0 :         vtable_dump_bus_properties(f, bus_target_vtable);
    1315           0 :         vtable_dump_bus_properties(f, bus_timer_vtable);
    1316           0 :         vtable_dump_bus_properties(f, bus_unit_vtable);
    1317           0 :         vtable_dump_bus_properties(f, bus_unit_cgroup_vtable);
    1318           0 : }

Generated by: LCOV version 1.14