bus-kernel.c revision 03785ad0e51b061efb9f9b3f2e328685f9a866aa
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt This file is part of systemd.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Copyright 2013 Lennart Poettering
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is free software; you can redistribute it and/or modify it
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt under the terms of the GNU Lesser General Public License as published by
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt the Free Software Foundation; either version 2.1 of the License, or
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt (at your option) any later version.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is distributed in the hope that it will be useful, but
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Lesser General Public License for more details.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt You should have received a copy of the GNU Lesser General Public License
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktint bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt /* Note that p can be NULL, which encodes a region full of
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt * zeroes, which is useful to optimize certain padding
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt * conditions */
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
assert(d);
*d = ALIGN8_PTR(*d);
assert(d);
assert(s);
*d = ALIGN8_PTR(*d);
struct kdbus_item *i;
assert(d);
i = ALIGN8_PTR(*d);
return &i->bloom_filter;
assert(d);
*d = ALIGN8_PTR(*d);
void *data;
assert(m);
bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
if (m->interface)
if (m->member)
if (m->path) {
bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
r = sd_bus_message_rewind(m, true);
char type;
struct kdbus_item *d;
bool well_known;
assert(b);
assert(m);
if (m->kdbus)
if (m->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;
well_known ? 0 :
r = -errno;
goto fail;
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_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:
return -EBADMSG;
case KDBUS_ITEM_NAME:
return -EBADMSG;
goto fail;
case KDBUS_ITEM_CONN_NAME:
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->connection_name) {
return -ENOMEM;
name = g;
return -ENOMEM;
return -ENOMEM;
name = g;
if (!b->connection_name)
return -ENOMEM;
if (b->fake_creds_valid)
if (b->fake_label) {
if (b->fake_creds_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;
return -ENOMEM;
return -errno;
*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;
if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
m |= KDBUS_ATTACH_CREDS;
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_CONN_NAME;
*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;
struct kdbus_item *n;
int fd;
assert(s);
if (fd < 0)
return -errno;
return -errno;
return -ENOTSUP;
return -ENOMEM;
return fd;
return -errno;
return -errno;