bus-control.c revision 1af5f746d569f013595bb16ca113741ee306f04a
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2013 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert_return(!bus_pid_changed(bus), -ECHILD);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n->flags = request_name_flags_to_kdbus(flags);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (n->return_flags & KDBUS_NAME_IN_QUEUE)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (flags & SD_BUS_NAME_REPLACE_EXISTING)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "org.freedesktop.DBus",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "org.freedesktop.DBus",
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering "RequestName",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = sd_bus_message_read(reply, "u", &ret);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_return(!bus_pid_changed(bus), -ECHILD);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_return(service_name_is_valid(name), -EINVAL);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering /* Don't allow requesting the special driver and local names */
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return bus_request_name_kernel(bus, name, flags);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return bus_request_name_dbus1(bus, name, flags);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poetteringstatic int bus_release_name_kernel(sd_bus *bus, const char *name) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic int bus_release_name_dbus1(sd_bus *bus, const char *name) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "org.freedesktop.DBus",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "org.freedesktop.DBus",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "ReleaseName",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = sd_bus_message_read(reply, "u", &ret);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert_return(!bus_pid_changed(bus), -ECHILD);
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering assert_return(service_name_is_valid(name), -EINVAL);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering /* Don't allow releasing the special driver and local names */
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering return bus_release_name_kernel(bus, name);
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering return bus_release_name_dbus1(bus, name);
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poetteringstatic int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Caller will free half-constructed list on failure... */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering KDBUS_FOREACH(name, name_list, cmd.list_size) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (entry_name && service_name_is_valid(entry_name)) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_strv_free_ char **x = NULL, **y = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_strv_free_ char **x = NULL, **y = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "org.freedesktop.DBus",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "org.freedesktop.DBus",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "org.freedesktop.DBus",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "org.freedesktop.DBus",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "ListActivatableNames",
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert_return(acquired || activatable, -EINVAL);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert_return(!bus_pid_changed(bus), -ECHILD);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return bus_list_names_kernel(bus, acquired, activatable);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return bus_list_names_dbus1(bus, acquired, activatable);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* The structure doesn't
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * really distinguish the case
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * where a process has no
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * parent and where we don't
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * know it because it could
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * not be translated due to
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * namespaces. However, we
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * know that PID 1 has no
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * parent process, hence let's
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * patch that in, manually. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
878cd63db2d6cfc00ae4d68355a2d5402cd9f24fLennart Poettering if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = free_and_strdup(&c->comm, item->str);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = free_and_strdup(&c->tid_comm, item->str);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c->cmdline = memdup(item->data, c->cmdline_size);
case KDBUS_ITEM_CGROUP:
c->mask |= m;
case KDBUS_ITEM_CAPS:
item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
return -EBADMSG;
if (!c->capability)
return -ENOMEM;
c->mask |= m;
case KDBUS_ITEM_SECLABEL:
case KDBUS_ITEM_AUDIT:
case KDBUS_ITEM_OWNED_NAME:
case KDBUS_ITEM_AUXGROUPS:
size_t i, n;
uid_t *g;
return -ENOMEM;
c->supplementary_gids = g;
c->n_supplementary_gids = n;
const char *name,
bool allow_activator,
return -EOPNOTSUPP;
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
return -errno;
r = -ENXIO;
r = -ESRCH;
goto fail;
c = bus_creds_new();
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
goto fail;
goto fail;
if (creds) {
*creds = c;
c = NULL;
fail:
static int bus_get_name_creds_dbus1(
const char *name,
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
name);
if (mask != 0) {
c = bus_creds_new();
return -ENOMEM;
if (!c->unique_name)
return -ENOMEM;
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
uint32_t u;
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
&reply,
pid = u;
c->pid = u;
uint32_t u;
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
&reply,
c->euid = u;
const void *p = NULL;
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
&error,
&reply,
if (!c->label)
return -ENOMEM;
if (creds) {
*creds = c;
c = NULL;
const char *name,
return -EINVAL;
return -EINVAL;
return -ENOTCONN;
c = bus_creds_new();
return -ENOMEM;
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
return -errno;
*ret = c;
c = NULL;
return -ENODATA;
c = bus_creds_new();
return -ENOMEM;
if (do_label) {
if (!c->label)
return -ENOMEM;
*ret = c;
c = NULL;
return -ENOTCONN;
const char *name,
const char *old_owner,
const char *new_owner) {
if (name) {
if (is_name_id < 0)
if (is_name_id <= 0) {
struct kdbus_cmd_match *m;
if (name)
return -errno;
return -errno;
return -errno;
if (is_name_id != 0) {
struct kdbus_cmd_match *m;
sizeof(struct kdbus_notify_id_change));
sizeof(struct kdbus_notify_id_change);
return -errno;
return -errno;
unsigned n_components,
struct kdbus_cmd_match *m;
bool using_bloom = false;
bool matches_name_change = true;
for (i = 0; i < n_components; i++) {
switch (c->type) {
case BUS_MATCH_SENDER:
matches_name_change = false;
case BUS_MATCH_MESSAGE_TYPE:
matches_name_change = false;
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
using_bloom = true;
case BUS_MATCH_INTERFACE:
matches_name_change = false;
using_bloom = true;
case BUS_MATCH_MEMBER:
matches_name_change = false;
using_bloom = true;
case BUS_MATCH_PATH:
matches_name_change = false;
using_bloom = true;
case BUS_MATCH_PATH_NAMESPACE:
using_bloom = true;
using_bloom = true;
using_bloom = true;
case BUS_MATCH_DESTINATION: {
matches_name_change = false;
case BUS_MATCH_ROOT:
case BUS_MATCH_VALUE:
case BUS_MATCH_LEAF:
case _BUS_MATCH_NODE_TYPE_MAX:
if (using_bloom)
if (using_bloom) {
if (sender) {
return -errno;
if (matches_name_change) {
static int bus_add_match_internal_dbus1(
const char *match) {
return sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
NULL,
const char *match,
unsigned n_components,
return -EINVAL;
struct kdbus_cmd_match m = {
return -errno;
static int bus_remove_match_internal_dbus1(
const char *match) {
return sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
NULL,
const char *match,
return -EINVAL;
const char *mid;
return -EINVAL;
return -ENOTCONN;
bus,
name,
r = sd_bus_message_set_auto_start(m, false);