bus-control.c revision 6ad4a4fc43e12c8c36f85abbb36e8791ec507519
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen This file is part of systemd.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen Copyright 2013 Lennart Poettering
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen systemd is free software; you can redistribute it and/or modify it
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen under the terms of the GNU Lesser General Public License as published by
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (at your option) any later version.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen systemd is distributed in the hope that it will be useful, but
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen Lesser General Public License for more details.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen You should have received a copy of the GNU Lesser General Public License
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(!bus_pid_changed(bus), -ECHILD);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen n->flags = request_name_flags_to_kdbus(flags);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "RequestName",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(!bus_pid_changed(bus), -ECHILD);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(service_name_is_valid(name), -EINVAL);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Don't allow requesting the special driver and local names */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return bus_request_name_kernel(bus, name, flags);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return bus_request_name_dbus1(bus, name, flags);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int bus_release_name_kernel(sd_bus *bus, const char *name) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int bus_release_name_dbus1(sd_bus *bus, const char *name) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "ReleaseName",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(!bus_pid_changed(bus), -ECHILD);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(service_name_is_valid(name), -EINVAL);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Don't allow releasing the special driver and local names */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Caller will free half-constructed list on failure... */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen KDBUS_FOREACH(name, name_list, cmd.list_size) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (entry_name && service_name_is_valid(entry_name)) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_strv_free_ char **x = NULL, **y = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2237aa02f3e2739a1ebe9c0bc224b5125f5eb292David Herrmann _cleanup_strv_free_ char **x = NULL, **y = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "org.freedesktop.DBus",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "ListActivatableNames",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(acquired || activatable, -EINVAL);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert_return(!bus_pid_changed(bus), -ECHILD);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return bus_list_names_kernel(bus, acquired, activatable);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return bus_list_names_dbus1(bus, acquired, activatable);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen c->cmdline = memdup(item->data, c->cmdline_size);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen 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 n;
uid_t *g;
return -ENOMEM;
c->supplementary_gids = g;
c->n_supplementary_gids = n;
const char *name,
bool allow_activator,
return -ENOTSUP;
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 -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 (!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;
using_bloom = true;
case BUS_MATCH_DESTINATION:
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,
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,
const char *mid;
return -ENOTCONN;
bus,
name,
r = sd_bus_message_set_auto_start(m, false);