LCOV - code coverage report
Current view: top level - core - dbus.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 29 619 4.7 %
Date: 2015-07-29 18:47:03 Functions: 3 37 8.1 %

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

Generated by: LCOV version 1.11