dbus.c revision 8f88ecf6232fe6c46eecafad7c421096bb29b617
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/***
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright 2010 Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen***/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <sys/epoll.h>
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen#include <errno.h>
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <unistd.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "sd-bus.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "log.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "strv.h"
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#include "mkdir.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "missing.h"
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include "dbus-unit.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "dbus-job.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "dbus-manager.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "dbus-execute.h"
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen#include "dbus-kill.h"
c6f7c917a1b494d4455800823472227463f87438Tom Gundersen#include "dbus-cgroup.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "special.h"
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier#include "dbus.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-error.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-common-errors.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "strxcpyx.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "bus-internal.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "selinux-access.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#define CONNECTIONS_MAX 4096
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersenstatic void destroy_bus(Manager *m, sd_bus **bus);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenint bus_send_queued_message(Manager *m) {
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen int r;
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(m);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (!m->queued_message)
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return 0;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek /* If we cannot get rid of this message we won't dispatch any
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek * D-Bus messages, so that we won't end up wanting to queue
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek * another message. */
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek r = sd_bus_send(NULL, m->queued_message, NULL);
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (r < 0)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen log_warning_errno(r, "Failed to send queued message: %m");
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen m->queued_message = sd_bus_message_unref(m->queued_message);
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersenstatic int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen Manager *m = userdata;
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen const char *cgroup;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen int r;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(message);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(m);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen r = sd_bus_message_read(message, "s", &cgroup);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (r < 0) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen bus_log_parse_error(r);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen }
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen manager_notify_cgroup_empty(m, cgroup);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* only forward to system bus if running as system instance */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (m->running_as != SYSTEMD_SYSTEM || !m->system_bus)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = sd_bus_message_rewind(message, 1);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r < 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen goto exit;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = sd_bus_send(m->system_bus, message, NULL);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenexit:
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (r < 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen log_warning_errno(r, "Failed to forward Released message: %m");
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Manager *m = userdata;
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering sd_bus *bus;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen assert(message);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen assert(m);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert_se(bus = sd_bus_message_get_bus(message));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (bus == m->api_bus)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen destroy_bus(m, &m->api_bus);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (bus == m->system_bus)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen destroy_bus(m, &m->system_bus);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (set_remove(m->private_buses, bus)) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen log_debug("Got disconnect on private connection.");
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen destroy_bus(m, &bus);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen }
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenstatic int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen const char *name, *old_owner, *new_owner;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen Manager *m = userdata;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen int r;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(message);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(m);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (r < 0) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen bus_log_parse_error(r);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen }
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen manager_dispatch_bus_name_owner_changed(
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen m, name,
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen isempty(old_owner) ? NULL : old_owner,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen isempty(new_owner) ? NULL : new_owner);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
6e37cd2f4af8928d905203108a4331e375d7127cThomas Hindoe Paaboel Andersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersenstatic int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Manager *m = userdata;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen const char *name;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sd_bus *bus;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Unit *u;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen int r;
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(message);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(m);
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek assert_se(bus = sd_bus_message_get_bus(message));
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read(message, "s", &name);
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek if (r < 0) {
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek bus_log_parse_error(r);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek }
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen goto failed;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen }
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek r = manager_load_unit(m, name, NULL, &error, &u);
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek if (r < 0)
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek goto failed;
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek if (u->refuse_manual_start) {
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
98a375f6d5cac24eb80d6d4e00699851324afdecTom Gundersen goto failed;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen if (r < 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen goto failed;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* Successfully queued, that's it for us */
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenfailed:
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!sd_bus_error_is_set(&error))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sd_bus_error_set_errno(&error, r);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f8a0bb5285024b6ce372c3157e761e6543ebdcd2Andreas Henriksson log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (r < 0) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen bus_log_create_error(r);
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering return 0;
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering }
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering if (r < 0) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen bus_log_create_error(r);
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek return 0;
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek }
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (r < 0)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return log_error_errno(r, "Failed to respond with to bus activation request: %m");
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom Gundersen
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom Gundersen#ifdef HAVE_SELINUX
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Manager *m = userdata;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen const char *verb, *path;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen Unit *u = NULL;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen Job *j;
3f85ef0f05ffc51e19f86fb83a1c51e8e3cd6817Harald Hoyer int r;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen assert(message);
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek /* Our own method calls are all protected individually with
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * selinux checks, but the built-in interfaces need to be
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek * protected too. */
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen verb = "reload";
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen verb = "status";
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen else
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen path = sd_bus_message_get_path(message);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (object_path_startswith("/org/freedesktop/systemd1", path)) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = mac_selinux_access_check(message, verb, error);
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen if (r < 0)
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen return r;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen }
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen pid_t pid;
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen if (r < 0)
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen return 0;
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen r = sd_bus_creds_get_pid(creds, &pid);
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen if (r < 0)
eb7040ec50fbfe5aad9eaf305bd442a4a235abaaTom Gundersen return 0;
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen
9b1c2626cef16722603bded9bb52033aba34dd74Tom Gundersen u = manager_get_unit_by_pid(m, pid);
bf175aafd20c9ef974709ef12c5acf836121af33Tom Gundersen } else {
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen r = manager_get_job_from_dbus_path(m, path, &j);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen if (r >= 0)
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen u = j->unit;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen else
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen manager_load_unit_from_dbus_path(m, path, NULL, &u);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen }
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
dc75168823540076b354135f6e2de7a9a978fbcaZbigniew Jędrzejewski-Szmek if (!u)
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen return 0;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen r = mac_selinux_unit_access_check(u, message, verb, error);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen if (r < 0)
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen return r;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen return 0;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen}
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen#endif
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersenstatic int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen Manager *m = userdata;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen Job *j;
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen int r;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen assert(bus);
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen assert(path);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen assert(interface);
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen assert(found);
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen assert(m);
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = manager_get_job_from_dbus_path(m, path, &j);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r < 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen *found = j;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 1;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen Unit *u;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen int r;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert(m);
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen assert(bus);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert(path);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen sd_bus_message *message;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen pid_t pid;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen message = sd_bus_get_current_message(bus);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (!message)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return 0;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (r < 0)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return r;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen r = sd_bus_creds_get_pid(creds, &pid);
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen if (r < 0)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return r;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen u = manager_get_unit_by_pid(m, pid);
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen } else {
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen r = manager_load_unit_from_dbus_path(m, path, error, &u);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (r < 0)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return 0;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen }
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (!u)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return 0;
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen *unit = u;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return 1;
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen}
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersenstatic int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen Manager *m = userdata;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen assert(bus);
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen assert(path);
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen assert(interface);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen assert(found);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert(m);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen return find_unit(m, bus, path, (Unit**) found, error);
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen}
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen Manager *m = userdata;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering Unit *u;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen int r;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering assert(bus);
b5db00e52ee2e20578839e4e4488f7b9af9abc38Umut Tezduyar Lindskog assert(path);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert(interface);
55428d84f31b52da1c50b7469f14e15740547f20Tom Gundersen assert(found);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert(m);
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering r = find_unit(m, bus, path, &u, error);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (r <= 0)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen return 0;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen *found = u;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return 1;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen}
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersenstatic int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen Manager *m = userdata;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen Unit *u;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen int r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen assert(bus);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen assert(path);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(interface);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen assert(found);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen assert(m);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen r = find_unit(m, bus, path, &u, error);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen if (r <= 0)
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen return r;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (!unit_get_cgroup_context(u))
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen return 0;
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poettering
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poettering *found = u;
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen return 1;
aedca89268ed4fd6be41e55a605f011033ad1fb5Tom Gundersen}
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poetteringstatic int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poettering Manager *m = userdata;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen CGroupContext *c;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen Unit *u;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen int r;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen assert(bus);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen assert(path);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen assert(interface);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen assert(found);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen assert(m);
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
68ba38770640413b4fa06773447666eb88a38d4cTom Gundersen r = find_unit(m, bus, path, &u, error);
68ba38770640413b4fa06773447666eb88a38d4cTom Gundersen if (r <= 0)
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return r;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return 0;
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen c = unit_get_cgroup_context(u);
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen if (!c)
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return 0;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen *found = c;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return 1;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen}
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersenstatic int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen Manager *m = userdata;
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen ExecContext *c;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen Unit *u;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen int r;
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen assert(bus);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen assert(path);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen assert(interface);
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen assert(found);
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen assert(m);
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen r = find_unit(m, bus, path, &u, error);
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen if (r <= 0)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return r;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return 0;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen c = unit_get_exec_context(u);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (!c)
92d927f850d4b668b44f3e5f41e266d934d03726Tom Gundersen return 0;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen *found = c;
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen return 1;
a669ea9860900d5cdebbc4cb9aaea72db7e28a02Tom Gundersen}
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen Manager *m = userdata;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen KillContext *c;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen Unit *u;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen int r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen assert(bus);
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen assert(path);
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen assert(interface);
a669ea9860900d5cdebbc4cb9aaea72db7e28a02Tom Gundersen assert(found);
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen assert(m);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen r = find_unit(m, bus, path, &u, error);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (r <= 0)
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return r;
66d3752e812915a549ebee01769ee761c1495667Jacob Keller
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return 0;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen c = unit_get_kill_context(u);
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen if (!c)
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return 0;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen *found = c;
d95b83b87d7d7c50e550f7128827f73a321c8934Tom Gundersen return 1;
d95b83b87d7d7c50e550f7128827f73a321c8934Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen _cleanup_free_ char **l = NULL;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen Manager *m = userdata;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen unsigned k = 0;
a7f7d1bde43fc825c49afea3f946f5b4b3d563e0Harald Hoyer Iterator i;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen Job *j;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen l = new0(char*, hashmap_size(m->jobs)+1);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (!l)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return -ENOMEM;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
aedca89268ed4fd6be41e55a605f011033ad1fb5Tom Gundersen HASHMAP_FOREACH(j, m->jobs, i) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen l[k] = job_dbus_path(j);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (!l[k])
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return -ENOMEM;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen k++;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen }
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack assert(hashmap_size(m->jobs) == k);
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
66d3752e812915a549ebee01769ee761c1495667Jacob Keller *nodes = l;
66d3752e812915a549ebee01769ee761c1495667Jacob Keller l = NULL;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen return k;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen}
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersenstatic int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen _cleanup_free_ char **l = NULL;
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack Manager *m = userdata;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen unsigned k = 0;
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen Iterator i;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen Unit *u;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen l = new0(char*, hashmap_size(m->units)+1);
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen if (!l)
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen return -ENOMEM;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen HASHMAP_FOREACH(u, m->units, i) {
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen l[k] = unit_dbus_path(u);
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen if (!l[k])
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen return -ENOMEM;
k++;
}
*nodes = l;
l = NULL;
return k;
}
static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
UnitType t;
int r;
assert(m);
assert(bus);
#ifdef HAVE_SELINUX
r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
if (r < 0)
return log_error_errno(r, "Failed to add SELinux access filter: %m");
#endif
r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
if (r < 0)
return log_error_errno(r, "Failed to register Manager vtable: %m");
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
if (r < 0)
return log_error_errno(r, "Failed to register Job vtable: %m");
r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
if (r < 0)
return log_error_errno(r, "Failed to add job enumerator: %m");
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
if (r < 0)
return log_error_errno(r, "Failed to register Unit vtable: %m");
r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
if (r < 0)
return log_error_errno(r, "Failed to add job enumerator: %m");
for (t = 0; t < _UNIT_TYPE_MAX; t++) {
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);
if (r < 0)
return log_error_errno(r, "Failed to register type specific vtable for %s: %m", unit_vtable[t]->bus_interface);
if (unit_vtable[t]->cgroup_context_offset > 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);
if (r < 0)
return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", unit_vtable[t]->bus_interface);
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);
if (r < 0)
return log_error_errno(r, "Failed to register control group vtable for %s: %m", unit_vtable[t]->bus_interface);
}
if (unit_vtable[t]->exec_context_offset > 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);
if (r < 0)
return log_error_errno(r, "Failed to register execute vtable for %s: %m", unit_vtable[t]->bus_interface);
}
if (unit_vtable[t]->kill_context_offset > 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);
if (r < 0)
return log_error_errno(r, "Failed to register kill vtable for %s: %m", unit_vtable[t]->bus_interface);
}
}
return 0;
}
static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
int r;
assert(m);
assert(bus);
r = sd_bus_add_match(
bus,
NULL,
"sender='org.freedesktop.DBus.Local',"
"type='signal',"
"path='/org/freedesktop/DBus/Local',"
"interface='org.freedesktop.DBus.Local',"
"member='Disconnected'",
signal_disconnected, m);
if (r < 0)
return log_error_errno(r, "Failed to register match for Disconnected message: %m");
return 0;
}
static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
_cleanup_bus_unref_ sd_bus *bus = NULL;
_cleanup_close_ int nfd = -1;
Manager *m = userdata;
sd_id128_t id;
int r;
assert(s);
assert(m);
nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (nfd < 0) {
log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
return 0;
}
if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
log_warning("Too many concurrent connections, refusing");
return 0;
}
r = set_ensure_allocated(&m->private_buses, NULL);
if (r < 0) {
log_oom();
return 0;
}
r = sd_bus_new(&bus);
if (r < 0) {
log_warning_errno(r, "Failed to allocate new private connection bus: %m");
return 0;
}
r = sd_bus_set_fd(bus, nfd, nfd);
if (r < 0) {
log_warning_errno(r, "Failed to set fd on new connection bus: %m");
return 0;
}
nfd = -1;
r = bus_check_peercred(bus);
if (r < 0) {
log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
return 0;
}
assert_se(sd_id128_randomize(&id) >= 0);
r = sd_bus_set_server(bus, 1, id);
if (r < 0) {
log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
return 0;
}
r = sd_bus_negotiate_creds(bus, 1,
SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
SD_BUS_CREDS_SELINUX_CONTEXT);
if (r < 0) {
log_warning_errno(r, "Failed to enable credentials for new connection: %m");
return 0;
}
r = sd_bus_start(bus);
if (r < 0) {
log_warning_errno(r, "Failed to start new connection bus: %m");
return 0;
}
r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0) {
log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
return 0;
}
if (m->running_as == SYSTEMD_SYSTEM) {
/* When we run as system instance we get the Released
* signal via a direct connection */
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"
"path='/org/freedesktop/systemd1/agent'",
signal_agent_released, m);
if (r < 0) {
log_warning_errno(r, "Failed to register Released match on new connection bus: %m");
return 0;
}
}
r = bus_setup_disconnected_match(m, bus);
if (r < 0)
return 0;
r = bus_setup_api_vtables(m, bus);
if (r < 0) {
log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
return 0;
}
r = set_put(m->private_buses, bus);
if (r < 0) {
log_warning_errno(r, "Failed to add new connection bus to set: %m");
return 0;
}
bus = NULL;
log_debug("Accepted new private connection.");
return 0;
}
static int bus_list_names(Manager *m, sd_bus *bus) {
_cleanup_strv_free_ char **names = NULL;
char **i;
int r;
assert(m);
assert(bus);
r = sd_bus_list_names(bus, &names, NULL);
if (r < 0)
return log_error_errno(r, "Failed to get initial list of names: %m");
/* This is a bit hacky, we say the owner of the name is the
* name itself, because we don't want the extra traffic to
* figure out the real owner. */
STRV_FOREACH(i, names)
manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
return 0;
}
static int bus_setup_api(Manager *m, sd_bus *bus) {
int r;
assert(m);
assert(bus);
/* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
r = sd_bus_negotiate_creds(bus, 1,
SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
SD_BUS_CREDS_SELINUX_CONTEXT);
if (r < 0)
log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
r = bus_setup_api_vtables(m, bus);
if (r < 0)
return r;
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.DBus',"
"member='NameOwnerChanged'",
signal_name_owner_changed, m);
if (r < 0)
log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.systemd1.Activator',"
"member='ActivationRequest'",
signal_activation_request, m);
if (r < 0)
log_warning_errno(r, "Failed to subscribe to activation signal: %m");
/* Allow replacing of our name, to ease implementation of
* reexecution, where we keep the old connection open until
* after the new connection is set up and the name installed
* to allow clients to synchronously wait for reexecution to
* finish */
r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
if (r < 0)
return log_error_errno(r, "Failed to register name: %m");
bus_list_names(m, bus);
log_debug("Successfully connected to API bus.");
return 0;
}
static int bus_init_api(Manager *m) {
_cleanup_bus_unref_ sd_bus *bus = NULL;
int r;
if (m->api_bus)
return 0;
/* The API and system bus is the same if we are running in system mode */
if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
bus = sd_bus_ref(m->system_bus);
else {
if (m->running_as == SYSTEMD_SYSTEM)
r = sd_bus_open_system(&bus);
else
r = sd_bus_open_user(&bus);
if (r < 0) {
log_debug("Failed to connect to API bus, retrying later...");
return 0;
}
r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0) {
log_error_errno(r, "Failed to attach API bus to event loop: %m");
return 0;
}
r = bus_setup_disconnected_match(m, bus);
if (r < 0)
return 0;
}
r = bus_setup_api(m, bus);
if (r < 0) {
log_error_errno(r, "Failed to set up API bus: %m");
return 0;
}
m->api_bus = bus;
bus = NULL;
return 0;
}
static int bus_setup_system(Manager *m, sd_bus *bus) {
int r;
assert(m);
assert(bus);
/* On kdbus or if we are a user instance we get the Released message via the system bus */
if (m->running_as == SYSTEMD_USER || m->kdbus_fd >= 0) {
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"
"path='/org/freedesktop/systemd1/agent'",
signal_agent_released, m);
if (r < 0)
log_warning_errno(r, "Failed to register Released match on system bus: %m");
}
log_debug("Successfully connected to system bus.");
return 0;
}
static int bus_init_system(Manager *m) {
_cleanup_bus_unref_ sd_bus *bus = NULL;
int r;
if (m->system_bus)
return 0;
/* The API and system bus is the same if we are running in system mode */
if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
m->system_bus = sd_bus_ref(m->api_bus);
return 0;
}
r = sd_bus_open_system(&bus);
if (r < 0) {
log_debug("Failed to connect to system bus, retrying later...");
return 0;
}
r = bus_setup_disconnected_match(m, bus);
if (r < 0)
return 0;
r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0) {
log_error_errno(r, "Failed to attach system bus to event loop: %m");
return 0;
}
r = bus_setup_system(m, bus);
if (r < 0) {
log_error_errno(r, "Failed to set up system bus: %m");
return 0;
}
m->system_bus = bus;
bus = NULL;
return 0;
}
static int bus_init_private(Manager *m) {
_cleanup_close_ int fd = -1;
union sockaddr_union sa = {
.un.sun_family = AF_UNIX
};
sd_event_source *s;
socklen_t salen;
int r;
assert(m);
if (m->private_listen_fd >= 0)
return 0;
/* We don't need the private socket if we have kdbus */
if (m->kdbus_fd >= 0)
return 0;
if (m->running_as == SYSTEMD_SYSTEM) {
/* We want the private bus only when running as init */
if (getpid() != 1)
return 0;
strcpy(sa.un.sun_path, "/run/systemd/private");
salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private");
} else {
size_t left = sizeof(sa.un.sun_path);
char *p = sa.un.sun_path;
const char *e;
e = secure_getenv("XDG_RUNTIME_DIR");
if (!e) {
log_error("Failed to determine XDG_RUNTIME_DIR");
return -EHOSTDOWN;
}
left = strpcpy(&p, left, e);
left = strpcpy(&p, left, "/systemd/private");
salen = sizeof(sa.un) - left;
}
(void) mkdir_parents_label(sa.un.sun_path, 0755);
(void) unlink(sa.un.sun_path);
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0)
return log_error_errno(errno, "Failed to allocate private socket: %m");
r = bind(fd, &sa.sa, salen);
if (r < 0)
return log_error_errno(errno, "Failed to bind private socket: %m");
r = listen(fd, SOMAXCONN);
if (r < 0)
return log_error_errno(errno, "Failed to make private socket listening: %m");
r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
if (r < 0)
return log_error_errno(r, "Failed to allocate event source: %m");
(void) sd_event_source_set_description(s, "bus-connection");
m->private_listen_fd = fd;
m->private_listen_event_source = s;
fd = -1;
log_debug("Successfully created private D-Bus server.");
return 0;
}
int bus_init(Manager *m, bool try_bus_connect) {
int r;
if (try_bus_connect) {
r = bus_init_system(m);
if (r < 0)
return r;
r = bus_init_api(m);
if (r < 0)
return r;
}
r = bus_init_private(m);
if (r < 0)
return r;
return 0;
}
static void destroy_bus(Manager *m, sd_bus **bus) {
Iterator i;
Job *j;
assert(m);
assert(bus);
if (!*bus)
return;
/* Get rid of tracked clients on this bus */
if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
m->subscribed = sd_bus_track_unref(m->subscribed);
HASHMAP_FOREACH(j, m->jobs, i)
if (j->clients && sd_bus_track_get_bus(j->clients) == *bus)
j->clients = sd_bus_track_unref(j->clients);
/* Get rid of queued message on this bus */
if (m->queued_message && sd_bus_message_get_bus(m->queued_message) == *bus)
m->queued_message = sd_bus_message_unref(m->queued_message);
/* Possibly flush unwritten data, but only if we are
* unprivileged, since we don't want to sync here */
if (m->running_as != SYSTEMD_SYSTEM)
sd_bus_flush(*bus);
/* And destroy the object */
sd_bus_close(*bus);
*bus = sd_bus_unref(*bus);
}
void bus_done(Manager *m) {
sd_bus *b;
assert(m);
if (m->api_bus)
destroy_bus(m, &m->api_bus);
if (m->system_bus)
destroy_bus(m, &m->system_bus);
while ((b = set_steal_first(m->private_buses)))
destroy_bus(m, &b);
set_free(m->private_buses);
m->private_buses = NULL;
m->subscribed = sd_bus_track_unref(m->subscribed);
strv_free(m->deserialized_subscribed);
m->deserialized_subscribed = NULL;
if (m->private_listen_event_source)
m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
m->private_listen_fd = safe_close(m->private_listen_fd);
bus_verify_polkit_async_registry_free(m->polkit_registry);
}
int bus_fdset_add_all(Manager *m, FDSet *fds) {
Iterator i;
sd_bus *b;
int fd;
assert(m);
assert(fds);
/* When we are about to reexecute we add all D-Bus fds to the
* set to pass over to the newly executed systemd. They won't
* be used there however, except thatt they are closed at the
* very end of deserialization, those making it possible for
* clients to synchronously wait for systemd to reexec by
* simply waiting for disconnection */
if (m->api_bus) {
fd = sd_bus_get_fd(m->api_bus);
if (fd >= 0) {
fd = fdset_put_dup(fds, fd);
if (fd < 0)
return fd;
}
}
SET_FOREACH(b, m->private_buses, i) {
fd = sd_bus_get_fd(b);
if (fd >= 0) {
fd = fdset_put_dup(fds, fd);
if (fd < 0)
return fd;
}
}
/* We don't offer any APIs on the system bus (well, unless it
* is the same as the API bus) hence we don't bother with it
* here */
return 0;
}
int bus_foreach_bus(
Manager *m,
sd_bus_track *subscribed2,
int (*send_message)(sd_bus *bus, void *userdata),
void *userdata) {
Iterator i;
sd_bus *b;
int r, ret = 0;
/* Send to all direct busses, unconditionally */
SET_FOREACH(b, m->private_buses, i) {
r = send_message(b, userdata);
if (r < 0)
ret = r;
}
/* Send to API bus, but only if somebody is subscribed */
if (sd_bus_track_count(m->subscribed) > 0 ||
sd_bus_track_count(subscribed2) > 0) {
r = send_message(m->api_bus, userdata);
if (r < 0)
ret = r;
}
return ret;
}
void bus_track_serialize(sd_bus_track *t, FILE *f) {
const char *n;
assert(f);
for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t))
fprintf(f, "subscribed=%s\n", n);
}
int bus_track_deserialize_item(char ***l, const char *line) {
const char *e;
int r;
assert(l);
assert(line);
e = startswith(line, "subscribed=");
if (!e)
return 0;
r = strv_extend(l, e);
if (r < 0)
return r;
return 1;
}
int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
int r = 0;
assert(m);
assert(t);
assert(l);
if (!strv_isempty(*l) && m->api_bus) {
char **i;
if (!*t) {
r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
if (r < 0)
return r;
}
r = 0;
STRV_FOREACH(i, *l) {
int k;
k = sd_bus_track_add_name(*t, *i);
if (k < 0)
r = k;
}
}
strv_free(*l);
*l = NULL;
return r;
}
int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
}
/* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
int bus_verify_manage_units_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
}
int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, UID_INVALID, &m->polkit_registry, error);
}
int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, UID_INVALID, &m->polkit_registry, error);
}
int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", false, UID_INVALID, &m->polkit_registry, error);
}