dbus.c revision 8f8f05a919355095518911135c3d630f4620a9b0
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/***
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2010 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering***/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include <sys/epoll.h>
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell#include <sys/timerfd.h>
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include <errno.h>
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include <unistd.h>
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "sd-bus.h"
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering#include "log.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "strv.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "mkdir.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "missing.h"
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering#include "dbus-unit.h"
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen#include "dbus-job.h"
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier#include "dbus-manager.h"
0b452006de98294d1690f045f6ea2f7f6630ec3bRonny Chevalier#include "dbus-execute.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "dbus-kill.h"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering#include "dbus-cgroup.h"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering#include "special.h"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering#include "dbus.h"
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering#include "bus-util.h"
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek#include "bus-error.h"
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering#include "bus-errors.h"
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek#include "strxcpyx.h"
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek#include "bus-internal.h"
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek#include "selinux-access.h"
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek#define CONNECTIONS_MAX 512
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poetteringstatic void destroy_bus(Manager *m, sd_bus **bus);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
f8294e4175918117ca6c131720bcf287eadcd029Josh Triplettint bus_send_queued_message(Manager *m) {
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!m->queued_message)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m->queued_message_bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* If we cannot get rid of this message we won't dispatch any
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * D-Bus messages, so that we won't end up wanting to queue
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * another message. */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_warning("Failed to send queued message: %s", strerror(-r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering m->queued_message = sd_bus_message_unref(m->queued_message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *cgroup;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_read(message, "s", &cgroup);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (r < 0) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering bus_log_parse_error(r);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler manager_notify_cgroup_empty(m, cgroup);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* If we are running as system manager, forward the
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler * message to the system bus */
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_send(m->system_bus, message, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_warning("Failed to forward Released message: %s", strerror(-r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poetteringstatic int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt if (bus == m->api_bus)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering destroy_bus(m, &m->api_bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (bus == m->system_bus)
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering destroy_bus(m, &m->system_bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (set_remove(m->private_buses, bus)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_debug("Got disconnect on private connection.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering destroy_bus(m, &bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *name, *old_owner, *new_owner;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
3b97fcbd28f92a1e51887fef5de8844a89bde523Lennart Poettering assert(message);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_log_parse_error(r);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering manager_dispatch_bus_name_owner_changed(
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering m, name,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering isempty(old_owner) ? NULL : old_owner,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering isempty(new_owner) ? NULL : new_owner);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *name;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Unit *u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_read(message, "s", &name);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_log_parse_error(r);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto failed;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_load_unit(m, name, NULL, &error, &u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto failed;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->refuse_manual_start) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto failed;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto failed;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Successfully queued, that's it for us */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringfailed:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!sd_bus_error_is_set(&error))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_error_set_errno(&error, r);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_log_create_error(r);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bus_log_create_error(r);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_error("Failed to respond with to bus activation request: %s", strerror(-r));
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#ifdef HAVE_SELINUX
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *verb, *path;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Unit *u = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Job *j;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Our own method calls are all protected individually with
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * selinux checks, but the built-in interfaces need to be
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * protected too. */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering verb = "reload";
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering verb = "status";
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8Filipe Brandenburger
ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8Filipe Brandenburger path = sd_bus_message_get_path(message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek if (object_path_startswith("/org/freedesktop/systemd1", path)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = selinux_access_check(bus, message, verb, error);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering pid_t pid;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_creds_get_pid(creds, &pid);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering u = manager_get_unit_by_pid(m, pid);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering } else {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = manager_get_job_from_dbus_path(m, path, &j);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r >= 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering u = j->unit;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering else
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering manager_load_unit_from_dbus_path(m, path, NULL, &u);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!u)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = selinux_unit_access_check(u, bus, message, verb, error);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering}
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering#endif
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering Manager *m = userdata;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering Job *j;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering int r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(bus);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(path);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(interface);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(found);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(m);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = manager_get_job_from_dbus_path(m, path, &j);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering *found = j;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 1;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering}
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering Unit *u;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering int r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(m);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(bus);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(path);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering sd_bus_message *message;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering pid_t pid;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering message = sd_bus_get_current(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!message)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering r = sd_bus_creds_get_pid(creds, &pid);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering if (r < 0)
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u = manager_get_unit_by_pid(m, pid);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else {
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering r = manager_load_unit_from_dbus_path(m, path, error, &u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!u)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering *unit = u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(path);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(interface);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(found);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen return find_unit(m, bus, path, (Unit**) found, error);
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen}
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m = userdata;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering Unit *u;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering assert(bus);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering assert(path);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering assert(interface);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering assert(found);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering r = find_unit(m, bus, path, &u, error);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r <= 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering *found = u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poetteringstatic int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Unit *u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(path);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(interface);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering assert(found);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = find_unit(m, bus, path, &u, error);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r <= 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
03ee5c38cb0da193dd08733fb4c0c2809cee6a99Lennart Poettering return 0;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!unit_get_cgroup_context(u))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt *found = u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt Manager *m = userdata;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt CGroupContext *c;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Unit *u;
4a61c3e51e96a747c30598d78ee3a24e7c569e9fZbigniew Jędrzejewski-Szmek int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(path);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(interface);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt assert(found);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt assert(m);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = find_unit(m, bus, path, &u, error);
6baa7db00812437bbc87e73faa1a11b6cf631958Lennart Poettering if (r <= 0)
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering return r;
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering c = unit_get_cgroup_context(u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!c)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return 0;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering *found = c;
8531ae707d4d0203e83304d4af948b8169a5fce1Lennart Poettering return 1;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt}
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m = userdata;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering ExecContext *c;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering Unit *u;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering int r;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(bus);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(path);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(interface);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(found);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(m);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering r = find_unit(m, bus, path, &u, error);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (r <= 0)
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return r;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return 0;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering c = unit_get_exec_context(u);
if (!c)
return 0;
*found = c;
return 1;
}
static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Manager *m = userdata;
KillContext *c;
Unit *u;
int r;
assert(bus);
assert(path);
assert(interface);
assert(found);
assert(m);
r = find_unit(m, bus, path, &u, error);
if (r <= 0)
return r;
if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
return 0;
c = unit_get_kill_context(u);
if (!c)
return 0;
*found = c;
return 1;
}
static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
_cleanup_free_ char **l = NULL;
Manager *m = userdata;
unsigned k = 0;
Iterator i;
Job *j;
l = new0(char*, hashmap_size(m->jobs)+1);
if (!l)
return -ENOMEM;
HASHMAP_FOREACH(j, m->jobs, i) {
l[k] = job_dbus_path(j);
if (!l[k])
return -ENOMEM;
k++;
}
assert(hashmap_size(m->jobs) == k);
*nodes = l;
l = NULL;
return k;
}
static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
_cleanup_free_ char **l = NULL;
Manager *m = userdata;
unsigned k = 0;
Iterator i;
Unit *u;
l = new0(char*, hashmap_size(m->units)+1);
if (!l)
return -ENOMEM;
HASHMAP_FOREACH(u, m->units, i) {
l[k] = unit_dbus_path(u);
if (!l[k])
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, selinux_filter, m);
if (r < 0) {
log_error("Failed to add SELinux access filter: %s", strerror(-r));
return r;
}
#endif
r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
if (r < 0) {
log_error("Failed to register Manager vtable: %s", strerror(-r));
return r;
}
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
if (r < 0) {
log_error("Failed to register Job vtable: %s", strerror(-r));
return r;
}
r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
if (r < 0) {
log_error("Failed to add job enumerator: %s", strerror(-r));
return r;
}
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
if (r < 0) {
log_error("Failed to register Unit vtable: %s", strerror(-r));
return r;
}
r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
if (r < 0) {
log_error("Failed to add job enumerator: %s", strerror(-r));
return r;
}
for (t = 0; t < _UNIT_TYPE_MAX; t++) {
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
if (r < 0) {
log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
if (unit_vtable[t]->cgroup_context_offset > 0) {
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
if (r < 0) {
log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
if (r < 0) {
log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
}
if (unit_vtable[t]->exec_context_offset > 0) {
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
if (r < 0) {
log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
}
if (unit_vtable[t]->kill_context_offset > 0) {
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
if (r < 0) {
log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
}
}
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,
"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) {
log_error("Failed to register match for Disconnected message: %s", strerror(-r));
return r;
}
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("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, trivial_hash_func, trivial_compare_func);
if (r < 0) {
log_oom();
return 0;
}
r = sd_bus_new(&bus);
if (r < 0) {
log_warning("Failed to allocate new private connection bus: %s", strerror(-r));
return 0;
}
r = sd_bus_set_fd(bus, nfd, nfd);
if (r < 0) {
log_warning("Failed to set fd on new connection bus: %s", strerror(-r));
return 0;
}
nfd = -1;
r = bus_check_peercred(bus);
if (r < 0) {
log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
return 0;
}
assert_se(sd_id128_randomize(&id) >= 0);
r = sd_bus_set_server(bus, 1, id);
if (r < 0) {
log_warning("Failed to enable server support for new connection bus: %s", strerror(-r));
return 0;
}
r = sd_bus_start(bus);
if (r < 0) {
log_warning("Failed to start new connection bus: %s", strerror(-r));
return 0;
}
r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0) {
log_warning("Failed to attach new connection bus to event loop: %s", strerror(-r));
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,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"
"path='/org/freedesktop/systemd1/agent'",
signal_agent_released, m);
if (r < 0) {
log_warning("Failed to register Released match on new connection bus: %s", strerror(-r));
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("Failed to set up API vtables on new connection bus: %s", strerror(-r));
return 0;
}
r = set_put(m->private_buses, bus);
if (r < 0) {
log_warning("Failed to add new conenction bus to set: %s", strerror(-r));
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) {
log_error("Failed to get initial list of names: %s", strerror(-r));
return r;
}
/* 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);
r = bus_setup_api_vtables(m, bus);
if (r < 0)
return r;
r = sd_bus_add_match(
bus,
"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("Failed to subscribe to NameOwnerChanged signal: %s", strerror(-r));
r = sd_bus_add_match(
bus,
"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("Failed to subscribe to activation signal: %s", strerror(-r));
/* 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) {
log_error("Failed to register name: %s", strerror(-r));
return r;
}
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("Failed to attach API bus to event loop: %s", strerror(-r));
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("Failed to set up API bus: %s", strerror(-r));
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);
if (m->running_as == SYSTEMD_SYSTEM)
return 0;
/* If we are a user instance we get the Released message via
* the system bus */
r = sd_bus_add_match(
bus,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"
"path='/org/freedesktop/systemd1/agent'",
signal_agent_released, m);
if (r < 0)
log_warning("Failed to register Released match on system bus: %s", strerror(-r));
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("Failed to attach system bus to event loop: %s", strerror(-r));
return 0;
}
r = bus_setup_system(m, bus);
if (r < 0) {
log_error("Fauiled to set up system bus: %s", strerror(-r));
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) + sizeof("/run/systemd/private") - 1;
} 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;
mkdir_parents_label(sa.un.sun_path, 0755);
}
unlink(sa.un.sun_path);
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0) {
log_error("Failed to allocate private socket: %m");
return -errno;
}
r = bind(fd, &sa.sa, salen);
if (r < 0) {
log_error("Failed to bind private socket: %m");
return -errno;
}
r = listen(fd, SOMAXCONN);
if (r < 0) {
log_error("Failed to make private socket listening: %m");
return -errno;
}
r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
if (r < 0) {
log_error("Failed to allocate event source: %s", strerror(-r));
return r;
}
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->subscribed && sd_bus_track_get_bus(j->subscribed) == *bus)
j->subscribed = sd_bus_track_unref(j->subscribed);
/* Get rid of queued message on this bus */
if (m->queued_message_bus == *bus) {
m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
if (m->queued_message)
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);
if (m->private_listen_fd >= 0) {
close_nointr_nofail(m->private_listen_fd);
m->private_listen_fd = -1;
}
}
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(t);
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;
assert(l);
assert(line);
e = startswith(line, "subscribed=");
if (!e)
return 0;
return strv_extend(l, e);
}
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;
}