dbus.c revision b2c23da8cea1987a1a329f5a964d3299b7ca7890
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering This file is part of systemd.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering Copyright 2010 Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering systemd is free software; you can redistribute it and/or modify it
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering under the terms of the GNU Lesser General Public License as published by
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering (at your option) any later version.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering systemd is distributed in the hope that it will be useful, but
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering Lesser General Public License for more details.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering You should have received a copy of the GNU Lesser General Public License
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
2b6bf07dd23bb467099d213c97b3875c5e453491Zbigniew Jędrzejewski-Szmekstatic void destroy_bus(Manager *m, sd_bus **bus);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* If we cannot get rid of this message we won't dispatch any
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * D-Bus messages, so that we won't end up wanting to queue
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * another message. */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_send(NULL, m->queued_message, NULL);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_warning_errno(r, "Failed to send queued message: %m");
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering m->queued_message = sd_bus_message_unref(m->queued_message);
cc3773810855956bad92337cee8fa193584ab62eLennart Poetteringstatic int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_message_read(message, "s", &cgroup);
d2e54fae5ca7a0f71b5ac8b356a589ff0a09ea0aKay Sievers /* only forward to system bus if running as system instance */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (m->running_as != MANAGER_SYSTEM || !m->system_bus)
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_send(m->system_bus, message, NULL);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_warning_errno(r, "Failed to forward Released message: %m");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering assert_se(bus = sd_bus_message_get_bus(message));
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_debug("Got disconnect on private connection.");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering const char *name, *old_owner, *new_owner;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering r = sd_bus_message_read(message, "s", &name);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = manager_load_unit(m, name, NULL, &error, &u);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* Successfully queued, that's it for us */
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering return log_error_errno(r, "Failed to respond with to bus activation request: %m");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering /* Our own method calls are all protected individually with
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering * selinux checks, but the built-in interfaces need to be
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering * protected too. */
a34faf579d2be139b0b9e8cd0c73ad4d918ef736Lukas Nykryn if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
a34faf579d2be139b0b9e8cd0c73ad4d918ef736Lukas Nykryn sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
a34faf579d2be139b0b9e8cd0c73ad4d918ef736Lukas Nykryn sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (object_path_startswith("/org/freedesktop/systemd1", path)) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering r = mac_selinux_access_check(message, verb, error);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = manager_get_job_from_dbus_path(m, path, &j);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering manager_load_unit_from_dbus_path(m, path, NULL, &u);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering r = mac_selinux_unit_access_check(u, message, verb, error);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering r = manager_get_job_from_dbus_path(m, path, &j);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering message = sd_bus_get_current_message(bus);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = manager_load_unit_from_dbus_path(m, path, error, &u);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering return find_unit(m, bus, path, (Unit**) found, error);
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poetteringstatic int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
2c4f86c1298f402220965682ab0e7729e150a562Lennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poetteringstatic int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
409133be63387fc04d927e8aecd2f6ba03d2f143Lennart Poetteringstatic int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poetteringstatic int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering unsigned k = 0;
Job *j;
return -ENOMEM;
l[k] = job_dbus_path(j);
return -ENOMEM;
*nodes = l;
l = NULL;
static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
Iterator i;
Unit *u;
return -ENOMEM;
l[k] = unit_dbus_path(u);
return -ENOMEM;
*nodes = l;
l = NULL;
UnitType t;
assert(m);
#ifdef HAVE_SELINUX
r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_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);
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, 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);
return log_error_errno(r, "Failed to register type specific 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_unit_cgroup_vtable, bus_unit_cgroup_find, m);
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);
return log_error_errno(r, "Failed to register control group 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_exec_vtable, bus_exec_context_find, m);
return log_error_errno(r, "Failed to register execute 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_kill_vtable, bus_kill_context_find, m);
return log_error_errno(r, "Failed to register kill vtable for %s: %m", unit_vtable[t]->bus_interface);
assert(m);
r = sd_bus_add_match(
bus,
NULL,
"path='/org/freedesktop/DBus/Local',"
signal_disconnected, m);
assert(s);
assert(m);
if (nfd < 0) {
log_oom();
r = sd_bus_add_match(
bus,
NULL,
"interface='org.freedesktop.systemd1.Agent',"
"path='/org/freedesktop/systemd1/agent'",
assert(m);
assert(m);
/* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
r = sd_bus_add_match(
bus,
NULL,
"path='/org/freedesktop/DBus',"
r = sd_bus_add_match(
bus,
NULL,
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.systemd1.Activator',"
r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
if (m->api_bus)
assert(m);
r = sd_bus_add_match(
bus,
NULL,
"interface='org.freedesktop.systemd1.Agent',"
"path='/org/freedesktop/systemd1/agent'",
if (m->system_bus)
sd_event_source *s;
assert(m);
if (m->private_listen_fd >= 0)
if (m->kdbus_fd >= 0)
return -EHOSTDOWN;
if (fd < 0)
m->private_listen_event_source = s;
if (try_bus_connect) {
r = bus_init_system(m);
r = bus_init_api(m);
r = bus_init_private(m);
Iterator i;
Job *j;
assert(m);
if (!*bus)
sd_bus *b;
assert(m);
if (m->api_bus)
if (m->system_bus)
destroy_bus(m, &b);
if (m->private_listen_event_source)
Iterator i;
sd_bus *b;
int fd;
assert(m);
if (m->api_bus) {
if (fd >= 0) {
if (fd < 0)
return fd;
if (fd >= 0) {
if (fd < 0)
return fd;
int bus_foreach_bus(
Manager *m,
void *userdata) {
Iterator i;
sd_bus *b;
int r, ret = 0;
ret = r;
ret = r;
return ret;
assert(f);
assert(l);
r = strv_extend(l, e);
assert(m);
assert(t);
assert(l);
STRV_FOREACH(i, *l) {
k = sd_bus_track_add_name(*t, *i);
strv_free(*l);
*l = NULL;
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, UID_INVALID, &m->polkit_registry, error);
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, UID_INVALID, &m->polkit_registry, error);
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", false, UID_INVALID, &m->polkit_registry, error);