bus-kernel.c revision 9f6dfd0624e44002e407a72acb0c15b7177e9a9f
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/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
b93312f5960b276bae915906ccde36f545bae3e0Zbigniew Jędrzejewski-Szmek /* Note that p can be NULL, which encodes a region full of
b93312f5960b276bae915906ccde36f545bae3e0Zbigniew Jędrzejewski-Szmek * zeroes, which is useful to optimize certain padding
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * conditions */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void append_destination(struct kdbus_item **d, const char *s, size_t length) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmekstatic struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering i->size = offsetof(struct kdbus_item, bloom_filter) +
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering offsetof(struct kdbus_bloom_filter, data) +
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poetteringstatic void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek memcpy((*d)->fds, fds, sizeof(int) * n_fds);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmekstatic int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering for (i = 0; i < 64; i++) {
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering const char *t;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_bus_message_peek_type(m, &type, NULL);
struct kdbus_item *d;
const char *destination;
bool well_known;
assert(b);
assert(m);
if (m->kdbus)
if (destination) {
well_known = r == 0;
well_known = false;
if (well_known) {
if (m->n_fds > 0)
if (!m->kdbus) {
r = -ENOMEM;
goto fail;
m->free_kdbus = true;
if (well_known) {
if (well_known)
goto fail;
goto fail;
if (m->n_fds > 0)
fail:
m->poisoned = true;
assert(m);
struct kdbus_item *d;
unsigned n_fds = 0;
assert(k);
size_t l;
switch (d->type) {
case KDBUS_ITEM_PAYLOAD_OFF:
return -EBADMSG;
case KDBUS_ITEM_PAYLOAD_MEMFD:
return -EBADMSG;
case KDBUS_ITEM_FDS: {
return -ENOMEM;
fds = f;
n_fds += j;
case KDBUS_ITEM_SECLABEL:
return -EBADMSG;
return -EBADMSG;
return -EPROTOTYPE;
size_t l;
switch (d->type) {
case KDBUS_ITEM_PAYLOAD_OFF: {
if (!part) {
r = -ENOMEM;
goto fail;
case KDBUS_ITEM_PAYLOAD_MEMFD: {
r = -EBADMSG;
goto fail;
if (!part) {
r = -ENOMEM;
goto fail;
case KDBUS_ITEM_PIDS:
case KDBUS_ITEM_CREDS:
case KDBUS_ITEM_TIMESTAMP:
case KDBUS_ITEM_PID_COMM:
case KDBUS_ITEM_TID_COMM:
case KDBUS_ITEM_EXE:
case KDBUS_ITEM_CMDLINE:
case KDBUS_ITEM_CGROUP:
m->creds.mask |= (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) & bus->creds_mask;
goto fail;
case KDBUS_ITEM_AUDIT:
case KDBUS_ITEM_CAPS:
m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
case KDBUS_ITEM_DST_NAME:
r = -EBADMSG;
goto fail;
case KDBUS_ITEM_OWNED_NAME:
r = -EBADMSG;
goto fail;
goto fail;
case KDBUS_ITEM_AUXGROUPS:
size_t i, n;
uid_t *u;
r = -ENOMEM;
goto fail;
case KDBUS_ITEM_FDS:
case KDBUS_ITEM_SECLABEL:
r = bus_message_parse_fields(m);
goto fail;
if (destination)
snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
m->kdbus = k;
m->release_kdbus = true;
m->free_fds = true;
fail:
unset_memfds(m);
const char *name;
assert(b);
if (b->is_server)
return -EINVAL;
if (b->description) {
return -ENOMEM;
name = g;
return -ENOMEM;
return -ENOMEM;
name = g;
if (!b->description)
return -ENOMEM;
if (b->fake_creds_valid)
if (b->fake_pids_valid)
if (b->fake_label) {
if (b->fake_creds_valid) {
if (b->fake_pids_valid) {
if (b->fake_label) {
return -errno;
if (!b->kdbus_buffer) {
return -errno;
return -ENOTSUP;
return -ENOTSUP;
return -ENOMEM;
b->is_kernel = true;
b->bus_client = true;
return bus_start_running(b);
assert(b);
if (b->is_server)
return -EINVAL;
if (b->input_fd < 0)
return -errno;
return bus_kernel_take_fd(b);
struct kdbus_item *d;
assert(k);
assert(m);
* kernel, so that it can pass CPU time/scheduling to the
if (hint_sync_call)
sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
return -errno;
bus,
&error,
&reply);
} else if (hint_sync_call) {
struct kdbus_msg *k;
assert(k);
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
bus,
"/org/freedesktop/DBus",
m = NULL;
assert(k);
assert(d);
if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
old_owner[0] = 0;
if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
new_owner[0] = 0;
assert(k);
assert(d);
return push_name_owner_changed(
assert(k);
assert(d);
bus,
k->cookie_reply,
m = NULL;
assert(k);
if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
if (found)
return -EBADMSG;
found = d;
if (!found) {
struct kdbus_msg *k;
if (hint_priority) {
return -errno;
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
struct memfd_cache *c;
int fd;
return -ENOTSUP;
*mapped = 0;
*allocated = 0;
return fd;
if (size > 0)
struct memfd_cache *c;
assert(b);
for (i = 0; i < b->n_memfd_cache; i++)
uint64_t f = 0;
f |= KDBUS_NAME_QUEUE;
*kdbus_flags = f;
uint64_t m = 0;
m |= KDBUS_ATTACH_CREDS;
m |= KDBUS_ATTACH_PIDS;
m |= KDBUS_ATTACH_PID_COMM;
m |= KDBUS_ATTACH_TID_COMM;
m |= KDBUS_ATTACH_EXE;
m |= KDBUS_ATTACH_CMDLINE;
if (mask & (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))
m |= KDBUS_ATTACH_CGROUP;
if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
m |= KDBUS_ATTACH_CAPS;
m |= KDBUS_ATTACH_SECLABEL;
m |= KDBUS_ATTACH_AUDIT;
m |= KDBUS_ATTACH_NAMES;
m |= KDBUS_ATTACH_AUXGROUPS;
*kdbus_mask = m;
struct kdbus_item *n;
int fd;
assert(s);
if (fd < 0)
return -errno;
sizeof(struct kdbus_bloom_parameter);
n = KDBUS_ITEM_NEXT(n);
return -errno;
return -ENOMEM;
return fd;
switch (access) {
case BUS_POLICY_ACCESS_SEE:
return KDBUS_POLICY_SEE;
case BUS_POLICY_ACCESS_TALK:
return KDBUS_POLICY_TALK;
case BUS_POLICY_ACCESS_OWN:
return KDBUS_POLICY_OWN;
case BUSNAME_POLICY_TYPE_USER: {
case BUSNAME_POLICY_TYPE_GROUP: {
int fd;
if (path) {
return -ENOMEM;
*path = p;
if (fd < 0)
return -errno;
return fd;
struct kdbus_item *n;
int fd;
if (fd < 0)
return fd;
return -errno;
if (ep_path) {
return -ENOMEM;
*ep_path = p;
return fd;
struct kdbus_item *n;
Iterator i;
n = KDBUS_ITEM_NEXT(n);
n = KDBUS_ITEM_NEXT(n);
return -errno;
int fd,
const char *name,
bool activating,
bool accept_fd,
struct kdbus_item *n;
policy_cnt++;
if (world_policy >= 0)
policy_cnt++;
policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
n = KDBUS_ITEM_NEXT(n);
n = KDBUS_ITEM_NEXT(n);
if (world_policy >= 0) {
return -errno;
return -ENOTSUP;
return -ENOTSUP;
return fd;
return -errno;
return -errno;