bus-kernel.c revision affc7fe9e1295e209c332a26acbbc992b710fe82
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright 2013 Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Note that p can be NULL, which encodes a region full of
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * zeroes, which is useful to optimize certain padding
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * conditions */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void append_destination(struct kdbus_item **d, const char *s, size_t length) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering i->size = offsetof(struct kdbus_item, bloom_filter) +
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering offsetof(struct kdbus_bloom_filter, data) +
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcpy((*d)->fds, fds, sizeof(int) * n_fds);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (i = 0; i < 64; i++) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack const char *t;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_bus_message_read_basic(m, type, &t);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *(e++) = '0' + (char) i;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '.');
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '/');
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We put this together only once, if this message is reused
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * we reuse the earlier-built version */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering destination = m->destination ?: m->destination_ptr;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = bus_kernel_parse_unique_name(destination, &unique);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Add in fixed header, fields header and payload */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering /* Add space for bloom filter */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering offsetof(struct kdbus_bloom_filter, data) +
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering /* Add in well-known destination header */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Add space for unix fds */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* verify_destination_id will usually be 0, which makes the kernel driver only look
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * at the provided well-known name. Otherwise, the kernel will make sure the provided
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * destination id matches the owner of the provided weel-known-name, and fail if they
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * differ. Currently, this is only needed for bus-proxyd. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->kdbus->dst_id = m->verify_destination_id;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->kdbus->cookie = (uint64_t) m->header->serial;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->kdbus->cookie_reply = m->reply_cookie;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* If this is padding then simply send a
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * vector with a NULL data pointer which the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * kernel will just pass through. This is the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * most efficient way to encode zeroes */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering append_payload_vec(&d, NULL, part->size);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (part->memfd >= 0 && part->sealed && destination) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Try to send a memfd, if the part is
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * sealed and this is not a broadcast. Since we can only */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering append_payload_memfd(&d, part->memfd, part->size);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Otherwise, let's send a vector to the actual data.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * For that, we need to map it first. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering append_payload_vec(&d, part->data, part->size);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bloom = append_bloom(&d, m->bus->bloom_size);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic void unset_memfds(struct sd_bus_message *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Make sure the memfds are not freed twice */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const char *destination = NULL, *seclabel = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering l = d->size - offsetof(struct kdbus_item, data);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering h = (struct bus_header *)((uint8_t *)k + d->vec.offset);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!bus_header_is_complete(h, d->vec.size))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j = l / sizeof(int);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering f = realloc(fds, sizeof(int) * (n_fds + j));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering memcpy(fds + n_fds, d->fds, sizeof(int) * j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* on kdbus we only speak native endian gvariant, never dbus1
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * marshalling or reverse endian */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* The well-known names list is different from the other
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering credentials. If we asked for it, but nothing is there, this
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering means that the list of well-known names is simply empty, not
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering that we lack any data */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering l = d->size - offsetof(struct kdbus_item, data);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Contains body material */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* A -1 offset is NUL padding. */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack part->data = (uint8_t *)k + d->vec.offset + (begin_body - idx);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* The PID starttime/TID might be missing,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * when the data is faked by some data bus
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * proxy and it lacks that information about
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * the real client since SO_PEERCRED is used
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * for that. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->creds.pid_starttime = d->pids.starttime / NSEC_PER_USEC;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_PID_STARTTIME & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* EUID/SUID/FSUID/EGID/SGID/FSGID might be missing too (see above). */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((uid_t) d->creds.euid != (uid_t) -1) {
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering if ((uid_t) d->creds.suid != (uid_t) -1) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((uid_t) d->creds.fsuid != (uid_t) -1) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((gid_t) d->creds.gid != (gid_t) -1) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((gid_t) d->creds.egid != (gid_t) -1) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((gid_t) d->creds.sgid != (gid_t) -1) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((gid_t) d->creds.fsgid != (gid_t) -1) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering 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;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if ((uint32_t) d->audit.sessionid != (uint32_t) -1) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((uid_t) d->audit.loginuid != (uid_t) -1) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.capability = (uint8_t *) d->caps.caps;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.capability_size = d->size - offsetof(struct kdbus_item, caps.caps);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering 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;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!service_name_is_valid(d->name.name)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = strv_extend(&m->creds.well_known_names, d->name.name);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering n = (d->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering for (i = 0; i < n; i++)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Got unknown field from kernel %llu", d->type);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Override information from the user header with data from the kernel */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->sender = m->creds.unique_name = m->sender_buffer;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We take possession of the kmsg struct now */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* If no name is explicitly set, we'll include a hint
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * indicating the library implementation, a hint which
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * kind of bus this is and the thread name */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering g = strappend(b->is_system ? "sd-system-" :
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b->description = bus_label_unescape(name);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hello->attach_flags_send = _KDBUS_ATTACH_ANY;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hello->attach_flags_recv = b->attach_flags;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering item->size = offsetof(struct kdbus_item, str) + m + 1;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering item->type = KDBUS_ITEM_CONN_DESCRIPTION;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering item->size = offsetof(struct kdbus_item, str) + l + 1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* The higher 32bit of the bus_flags fields are considered
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * 'incompatible flags'. Refuse them all for now. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b->bloom_size = (size_t) hello->bloom.size;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b->bloom_n_hash = (unsigned) hello->bloom.n_hash;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* the kernel told us the UUID of the underlying bus */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
700ff4d97311902a440109a2c081731ab6ae8a20Lennart Poettering b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mackstatic void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering cmd.offset = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (void) ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* If we can't deliver, we want room for the error message */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* If this is a synchronous method call, then let's tell the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * kernel, so that it can pass CPU time/scheduling to the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * destination for the time, if it wants to. If we
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * synchronously wait for the result anyway, we won't need CPU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->kdbus->flags |= KDBUS_MSG_FLAGS_EXPECT_REPLY|KDBUS_MSG_FLAGS_SYNC_REPLY;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (errno == ENXIO || errno == ESRCH) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* ENXIO: unique name not known
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * ESRCH: well-known name not known */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->header->type == SD_BUS_MESSAGE_METHOD_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) {
log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
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;
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;
struct kdbus_item *n;
size_t l;
int fd;
assert(s);
if (fd < 0)
return -errno;
sizeof(struct kdbus_bloom_parameter);
n = KDBUS_ITEM_NEXT(n);
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;
if (fd < 0) {
if (path)
free(p);
return -errno;
if (path)
*path = p;
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;
struct kdbus_item *n;
return -errno;