2013-04-11 23:09:29 +02:00
|
|
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
|
|
|
|
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2013 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2013-04-12 02:19:26 +02:00
|
|
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
|
|
|
#include <valgrind/memcheck.h>
|
|
|
|
#endif
|
|
|
|
|
2013-04-11 23:09:29 +02:00
|
|
|
#include <fcntl.h>
|
2013-04-17 18:45:45 +02:00
|
|
|
#include <malloc.h>
|
2014-08-18 19:58:42 +02:00
|
|
|
#include <libgen.h>
|
2013-05-10 03:36:55 +02:00
|
|
|
#include <sys/mman.h>
|
2014-01-22 16:09:59 +01:00
|
|
|
#include <sys/prctl.h>
|
2013-04-11 23:09:29 +02:00
|
|
|
|
|
|
|
#include "util.h"
|
2013-12-04 23:36:02 +01:00
|
|
|
#include "strv.h"
|
2014-10-31 11:22:46 +01:00
|
|
|
#include "memfd-util.h"
|
2013-04-11 23:09:29 +02:00
|
|
|
|
|
|
|
#include "bus-internal.h"
|
|
|
|
#include "bus-message.h"
|
|
|
|
#include "bus-kernel.h"
|
2013-04-14 17:49:18 +02:00
|
|
|
#include "bus-bloom.h"
|
2013-11-29 20:07:56 +01:00
|
|
|
#include "bus-util.h"
|
2014-03-11 19:03:50 +01:00
|
|
|
#include "bus-label.h"
|
2013-12-24 19:31:44 +01:00
|
|
|
#include "cgroup-util.h"
|
2013-11-29 20:07:56 +01:00
|
|
|
|
|
|
|
#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-05-19 18:39:08 +02:00
|
|
|
int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
|
2013-04-11 23:09:29 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(id);
|
|
|
|
|
|
|
|
if (!startswith(s, ":1."))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
r = safe_atou64(s + 3, id);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
|
2013-04-11 23:09:29 +02:00
|
|
|
assert(d);
|
|
|
|
assert(sz > 0);
|
|
|
|
|
2013-04-12 21:43:50 +02:00
|
|
|
*d = ALIGN8_PTR(*d);
|
|
|
|
|
2013-05-16 16:26:35 +02:00
|
|
|
/* Note that p can be NULL, which encodes a region full of
|
|
|
|
* zeroes, which is useful to optimize certain padding
|
|
|
|
* conditions */
|
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
(*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
|
2013-11-29 18:10:36 +01:00
|
|
|
(*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
|
2013-05-16 02:04:13 +02:00
|
|
|
(*d)->vec.address = PTR_TO_UINT64(p);
|
2013-04-11 23:09:29 +02:00
|
|
|
(*d)->vec.size = sz;
|
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
*d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2013-05-16 02:04:13 +02:00
|
|
|
static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
|
|
|
|
assert(d);
|
|
|
|
assert(memfd >= 0);
|
|
|
|
assert(sz > 0);
|
|
|
|
|
|
|
|
*d = ALIGN8_PTR(*d);
|
|
|
|
(*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
|
2013-11-29 18:10:36 +01:00
|
|
|
(*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
|
2013-05-16 02:04:13 +02:00
|
|
|
(*d)->memfd.fd = memfd;
|
|
|
|
(*d)->memfd.size = sz;
|
|
|
|
|
|
|
|
*d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
|
|
|
|
}
|
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
|
2013-04-11 23:09:29 +02:00
|
|
|
assert(d);
|
2013-04-12 22:48:34 +02:00
|
|
|
assert(s);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-04-12 21:43:50 +02:00
|
|
|
*d = ALIGN8_PTR(*d);
|
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
(*d)->size = offsetof(struct kdbus_item, str) + length + 1;
|
2013-11-29 18:10:36 +01:00
|
|
|
(*d)->type = KDBUS_ITEM_DST_NAME;
|
2013-04-12 20:17:00 +02:00
|
|
|
memcpy((*d)->str, s, length + 1);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
*d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2014-01-24 17:06:36 +01:00
|
|
|
static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
|
|
|
|
struct kdbus_item *i;
|
2013-04-14 17:49:18 +02:00
|
|
|
|
2013-04-12 22:48:34 +02:00
|
|
|
assert(d);
|
|
|
|
|
2014-01-24 17:06:36 +01:00
|
|
|
i = ALIGN8_PTR(*d);
|
2013-04-12 22:48:34 +02:00
|
|
|
|
2014-01-24 17:06:36 +01:00
|
|
|
i->size = offsetof(struct kdbus_item, bloom_filter) +
|
|
|
|
offsetof(struct kdbus_bloom_filter, data) +
|
|
|
|
length;
|
|
|
|
i->type = KDBUS_ITEM_BLOOM_FILTER;
|
2013-04-12 22:48:34 +02:00
|
|
|
|
2014-01-24 17:06:36 +01:00
|
|
|
*d = (struct kdbus_item *) ((uint8_t*) i + i->size);
|
2013-04-14 17:49:18 +02:00
|
|
|
|
2014-01-24 17:06:36 +01:00
|
|
|
return &i->bloom_filter;
|
2013-04-14 17:49:18 +02:00
|
|
|
}
|
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
|
2013-04-22 03:24:50 +02:00
|
|
|
assert(d);
|
|
|
|
assert(fds);
|
|
|
|
assert(n_fds > 0);
|
|
|
|
|
|
|
|
*d = ALIGN8_PTR(*d);
|
2013-05-02 19:01:49 +02:00
|
|
|
(*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
|
2013-11-29 18:10:36 +01:00
|
|
|
(*d)->type = KDBUS_ITEM_FDS;
|
2013-04-22 03:24:50 +02:00
|
|
|
memcpy((*d)->fds, fds, sizeof(int) * n_fds);
|
|
|
|
|
2013-05-02 19:01:49 +02:00
|
|
|
*d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
|
2013-04-22 03:24:50 +02:00
|
|
|
}
|
|
|
|
|
2014-01-24 17:06:36 +01:00
|
|
|
static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
|
|
|
|
void *data;
|
2013-04-14 17:49:18 +02:00
|
|
|
unsigned i;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
assert(bloom);
|
|
|
|
|
2014-01-24 17:06:36 +01:00
|
|
|
data = bloom->data;
|
2014-01-31 06:51:32 +01:00
|
|
|
memzero(data, m->bus->bloom_size);
|
2014-01-24 17:06:36 +01:00
|
|
|
bloom->generation = 0;
|
2013-04-14 17:49:18 +02:00
|
|
|
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
|
2013-04-14 17:49:18 +02:00
|
|
|
|
|
|
|
if (m->interface)
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
|
2013-04-14 17:49:18 +02:00
|
|
|
if (m->member)
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
|
2013-04-14 17:49:18 +02:00
|
|
|
if (m->path) {
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
|
|
|
|
bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
|
|
|
|
bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
|
2013-04-14 17:49:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_rewind(m, true);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
for (i = 0; i < 64; i++) {
|
|
|
|
char type;
|
|
|
|
const char *t;
|
|
|
|
char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
|
|
|
|
char *e;
|
|
|
|
|
|
|
|
r = sd_bus_message_peek_type(m, &type, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (type != SD_BUS_TYPE_STRING &&
|
|
|
|
type != SD_BUS_TYPE_OBJECT_PATH &&
|
|
|
|
type != SD_BUS_TYPE_SIGNATURE)
|
|
|
|
break;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_basic(m, type, &t);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
e = stpcpy(buf, "arg");
|
|
|
|
if (i < 10)
|
2013-12-25 17:46:45 +01:00
|
|
|
*(e++) = '0' + (char) i;
|
2013-04-14 17:49:18 +02:00
|
|
|
else {
|
2013-12-25 17:46:45 +01:00
|
|
|
*(e++) = '0' + (char) (i / 10);
|
|
|
|
*(e++) = '0' + (char) (i % 10);
|
2013-04-14 17:49:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*e = 0;
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t);
|
2013-04-14 17:49:18 +02:00
|
|
|
|
|
|
|
strcpy(e, "-dot-prefix");
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '.');
|
2013-04-14 17:49:18 +02:00
|
|
|
strcpy(e, "-slash-prefix");
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '/');
|
2013-04-14 17:49:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2013-04-12 22:48:34 +02:00
|
|
|
}
|
|
|
|
|
2013-04-13 20:12:27 +02:00
|
|
|
static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
|
2013-05-15 01:43:15 +02:00
|
|
|
struct bus_body_part *part;
|
2013-05-02 19:01:49 +02:00
|
|
|
struct kdbus_item *d;
|
2014-10-22 14:41:53 +02:00
|
|
|
const char *destination;
|
2013-04-11 23:09:29 +02:00
|
|
|
bool well_known;
|
|
|
|
uint64_t unique;
|
|
|
|
size_t sz, dl;
|
2013-05-15 01:43:15 +02:00
|
|
|
unsigned i;
|
2013-04-11 23:09:29 +02:00
|
|
|
int r;
|
|
|
|
|
2013-04-13 20:12:27 +02:00
|
|
|
assert(b);
|
2013-04-11 23:09:29 +02:00
|
|
|
assert(m);
|
|
|
|
assert(m->sealed);
|
2013-04-12 01:16:40 +02:00
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
/* We put this together only once, if this message is reused
|
|
|
|
* we reuse the earlier-built version */
|
2013-04-12 01:16:40 +02:00
|
|
|
if (m->kdbus)
|
|
|
|
return 0;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-10-22 14:41:53 +02:00
|
|
|
destination = m->destination ?: m->destination_ptr;
|
|
|
|
|
|
|
|
if (destination) {
|
|
|
|
r = bus_kernel_parse_unique_name(destination, &unique);
|
2013-04-11 23:09:29 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
well_known = r == 0;
|
|
|
|
} else
|
|
|
|
well_known = false;
|
|
|
|
|
2013-04-15 23:32:38 +02:00
|
|
|
sz = offsetof(struct kdbus_msg, items);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-05-16 02:04:13 +02:00
|
|
|
assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
|
|
|
|
ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
|
|
|
|
|
2013-04-13 21:53:11 +02:00
|
|
|
/* Add in fixed header, fields header and payload */
|
2013-05-15 02:56:45 +02:00
|
|
|
sz += (1 + m->n_body_parts) *
|
2013-05-14 22:24:26 +02:00
|
|
|
ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-04-13 21:53:11 +02:00
|
|
|
/* Add space for bloom filter */
|
2014-01-24 17:06:36 +01:00
|
|
|
sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
|
|
|
|
offsetof(struct kdbus_bloom_filter, data) +
|
2014-01-28 00:57:38 +01:00
|
|
|
m->bus->bloom_size);
|
2013-04-12 22:48:34 +02:00
|
|
|
|
2013-04-11 23:09:29 +02:00
|
|
|
/* Add in well-known destination header */
|
|
|
|
if (well_known) {
|
2014-10-22 14:41:53 +02:00
|
|
|
dl = strlen(destination);
|
2013-05-02 19:01:49 +02:00
|
|
|
sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2013-04-22 03:24:50 +02:00
|
|
|
/* Add space for unix fds */
|
|
|
|
if (m->n_fds > 0)
|
2013-05-02 19:01:49 +02:00
|
|
|
sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
|
2013-04-22 03:24:50 +02:00
|
|
|
|
2013-04-17 18:45:45 +02:00
|
|
|
m->kdbus = memalign(8, sz);
|
2013-05-16 16:26:35 +02:00
|
|
|
if (!m->kdbus) {
|
|
|
|
r = -ENOMEM;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-05-16 16:26:35 +02:00
|
|
|
m->free_kdbus = true;
|
2014-01-31 06:51:32 +01:00
|
|
|
memzero(m->kdbus, sz);
|
2013-04-12 21:44:14 +02:00
|
|
|
|
2013-04-11 23:09:29 +02:00
|
|
|
m->kdbus->flags =
|
2013-12-03 18:13:48 +01:00
|
|
|
((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
|
2014-01-20 23:42:05 +01:00
|
|
|
((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
|
2014-10-22 14:41:53 +02:00
|
|
|
|
|
|
|
if (well_known) {
|
|
|
|
/* verify_destination_id will usually be 0, which makes the kernel driver only look
|
|
|
|
* at the provided well-known name. Otherwise, the kernel will make sure the provided
|
|
|
|
* destination id matches the owner of the provided weel-known-name, and fail if they
|
|
|
|
* differ. Currently, this is only needed for bus-proxyd. */
|
|
|
|
m->kdbus->dst_id = m->verify_destination_id;
|
|
|
|
} else {
|
|
|
|
m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
|
|
|
|
}
|
|
|
|
|
2013-12-09 23:03:21 +01:00
|
|
|
m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
|
2014-03-13 20:33:22 +01:00
|
|
|
m->kdbus->cookie = (uint64_t) m->header->serial;
|
2014-01-22 20:01:23 +01:00
|
|
|
m->kdbus->priority = m->priority;
|
2013-12-25 16:42:50 +01:00
|
|
|
|
2014-10-21 22:14:03 +02:00
|
|
|
if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) {
|
2013-12-25 17:46:45 +01:00
|
|
|
m->kdbus->cookie_reply = m->reply_cookie;
|
2014-10-21 22:14:03 +02:00
|
|
|
} else {
|
|
|
|
struct timespec now;
|
|
|
|
|
2014-10-22 13:39:51 +02:00
|
|
|
assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
|
2014-10-21 22:14:03 +02:00
|
|
|
m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
|
|
|
|
m->timeout * NSEC_PER_USEC;
|
|
|
|
}
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-04-15 23:32:38 +02:00
|
|
|
d = m->kdbus->items;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
|
|
|
if (well_known)
|
2014-10-22 14:41:53 +02:00
|
|
|
append_destination(&d, destination, dl);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-05-15 02:56:45 +02:00
|
|
|
append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
|
2013-05-16 02:04:13 +02:00
|
|
|
|
|
|
|
MESSAGE_FOREACH_PART(part, i, m) {
|
|
|
|
if (part->is_zero) {
|
2013-05-16 16:26:35 +02:00
|
|
|
/* If this is padding then simply send a
|
|
|
|
* vector with a NULL data pointer which the
|
|
|
|
* kernel will just pass through. This is the
|
|
|
|
* most efficient way to encode zeroes */
|
|
|
|
|
2013-05-16 02:04:13 +02:00
|
|
|
append_payload_vec(&d, NULL, part->size);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-10-22 14:41:53 +02:00
|
|
|
if (part->memfd >= 0 && part->sealed && destination) {
|
2013-05-16 16:26:35 +02:00
|
|
|
/* Try to send a memfd, if the part is
|
|
|
|
* sealed and this is not a broadcast. Since we can only */
|
2013-05-16 02:04:13 +02:00
|
|
|
|
2013-05-16 16:26:35 +02:00
|
|
|
append_payload_memfd(&d, part->memfd, part->size);
|
|
|
|
continue;
|
2013-05-16 02:04:13 +02:00
|
|
|
}
|
|
|
|
|
2014-02-17 03:37:13 +01:00
|
|
|
/* Otherwise, let's send a vector to the actual data.
|
|
|
|
* For that, we need to map it first. */
|
2013-05-16 16:26:35 +02:00
|
|
|
r = bus_body_part_map(part);
|
|
|
|
if (r < 0)
|
|
|
|
goto fail;
|
2013-05-16 02:04:13 +02:00
|
|
|
|
2013-05-14 22:24:26 +02:00
|
|
|
append_payload_vec(&d, part->data, part->size);
|
2013-05-16 02:04:13 +02:00
|
|
|
}
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-04-13 20:12:27 +02:00
|
|
|
if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
|
2014-01-24 17:06:36 +01:00
|
|
|
struct kdbus_bloom_filter *bloom;
|
2013-04-13 20:12:27 +02:00
|
|
|
|
2014-01-28 00:57:38 +01:00
|
|
|
bloom = append_bloom(&d, m->bus->bloom_size);
|
2014-01-24 17:06:36 +01:00
|
|
|
r = bus_message_setup_bloom(m, bloom);
|
2013-05-16 02:04:13 +02:00
|
|
|
if (r < 0)
|
|
|
|
goto fail;
|
2013-04-13 20:12:27 +02:00
|
|
|
}
|
2013-04-12 22:48:34 +02:00
|
|
|
|
2013-04-22 03:24:50 +02:00
|
|
|
if (m->n_fds > 0)
|
|
|
|
append_fds(&d, m->fds, m->n_fds);
|
|
|
|
|
2013-04-12 01:16:40 +02:00
|
|
|
m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
|
2013-04-11 23:09:29 +02:00
|
|
|
assert(m->kdbus->size <= sz);
|
|
|
|
|
|
|
|
return 0;
|
2013-05-16 02:04:13 +02:00
|
|
|
|
|
|
|
fail:
|
2013-05-16 16:26:35 +02:00
|
|
|
m->poisoned = true;
|
2013-05-16 02:04:13 +02:00
|
|
|
return r;
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2014-10-04 01:47:47 +02:00
|
|
|
static void unset_memfds(struct sd_bus_message *m) {
|
|
|
|
struct bus_body_part *part;
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
|
|
|
|
/* Make sure the memfds are not freed twice */
|
|
|
|
MESSAGE_FOREACH_PART(part, i, m)
|
|
|
|
if (part->memfd >= 0)
|
|
|
|
part->memfd = -1;
|
|
|
|
}
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
|
|
|
|
sd_bus_message *m = NULL;
|
|
|
|
struct kdbus_item *d;
|
|
|
|
unsigned n_fds = 0;
|
|
|
|
_cleanup_free_ int *fds = NULL;
|
|
|
|
struct bus_header *h = NULL;
|
|
|
|
size_t total, n_bytes = 0, idx = 0;
|
|
|
|
const char *destination = NULL, *seclabel = NULL;
|
2013-04-11 23:09:29 +02:00
|
|
|
int r;
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(k);
|
|
|
|
assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
|
2013-12-10 20:31:10 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
KDBUS_ITEM_FOREACH(d, k, items) {
|
|
|
|
size_t l;
|
2013-04-12 03:08:14 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
l = d->size - offsetof(struct kdbus_item, data);
|
2013-05-22 16:02:21 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
switch (d->type) {
|
2013-05-30 05:35:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_PAYLOAD_OFF:
|
|
|
|
if (!h) {
|
|
|
|
h = (struct bus_header *)((uint8_t *)k + d->vec.offset);
|
2013-12-24 15:03:32 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (!bus_header_is_complete(h, d->vec.size))
|
|
|
|
return -EBADMSG;
|
|
|
|
}
|
2013-12-24 15:03:32 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
n_bytes += d->vec.size;
|
|
|
|
break;
|
2013-12-24 15:03:32 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_PAYLOAD_MEMFD:
|
|
|
|
if (!h)
|
|
|
|
return -EBADMSG;
|
2013-12-24 15:03:32 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
n_bytes += d->memfd.size;
|
|
|
|
break;
|
2013-12-24 15:03:32 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_FDS: {
|
|
|
|
int *f;
|
|
|
|
unsigned j;
|
2013-12-24 15:03:32 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
j = l / sizeof(int);
|
|
|
|
f = realloc(fds, sizeof(int) * (n_fds + j));
|
|
|
|
if (!f)
|
|
|
|
return -ENOMEM;
|
2013-12-24 15:03:32 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
fds = f;
|
|
|
|
memcpy(fds + n_fds, d->fds, sizeof(int) * j);
|
|
|
|
n_fds += j;
|
|
|
|
break;
|
|
|
|
}
|
2013-05-30 05:35:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_SECLABEL:
|
|
|
|
seclabel = d->str;
|
|
|
|
break;
|
2013-05-10 03:36:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (!h)
|
|
|
|
return -EBADMSG;
|
2013-04-12 00:43:12 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_header_message_size(h, &total);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-29 22:02:43 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (n_bytes != total)
|
|
|
|
return -EBADMSG;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* on kdbus we only speak native endian gvariant, never dbus1
|
|
|
|
* marshalling or reverse endian */
|
|
|
|
if (h->version != 2 ||
|
|
|
|
h->endian != BUS_NATIVE_ENDIAN)
|
|
|
|
return -EPROTOTYPE;
|
2013-11-29 16:24:40 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* The well-known names list is different from the other
|
|
|
|
credentials. If we asked for it, but nothing is there, this
|
|
|
|
means that the list of well-known names is simply empty, not
|
|
|
|
that we lack any data */
|
2013-12-10 20:31:10 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
|
2013-04-12 03:08:14 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
KDBUS_ITEM_FOREACH(d, k, items) {
|
|
|
|
size_t l;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
l = d->size - offsetof(struct kdbus_item, data);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
switch (d->type) {
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_PAYLOAD_OFF: {
|
|
|
|
size_t begin_body;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
begin_body = BUS_MESSAGE_BODY_BEGIN(m);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (idx + d->vec.size > begin_body) {
|
|
|
|
struct bus_body_part *part;
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* Contains body material */
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
part = message_append_part(m);
|
|
|
|
if (!part) {
|
|
|
|
r = -ENOMEM;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* A -1 offset is NUL padding. */
|
|
|
|
part->is_zero = d->vec.offset == ~0ULL;
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (idx >= begin_body) {
|
|
|
|
if (!part->is_zero)
|
|
|
|
part->data = (uint8_t *)k + d->vec.offset;
|
|
|
|
part->size = d->vec.size;
|
|
|
|
} else {
|
|
|
|
if (!part->is_zero)
|
|
|
|
part->data = (uint8_t *)k + d->vec.offset + (begin_body - idx);
|
|
|
|
part->size = d->vec.size - (begin_body - idx);
|
|
|
|
}
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
part->sealed = true;
|
2013-12-10 21:38:51 +01:00
|
|
|
}
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
idx += d->vec.size;
|
|
|
|
break;
|
|
|
|
}
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_PAYLOAD_MEMFD: {
|
|
|
|
struct bus_body_part *part;
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
|
|
|
|
r = -EBADMSG;
|
|
|
|
goto fail;
|
2013-12-10 21:38:51 +01:00
|
|
|
}
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
part = message_append_part(m);
|
|
|
|
if (!part) {
|
|
|
|
r = -ENOMEM;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
part->memfd = d->memfd.fd;
|
|
|
|
part->size = d->memfd.size;
|
|
|
|
part->sealed = true;
|
2013-11-30 01:02:51 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
idx += d->memfd.size;
|
|
|
|
break;
|
|
|
|
}
|
2013-11-30 01:02:51 +01:00
|
|
|
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
case KDBUS_ITEM_PIDS:
|
|
|
|
|
|
|
|
/* The PID starttime/TID might be missing,
|
|
|
|
* when the data is faked by some data bus
|
|
|
|
* proxy and it lacks that information about
|
|
|
|
* the real client since SO_PEERCRED is used
|
|
|
|
* for that. */
|
|
|
|
|
|
|
|
if (d->pids.pid > 0) {
|
|
|
|
m->creds.pid = (pid_t) d->pids.pid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->pids.starttime > 0) {
|
|
|
|
m->creds.pid_starttime = d->pids.starttime / NSEC_PER_USEC;
|
2014-01-18 20:06:21 +01:00
|
|
|
m->creds.mask |= SD_BUS_CREDS_PID_STARTTIME & bus->creds_mask;
|
|
|
|
}
|
2013-04-11 23:09:29 +02:00
|
|
|
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
if (d->pids.tid > 0) {
|
|
|
|
m->creds.tid = (pid_t) d->pids.tid;
|
2014-01-18 20:06:21 +01:00
|
|
|
m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
|
|
|
|
}
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KDBUS_ITEM_CREDS:
|
|
|
|
|
|
|
|
/* EUID/SUID/FSUID/EGID/SGID/FSGID might be missing too (see above). */
|
|
|
|
|
|
|
|
if ((uid_t) d->creds.uid != (uid_t) -1) {
|
|
|
|
m->creds.uid = (uid_t) d->creds.uid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((uid_t) d->creds.euid != (uid_t) -1) {
|
|
|
|
m->creds.euid = (uid_t) d->creds.euid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((uid_t) d->creds.suid != (uid_t) -1) {
|
|
|
|
m->creds.suid = (uid_t) d->creds.suid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((uid_t) d->creds.fsuid != (uid_t) -1) {
|
|
|
|
m->creds.fsuid = (uid_t) d->creds.fsuid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((gid_t) d->creds.gid != (gid_t) -1) {
|
|
|
|
m->creds.gid = (gid_t) d->creds.gid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((gid_t) d->creds.egid != (gid_t) -1) {
|
|
|
|
m->creds.egid = (gid_t) d->creds.egid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((gid_t) d->creds.sgid != (gid_t) -1) {
|
|
|
|
m->creds.sgid = (gid_t) d->creds.sgid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((gid_t) d->creds.fsgid != (gid_t) -1) {
|
|
|
|
m->creds.fsgid = (gid_t) d->creds.fsgid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
break;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_TIMESTAMP:
|
2014-01-22 16:44:32 +01:00
|
|
|
|
|
|
|
if (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) {
|
|
|
|
m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
|
|
|
|
m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
|
|
|
|
m->seqnum = d->timestamp.seqnum;
|
|
|
|
}
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
break;
|
2013-05-10 03:36:55 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_PID_COMM:
|
|
|
|
m->creds.comm = d->str;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
|
|
|
|
break;
|
2013-05-10 03:36:55 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_TID_COMM:
|
|
|
|
m->creds.tid_comm = d->str;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
|
|
|
|
break;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_EXE:
|
|
|
|
m->creds.exe = d->str;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
|
|
|
|
break;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_CMDLINE:
|
|
|
|
m->creds.cmdline = d->str;
|
|
|
|
m->creds.cmdline_size = l;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
|
|
|
|
break;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_CGROUP:
|
|
|
|
m->creds.cgroup = d->str;
|
|
|
|
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;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-08-18 20:21:55 +02:00
|
|
|
r = bus_get_root_path(bus);
|
|
|
|
if (r < 0)
|
|
|
|
goto fail;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
m->creds.cgroup_root = bus->cgroup_root;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
break;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_AUDIT:
|
2014-11-25 13:22:55 +01:00
|
|
|
if ((uint32_t) d->audit.sessionid != (uint32_t) -1) {
|
|
|
|
m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((uid_t) d->audit.loginuid != (uid_t) -1) {
|
|
|
|
m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
|
|
|
|
}
|
2014-01-18 20:06:21 +01:00
|
|
|
break;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_CAPS:
|
2014-10-27 17:02:31 +01:00
|
|
|
m->creds.capability = (uint8_t *) d->caps.caps;
|
|
|
|
m->creds.capability_size = d->size - offsetof(struct kdbus_item, caps.caps);
|
2014-01-18 20:06:21 +01:00
|
|
|
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;
|
|
|
|
break;
|
2013-11-29 22:02:43 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_DST_NAME:
|
2014-11-25 13:23:44 +01:00
|
|
|
if (!service_name_is_valid(d->str)) {
|
|
|
|
r = -EBADMSG;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-11-29 22:02:43 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
destination = d->str;
|
|
|
|
break;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-11-04 12:08:36 +01:00
|
|
|
case KDBUS_ITEM_OWNED_NAME:
|
2014-11-25 13:23:44 +01:00
|
|
|
if (!service_name_is_valid(d->name.name)) {
|
|
|
|
r = -EBADMSG;
|
2014-01-18 20:06:21 +01:00
|
|
|
goto fail;
|
2014-11-25 13:23:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
|
|
|
|
r = strv_extend(&m->creds.well_known_names, d->name.name);
|
|
|
|
if (r < 0)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
|
|
|
|
}
|
2014-01-18 20:06:21 +01:00
|
|
|
break;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-11-04 12:08:36 +01:00
|
|
|
case KDBUS_ITEM_CONN_DESCRIPTION:
|
2014-11-04 16:13:49 +01:00
|
|
|
m->creds.description = d->str;
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
|
2014-01-22 16:28:58 +01:00
|
|
|
break;
|
|
|
|
|
2014-11-25 13:21:23 +01:00
|
|
|
case KDBUS_ITEM_AUXGROUPS:
|
|
|
|
|
|
|
|
if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
|
|
|
|
size_t i, n;
|
|
|
|
uid_t *u;
|
|
|
|
n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
|
|
|
|
u = new(uid_t, n);
|
|
|
|
if (!u) {
|
|
|
|
r = -ENOMEM;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
u[i] = (uid_t) d->data64[i];
|
|
|
|
|
|
|
|
m->creds.supplementary_gids = u;
|
|
|
|
m->creds.n_supplementary_gids = n;
|
|
|
|
|
|
|
|
m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
case KDBUS_ITEM_FDS:
|
|
|
|
case KDBUS_ITEM_SECLABEL:
|
|
|
|
break;
|
2013-12-12 01:42:41 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
default:
|
|
|
|
log_debug("Got unknown field from kernel %llu", d->type);
|
|
|
|
}
|
|
|
|
}
|
2013-12-12 01:42:41 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_message_parse_fields(m);
|
|
|
|
if (r < 0)
|
|
|
|
goto fail;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* Override information from the user header with data from the kernel */
|
|
|
|
if (k->src_id == KDBUS_SRC_ID_KERNEL)
|
|
|
|
m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
|
|
|
|
else {
|
|
|
|
snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
|
|
|
|
m->sender = m->creds.unique_name = m->sender_buffer;
|
|
|
|
}
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (destination)
|
|
|
|
m->destination = destination;
|
|
|
|
else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
|
|
|
|
m->destination = NULL;
|
|
|
|
else if (k->dst_id == KDBUS_DST_ID_NAME)
|
|
|
|
m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
|
|
|
|
else {
|
|
|
|
snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
|
|
|
|
m->destination = m->destination_buffer;
|
|
|
|
}
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* We take possession of the kmsg struct now */
|
|
|
|
m->kdbus = k;
|
|
|
|
m->release_kdbus = true;
|
|
|
|
m->free_fds = true;
|
|
|
|
fds = NULL;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
bus->rqueue[bus->rqueue_size++] = m;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
return 1;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
fail:
|
2014-10-04 01:47:47 +02:00
|
|
|
unset_memfds(m);
|
|
|
|
sd_bus_message_unref(m);
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
return r;
|
|
|
|
}
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
int bus_kernel_take_fd(sd_bus *b) {
|
|
|
|
struct kdbus_cmd_hello *hello;
|
|
|
|
struct kdbus_item *item;
|
2014-01-22 16:09:59 +01:00
|
|
|
_cleanup_free_ char *g = NULL;
|
|
|
|
const char *name;
|
|
|
|
size_t l = 0, m = 0, sz;
|
2014-01-18 20:06:21 +01:00
|
|
|
int r;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
assert(b);
|
2013-11-30 00:19:01 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (b->is_server)
|
|
|
|
return -EINVAL;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
b->use_memfd = 1;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-11-04 16:13:49 +01:00
|
|
|
if (b->description) {
|
|
|
|
g = bus_label_escape(b->description);
|
2014-01-22 16:09:59 +01:00
|
|
|
if (!g)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
name = g;
|
|
|
|
} else {
|
|
|
|
char pr[17] = {};
|
|
|
|
|
|
|
|
/* If no name is explicitly set, we'll include a hint
|
|
|
|
* indicating the library implementation, a hint which
|
|
|
|
* kind of bus this is and the thread name */
|
|
|
|
|
|
|
|
assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
|
|
|
|
|
|
|
|
if (isempty(pr)) {
|
|
|
|
name = b->is_system ? "sd-system" :
|
|
|
|
b->is_user ? "sd-user" : "sd";
|
|
|
|
} else {
|
|
|
|
_cleanup_free_ char *e = NULL;
|
|
|
|
|
2014-03-11 19:03:50 +01:00
|
|
|
e = bus_label_escape(pr);
|
2014-01-22 16:09:59 +01:00
|
|
|
if (!e)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
g = strappend(b->is_system ? "sd-system-" :
|
|
|
|
b->is_user ? "sd-user-" : "sd-",
|
|
|
|
e);
|
|
|
|
if (!g)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
name = g;
|
|
|
|
}
|
|
|
|
|
2014-11-04 16:13:49 +01:00
|
|
|
b->description = bus_label_unescape(name);
|
|
|
|
if (!b->description)
|
2014-01-22 16:09:59 +01:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
m = strlen(name);
|
|
|
|
|
|
|
|
sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
|
|
|
|
ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (b->fake_creds_valid)
|
2014-01-22 16:09:59 +01:00
|
|
|
sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
|
2013-11-29 20:07:56 +01:00
|
|
|
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
if (b->fake_pids_valid)
|
|
|
|
sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (b->fake_label) {
|
|
|
|
l = strlen(b->fake_label);
|
|
|
|
sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
|
|
|
|
}
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-09-22 12:49:47 +02:00
|
|
|
hello = alloca0_align(sz, 8);
|
2014-01-18 20:06:21 +01:00
|
|
|
hello->size = sz;
|
2014-10-21 19:19:44 +02:00
|
|
|
hello->flags = b->hello_flags;
|
2014-11-05 18:54:50 +01:00
|
|
|
hello->attach_flags_send = _KDBUS_ATTACH_ANY;
|
2014-11-05 14:32:48 +01:00
|
|
|
hello->attach_flags_recv = b->attach_flags;
|
2014-01-18 20:06:21 +01:00
|
|
|
hello->pool_size = KDBUS_POOL_SIZE;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
item = hello->items;
|
|
|
|
|
2014-01-22 16:09:59 +01:00
|
|
|
item->size = offsetof(struct kdbus_item, str) + m + 1;
|
2014-11-04 12:08:36 +01:00
|
|
|
item->type = KDBUS_ITEM_CONN_DESCRIPTION;
|
2014-01-22 16:09:59 +01:00
|
|
|
memcpy(item->str, name, m + 1);
|
|
|
|
item = KDBUS_ITEM_NEXT(item);
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (b->fake_creds_valid) {
|
|
|
|
item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
|
|
|
|
item->type = KDBUS_ITEM_CREDS;
|
|
|
|
item->creds = b->fake_creds;
|
|
|
|
|
|
|
|
item = KDBUS_ITEM_NEXT(item);
|
2013-11-29 20:07:56 +01:00
|
|
|
}
|
|
|
|
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
if (b->fake_pids_valid) {
|
|
|
|
item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
|
|
|
|
item->type = KDBUS_ITEM_PIDS;
|
|
|
|
item->pids = b->fake_pids;
|
|
|
|
|
|
|
|
item = KDBUS_ITEM_NEXT(item);
|
|
|
|
}
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (b->fake_label) {
|
|
|
|
item->size = offsetof(struct kdbus_item, str) + l + 1;
|
2014-01-22 16:09:59 +01:00
|
|
|
item->type = KDBUS_ITEM_SECLABEL;
|
2014-01-18 20:06:21 +01:00
|
|
|
memcpy(item->str, b->fake_label, l+1);
|
2013-11-29 20:07:56 +01:00
|
|
|
}
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
|
|
|
|
if (r < 0)
|
|
|
|
return -errno;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (!b->kdbus_buffer) {
|
|
|
|
b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
|
|
|
|
if (b->kdbus_buffer == MAP_FAILED) {
|
|
|
|
b->kdbus_buffer = NULL;
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
}
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-10-18 20:57:53 +02:00
|
|
|
/* The higher 32bit of the bus_flags fields are considered
|
2014-01-18 20:06:21 +01:00
|
|
|
* 'incompatible flags'. Refuse them all for now. */
|
2014-10-18 20:57:53 +02:00
|
|
|
if (hello->bus_flags > 0xFFFFFFFFULL)
|
2014-01-18 20:06:21 +01:00
|
|
|
return -ENOTSUP;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-28 00:57:38 +01:00
|
|
|
if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash))
|
2014-01-18 20:06:21 +01:00
|
|
|
return -ENOTSUP;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-28 00:57:38 +01:00
|
|
|
b->bloom_size = (size_t) hello->bloom.size;
|
|
|
|
b->bloom_n_hash = (unsigned) hello->bloom.n_hash;
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
|
|
|
|
return -ENOMEM;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
b->unique_id = hello->id;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
b->is_kernel = true;
|
|
|
|
b->bus_client = true;
|
2014-10-21 19:19:44 +02:00
|
|
|
b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
|
2014-01-18 20:06:21 +01:00
|
|
|
b->message_version = 2;
|
|
|
|
b->message_endian = BUS_NATIVE_ENDIAN;
|
2013-05-15 02:56:45 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* the kernel told us the UUID of the underlying bus */
|
|
|
|
memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
return bus_start_running(b);
|
|
|
|
}
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
int bus_kernel_connect(sd_bus *b) {
|
|
|
|
assert(b);
|
|
|
|
assert(b->input_fd < 0);
|
|
|
|
assert(b->output_fd < 0);
|
|
|
|
assert(b->kernel);
|
2013-05-16 02:37:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (b->is_server)
|
|
|
|
return -EINVAL;
|
2013-05-16 02:37:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
|
|
|
|
if (b->input_fd < 0)
|
|
|
|
return -errno;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
b->output_fd = b->input_fd;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
return bus_kernel_take_fd(b);
|
|
|
|
}
|
2013-04-12 01:45:18 +02:00
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
|
2014-11-25 19:25:19 +01:00
|
|
|
struct kdbus_cmd_free cmd = {};
|
2014-01-21 15:02:07 +01:00
|
|
|
struct kdbus_item *d;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(k);
|
|
|
|
|
2014-10-06 18:36:16 +02:00
|
|
|
cmd.offset = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
|
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
KDBUS_ITEM_FOREACH(d, k, items) {
|
|
|
|
|
|
|
|
if (d->type == KDBUS_ITEM_FDS)
|
|
|
|
close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
|
|
|
|
else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
|
2014-03-18 19:22:43 +01:00
|
|
|
safe_close(d->memfd.fd);
|
2014-01-21 15:02:07 +01:00
|
|
|
}
|
2014-10-07 11:32:07 +02:00
|
|
|
|
|
|
|
(void) ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
|
2014-01-21 15:02:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
|
2014-01-18 20:06:21 +01:00
|
|
|
int r;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(m);
|
|
|
|
assert(bus->state == BUS_RUNNING);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* If we can't deliver, we want room for the error message */
|
|
|
|
r = bus_rqueue_make_room(bus);
|
2013-04-11 23:09:29 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_message_setup_kmsg(bus, m);
|
2013-04-11 23:09:29 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
/* If this is a synchronous method call, then let's tell the
|
|
|
|
* kernel, so that it can pass CPU time/scheduling to the
|
|
|
|
* destination for the time, if it wants to. If we
|
|
|
|
* synchronously wait for the result anyway, we won't need CPU
|
|
|
|
* anyway. */
|
|
|
|
if (hint_sync_call)
|
|
|
|
m->kdbus->flags |= KDBUS_MSG_FLAGS_EXPECT_REPLY|KDBUS_MSG_FLAGS_SYNC_REPLY;
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
|
|
|
|
if (r < 0) {
|
|
|
|
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
|
|
sd_bus_message *reply;
|
2013-12-21 03:16:39 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (errno == EAGAIN || errno == EINTR)
|
|
|
|
return 0;
|
|
|
|
else if (errno == ENXIO || errno == ESRCH) {
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* ENXIO: unique name not known
|
|
|
|
* ESRCH: well-known name not known */
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
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);
|
|
|
|
else {
|
|
|
|
log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
} else if (errno == EADDRNOTAVAIL) {
|
2013-05-10 03:36:55 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
/* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
|
|
|
|
sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
|
|
|
|
else {
|
|
|
|
log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
return -errno;
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_message_new_synthetic_error(
|
|
|
|
bus,
|
|
|
|
BUS_MESSAGE_COOKIE(m),
|
|
|
|
&error,
|
|
|
|
&reply);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_seal_synthetic_message(bus, reply);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-05-30 05:35:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
bus->rqueue[bus->rqueue_size++] = reply;
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
} else if (hint_sync_call) {
|
|
|
|
struct kdbus_msg *k;
|
2013-05-10 03:36:55 +02:00
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + m->kdbus->offset_reply);
|
|
|
|
assert(k);
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
|
2013-05-16 02:37:42 +02:00
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
r = bus_kernel_make_message(bus, k);
|
|
|
|
if (r < 0) {
|
|
|
|
close_kdbus_msg(bus, k);
|
2013-05-16 02:37:42 +02:00
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
/* Anybody can send us invalid messages, let's just drop them. */
|
|
|
|
if (r == -EBADMSG || r == -EPROTOTYPE)
|
|
|
|
log_debug("Ignoring invalid message: %s", strerror(-r));
|
|
|
|
else
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
|
|
|
|
close_kdbus_msg(bus, k);
|
|
|
|
}
|
2014-01-18 20:06:21 +01:00
|
|
|
}
|
2014-01-21 15:02:07 +01:00
|
|
|
|
|
|
|
return 1;
|
2014-01-18 20:06:21 +01:00
|
|
|
}
|
2013-04-13 21:53:11 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
|
|
|
|
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
|
|
|
|
int r;
|
2013-12-24 16:20:47 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
assert(bus);
|
2013-12-24 16:20:47 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = sd_bus_message_new_signal(
|
|
|
|
bus,
|
2014-02-19 23:54:58 +01:00
|
|
|
&m,
|
2014-01-18 20:06:21 +01:00
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus",
|
2014-02-19 23:54:58 +01:00
|
|
|
"NameOwnerChanged");
|
2014-01-18 20:06:21 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-12-24 16:20:47 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
m->sender = "org.freedesktop.DBus";
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_seal_synthetic_message(bus, m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
bus->rqueue[bus->rqueue_size++] = m;
|
|
|
|
m = NULL;
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
|
|
|
|
char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(k);
|
|
|
|
assert(d);
|
2013-12-24 19:31:44 +01:00
|
|
|
|
2014-09-23 16:13:54 +02:00
|
|
|
if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
|
2014-01-18 20:06:21 +01:00
|
|
|
old_owner[0] = 0;
|
|
|
|
else
|
2014-09-23 16:13:54 +02:00
|
|
|
sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id);
|
2013-12-24 19:31:44 +01:00
|
|
|
|
2014-09-23 16:13:54 +02:00
|
|
|
if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
|
2013-12-24 19:31:44 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (isempty(old_owner))
|
|
|
|
return 0;
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
new_owner[0] = 0;
|
|
|
|
} else
|
2014-09-23 16:13:54 +02:00
|
|
|
sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id);
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner);
|
|
|
|
}
|
2013-11-28 17:50:02 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
|
|
|
|
char owner[UNIQUE_NAME_MAX];
|
2013-12-27 00:27:43 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(k);
|
|
|
|
assert(d);
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
sprintf(owner, ":1.%llu", d->id_change.id);
|
2013-12-27 00:27:43 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
return push_name_owner_changed(
|
|
|
|
bus, owner,
|
|
|
|
d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
|
|
|
|
d->type == KDBUS_ITEM_ID_ADD ? owner : NULL);
|
|
|
|
}
|
2013-11-30 04:14:10 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
|
|
|
|
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
|
|
|
|
int r;
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(k);
|
|
|
|
assert(d);
|
2013-04-12 01:57:53 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_message_new_synthetic_error(
|
|
|
|
bus,
|
|
|
|
k->cookie_reply,
|
|
|
|
d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
|
|
|
|
&SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
|
|
|
|
&SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
|
|
|
|
&m);
|
2013-05-16 02:37:42 +02:00
|
|
|
if (r < 0)
|
2014-01-18 20:06:21 +01:00
|
|
|
return r;
|
2013-04-12 20:17:00 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
m->sender = "org.freedesktop.DBus";
|
2013-04-12 20:17:00 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
r = bus_seal_synthetic_message(bus, m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-11-30 00:19:01 +01:00
|
|
|
bus->rqueue[bus->rqueue_size++] = m;
|
2014-01-18 20:06:21 +01:00
|
|
|
m = NULL;
|
2013-11-29 21:29:16 +01:00
|
|
|
|
2013-04-11 23:09:29 +02:00
|
|
|
return 1;
|
2014-01-18 20:06:21 +01:00
|
|
|
}
|
2013-05-16 02:37:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
|
|
|
|
struct kdbus_item *d, *found = NULL;
|
2013-05-16 02:37:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) = {
|
|
|
|
[KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
|
|
|
|
[KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
|
|
|
|
[KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
|
2013-05-16 02:37:42 +02:00
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
[KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
|
|
|
|
[KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
|
|
|
|
|
|
|
|
[KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
|
|
|
|
[KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(k);
|
|
|
|
assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
|
|
|
|
|
|
|
|
KDBUS_ITEM_FOREACH(d, k, items) {
|
|
|
|
if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
|
|
|
|
if (found)
|
|
|
|
return -EBADMSG;
|
|
|
|
found = d;
|
|
|
|
} else
|
|
|
|
log_debug("Got unknown field from kernel %llu", d->type);
|
2013-05-16 02:37:42 +02:00
|
|
|
}
|
|
|
|
|
2014-01-18 20:06:21 +01:00
|
|
|
if (!found) {
|
|
|
|
log_debug("Didn't find a kernel message to translate.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found);
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2014-01-22 20:26:58 +01:00
|
|
|
int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
|
2014-01-17 01:29:48 +01:00
|
|
|
struct kdbus_cmd_recv recv = {};
|
2013-04-11 23:09:29 +02:00
|
|
|
struct kdbus_msg *k;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
2013-11-29 21:29:16 +01:00
|
|
|
|
2013-11-30 00:19:01 +01:00
|
|
|
r = bus_rqueue_make_room(bus);
|
2013-11-29 21:29:16 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2014-01-22 20:26:58 +01:00
|
|
|
if (hint_priority) {
|
|
|
|
recv.flags |= KDBUS_RECV_USE_PRIORITY;
|
|
|
|
recv.priority = priority;
|
|
|
|
}
|
|
|
|
|
2014-01-17 01:29:48 +01:00
|
|
|
r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &recv);
|
2013-05-10 03:36:55 +02:00
|
|
|
if (r < 0) {
|
2013-04-11 23:09:29 +02:00
|
|
|
if (errno == EAGAIN)
|
|
|
|
return 0;
|
|
|
|
|
2014-11-25 19:54:18 +01:00
|
|
|
if (errno == EOVERFLOW) {
|
|
|
|
log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-10 03:36:55 +02:00
|
|
|
return -errno;
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2014-01-21 15:02:07 +01:00
|
|
|
k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset);
|
2013-12-10 01:07:09 +01:00
|
|
|
if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
|
2013-11-29 21:29:16 +01:00
|
|
|
r = bus_kernel_make_message(bus, k);
|
2013-12-10 01:07:09 +01:00
|
|
|
|
|
|
|
/* Anybody can send us invalid messages, let's just drop them. */
|
|
|
|
if (r == -EBADMSG || r == -EPROTOTYPE) {
|
2013-12-10 21:38:51 +01:00
|
|
|
log_debug("Ignoring invalid message: %s", strerror(-r));
|
2013-12-10 01:07:09 +01:00
|
|
|
r = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
|
2013-11-29 21:29:16 +01:00
|
|
|
r = bus_kernel_translate_message(bus, k);
|
2014-01-21 15:02:07 +01:00
|
|
|
else {
|
|
|
|
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
|
2013-11-29 20:07:56 +01:00
|
|
|
r = 0;
|
2014-01-21 15:02:07 +01:00
|
|
|
}
|
2013-11-29 20:07:56 +01:00
|
|
|
|
2013-05-10 03:36:55 +02:00
|
|
|
if (r <= 0)
|
|
|
|
close_kdbus_msg(bus, k);
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-04-12 20:17:00 +02:00
|
|
|
return r < 0 ? r : 1;
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2013-12-18 18:46:23 +01:00
|
|
|
int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
|
2013-05-14 22:24:26 +02:00
|
|
|
struct memfd_cache *c;
|
2013-05-17 03:13:58 +02:00
|
|
|
int fd;
|
2013-05-14 22:24:26 +02:00
|
|
|
|
|
|
|
assert(address);
|
2013-12-18 18:46:23 +01:00
|
|
|
assert(mapped);
|
|
|
|
assert(allocated);
|
2013-12-10 20:31:10 +01:00
|
|
|
|
|
|
|
if (!bus || !bus->is_kernel)
|
|
|
|
return -ENOTSUP;
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2013-05-29 09:58:31 +02:00
|
|
|
assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
|
2013-05-17 03:13:58 +02:00
|
|
|
|
2013-05-14 22:24:26 +02:00
|
|
|
if (bus->n_memfd_cache <= 0) {
|
2013-05-17 03:13:58 +02:00
|
|
|
int r;
|
|
|
|
|
2013-05-29 09:58:31 +02:00
|
|
|
assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2014-11-04 16:13:49 +01:00
|
|
|
r = memfd_new(bus->description);
|
2013-05-14 22:52:58 +02:00
|
|
|
if (r < 0)
|
2014-10-30 18:28:37 +01:00
|
|
|
return r;
|
2013-05-14 22:24:26 +02:00
|
|
|
|
|
|
|
*address = NULL;
|
2013-12-18 18:46:23 +01:00
|
|
|
*mapped = 0;
|
|
|
|
*allocated = 0;
|
2014-05-13 01:28:09 +02:00
|
|
|
return r;
|
2013-05-14 22:24:26 +02:00
|
|
|
}
|
|
|
|
|
2013-06-04 23:37:57 +02:00
|
|
|
c = &bus->memfd_cache[--bus->n_memfd_cache];
|
2013-05-14 22:24:26 +02:00
|
|
|
|
|
|
|
assert(c->fd >= 0);
|
2013-12-18 18:46:23 +01:00
|
|
|
assert(c->mapped == 0 || c->address);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
|
|
|
*address = c->address;
|
2013-12-18 18:46:23 +01:00
|
|
|
*mapped = c->mapped;
|
|
|
|
*allocated = c->allocated;
|
2013-05-17 03:13:58 +02:00
|
|
|
fd = c->fd;
|
|
|
|
|
2013-05-29 09:58:31 +02:00
|
|
|
assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2013-05-17 03:13:58 +02:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void close_and_munmap(int fd, void *address, size_t size) {
|
|
|
|
if (size > 0)
|
2013-05-29 09:58:31 +02:00
|
|
|
assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
|
2013-05-17 03:13:58 +02:00
|
|
|
|
2014-03-18 19:22:43 +01:00
|
|
|
safe_close(fd);
|
2013-05-14 22:24:26 +02:00
|
|
|
}
|
|
|
|
|
2013-12-18 18:46:23 +01:00
|
|
|
void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
|
2013-05-14 22:24:26 +02:00
|
|
|
struct memfd_cache *c;
|
2013-12-18 18:46:23 +01:00
|
|
|
uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
|
|
|
assert(fd >= 0);
|
2013-12-18 18:46:23 +01:00
|
|
|
assert(mapped == 0 || address);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2013-05-17 03:13:58 +02:00
|
|
|
if (!bus || !bus->is_kernel) {
|
2013-12-18 18:46:23 +01:00
|
|
|
close_and_munmap(fd, address, mapped);
|
2013-05-17 03:13:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-29 09:58:31 +02:00
|
|
|
assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2013-05-17 03:13:58 +02:00
|
|
|
if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
|
2013-05-29 09:58:31 +02:00
|
|
|
assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
|
2013-05-14 22:24:26 +02:00
|
|
|
|
2013-12-18 18:46:23 +01:00
|
|
|
close_and_munmap(fd, address, mapped);
|
2013-05-14 22:24:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = &bus->memfd_cache[bus->n_memfd_cache++];
|
|
|
|
c->fd = fd;
|
|
|
|
c->address = address;
|
|
|
|
|
|
|
|
/* If overly long, let's return a bit to the OS */
|
2013-12-18 18:46:23 +01:00
|
|
|
if (mapped > max_mapped) {
|
2014-10-30 18:28:37 +01:00
|
|
|
assert_se(memfd_set_size(fd, max_mapped) >= 0);
|
2013-12-18 18:46:23 +01:00
|
|
|
assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
|
|
|
|
c->mapped = c->allocated = max_mapped;
|
|
|
|
} else {
|
|
|
|
c->mapped = mapped;
|
|
|
|
c->allocated = allocated;
|
|
|
|
}
|
2013-05-17 03:13:58 +02:00
|
|
|
|
2013-05-29 09:58:31 +02:00
|
|
|
assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
|
2013-05-14 22:24:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void bus_kernel_flush_memfd(sd_bus *b) {
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
assert(b);
|
|
|
|
|
2013-05-29 09:58:31 +02:00
|
|
|
for (i = 0; i < b->n_memfd_cache; i++)
|
2013-12-18 18:46:23 +01:00
|
|
|
close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
|
2013-05-14 22:24:26 +02:00
|
|
|
}
|
2013-11-26 16:45:50 +01:00
|
|
|
|
2014-11-26 02:20:28 +01:00
|
|
|
uint64_t request_name_flags_to_kdbus(uint64_t flags) {
|
2013-11-30 03:53:42 +01:00
|
|
|
uint64_t f = 0;
|
2013-11-26 16:45:50 +01:00
|
|
|
|
2013-11-30 03:53:42 +01:00
|
|
|
if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
|
|
|
|
f |= KDBUS_NAME_ALLOW_REPLACEMENT;
|
2013-11-26 16:45:50 +01:00
|
|
|
|
2013-11-30 03:53:42 +01:00
|
|
|
if (flags & SD_BUS_NAME_REPLACE_EXISTING)
|
|
|
|
f |= KDBUS_NAME_REPLACE_EXISTING;
|
2013-11-26 16:45:50 +01:00
|
|
|
|
2013-12-12 06:23:38 +01:00
|
|
|
if (flags & SD_BUS_NAME_QUEUE)
|
2013-11-30 03:53:42 +01:00
|
|
|
f |= KDBUS_NAME_QUEUE;
|
2013-11-26 16:45:50 +01:00
|
|
|
|
2014-11-26 02:20:28 +01:00
|
|
|
return f;
|
2013-11-30 03:53:42 +01:00
|
|
|
}
|
|
|
|
|
2014-11-26 02:20:28 +01:00
|
|
|
uint64_t attach_flags_to_kdbus(uint64_t mask) {
|
2013-11-30 03:53:42 +01:00
|
|
|
uint64_t m = 0;
|
|
|
|
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
|
|
|
|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
|
2013-11-30 03:53:42 +01:00
|
|
|
m |= KDBUS_ATTACH_CREDS;
|
|
|
|
|
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also:
- adds support for euid, suid, fsuid, egid, sgid, fsgid fields.
- makes augmentation of creds with data from /proc explicitly
controllable to give apps better control over this, given that this is
racy.
- enables augmentation for kdbus connections (previously we only did it
for dbus1). This is useful since with recent kdbus versions it is
possible for clients to control the metadata they want to send.
- changes sd_bus_query_sender_privilege() to take the euid of the client
into consideration, if known
- when we don't have permissions to read augmentation data from /proc,
don't fail, just don't add the data in
2014-11-24 21:41:40 +01:00
|
|
|
if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
|
|
|
|
m |= KDBUS_ATTACH_PIDS;
|
|
|
|
|
2014-10-20 15:26:00 +02:00
|
|
|
if (mask & SD_BUS_CREDS_COMM)
|
|
|
|
m |= KDBUS_ATTACH_PID_COMM;
|
|
|
|
|
|
|
|
if (mask & SD_BUS_CREDS_TID_COMM)
|
|
|
|
m |= KDBUS_ATTACH_TID_COMM;
|
2013-11-30 03:53:42 +01:00
|
|
|
|
|
|
|
if (mask & SD_BUS_CREDS_EXE)
|
|
|
|
m |= KDBUS_ATTACH_EXE;
|
|
|
|
|
|
|
|
if (mask & SD_BUS_CREDS_CMDLINE)
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
|
|
|
|
m |= KDBUS_ATTACH_SECLABEL;
|
2013-11-26 16:45:50 +01:00
|
|
|
|
2013-11-30 03:53:42 +01:00
|
|
|
if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
|
|
|
|
m |= KDBUS_ATTACH_AUDIT;
|
|
|
|
|
2013-11-30 04:14:10 +01:00
|
|
|
if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
|
|
|
|
m |= KDBUS_ATTACH_NAMES;
|
|
|
|
|
2014-11-04 16:13:49 +01:00
|
|
|
if (mask & SD_BUS_CREDS_DESCRIPTION)
|
2014-11-04 12:08:36 +01:00
|
|
|
m |= KDBUS_ATTACH_CONN_DESCRIPTION;
|
2014-01-22 16:28:58 +01:00
|
|
|
|
2014-11-25 13:21:23 +01:00
|
|
|
if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
|
|
|
|
m |= KDBUS_ATTACH_AUXGROUPS;
|
|
|
|
|
2014-11-26 02:20:28 +01:00
|
|
|
return m;
|
2013-11-26 16:45:50 +01:00
|
|
|
}
|
2013-11-30 03:53:42 +01:00
|
|
|
|
2013-12-26 03:08:15 +01:00
|
|
|
int bus_kernel_create_bus(const char *name, bool world, char **s) {
|
2013-12-17 13:45:02 +01:00
|
|
|
struct kdbus_cmd_make *make;
|
2013-11-30 03:53:42 +01:00
|
|
|
struct kdbus_item *n;
|
2014-11-26 02:50:49 +01:00
|
|
|
size_t l;
|
2013-11-30 03:53:42 +01:00
|
|
|
int fd;
|
|
|
|
|
|
|
|
assert(name);
|
|
|
|
assert(s);
|
|
|
|
|
sd-bus: sync with kdbus upstream (ABI break)
kdbus has seen a larger update than expected lately, most notably with
kdbusfs, a file system to expose the kdbus control files:
* Each time a file system of this type is mounted, a new kdbus
domain is created.
* The layout inside each mount point is the same as before, except
that domains are not hierarchically nested anymore.
* Domains are therefore also unnamed now.
* Unmounting a kdbusfs will automatically also detroy the
associated domain.
* Hence, the action of creating a kdbus domain is now as
privileged as mounting a filesystem.
* This way, we can get around creating dev nodes for everything,
which is last but not least something that is not limited by
20-bit minor numbers.
The kdbus specific bits in nspawn have all been dropped now, as nspawn
can rely on the container OS to set up its own kdbus domain, simply by
mounting a new instance.
A new set of mounts has been added to mount things *after* the kernel
modules have been loaded. For now, only kdbus is in this set, which is
invoked with mount_setup_late().
2014-11-13 20:33:03 +01:00
|
|
|
fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
|
2013-11-30 03:53:42 +01:00
|
|
|
if (fd < 0)
|
|
|
|
return -errno;
|
|
|
|
|
2014-11-26 02:50:49 +01:00
|
|
|
l = strlen(name);
|
|
|
|
make = alloca0_align(offsetof(struct kdbus_cmd_make, items) +
|
|
|
|
ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
|
|
|
|
ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
|
|
|
|
ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
|
2014-09-22 12:49:47 +02:00
|
|
|
8);
|
2013-11-30 03:53:42 +01:00
|
|
|
|
2013-12-17 13:45:02 +01:00
|
|
|
make->size = offsetof(struct kdbus_cmd_make, items);
|
|
|
|
|
2014-11-26 02:50:49 +01:00
|
|
|
/* Set the bloom parameters */
|
2013-11-30 03:53:42 +01:00
|
|
|
n = make->items;
|
2014-01-24 17:06:36 +01:00
|
|
|
n->size = offsetof(struct kdbus_item, bloom_parameter) +
|
|
|
|
sizeof(struct kdbus_bloom_parameter);
|
|
|
|
n->type = KDBUS_ITEM_BLOOM_PARAMETER;
|
2014-01-28 00:57:38 +01:00
|
|
|
n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
|
|
|
|
n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
|
|
|
|
|
|
|
|
assert_cc(DEFAULT_BLOOM_SIZE > 0);
|
|
|
|
assert_cc(DEFAULT_BLOOM_N_HASH > 0);
|
|
|
|
|
2013-12-17 13:45:02 +01:00
|
|
|
make->size += ALIGN8(n->size);
|
|
|
|
|
2014-11-26 02:50:49 +01:00
|
|
|
/* The busses we create make no restrictions on what metadata
|
|
|
|
* peers can read from incoming messages. */
|
|
|
|
n = KDBUS_ITEM_NEXT(n);
|
|
|
|
n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
|
|
|
|
n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
|
|
|
|
n->data64[0] = _KDBUS_ATTACH_ANY;
|
|
|
|
make->size += ALIGN8(n->size);
|
|
|
|
|
|
|
|
/* Set the a good name */
|
2013-12-17 13:45:02 +01:00
|
|
|
n = KDBUS_ITEM_NEXT(n);
|
2014-06-05 12:24:03 +02:00
|
|
|
sprintf(n->str, UID_FMT "-%s", getuid(), name);
|
2013-11-30 03:53:42 +01:00
|
|
|
n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
|
2013-12-06 20:19:20 +01:00
|
|
|
n->type = KDBUS_ITEM_MAKE_NAME;
|
2013-12-17 13:45:02 +01:00
|
|
|
make->size += ALIGN8(n->size);
|
2013-11-30 03:53:42 +01:00
|
|
|
|
2014-03-07 17:14:52 +01:00
|
|
|
make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
|
2013-11-30 03:53:42 +01:00
|
|
|
|
|
|
|
if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
|
2014-03-18 19:22:43 +01:00
|
|
|
safe_close(fd);
|
2013-11-30 03:53:42 +01:00
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s) {
|
|
|
|
char *p;
|
|
|
|
|
sd-bus: sync with kdbus upstream (ABI break)
kdbus has seen a larger update than expected lately, most notably with
kdbusfs, a file system to expose the kdbus control files:
* Each time a file system of this type is mounted, a new kdbus
domain is created.
* The layout inside each mount point is the same as before, except
that domains are not hierarchically nested anymore.
* Domains are therefore also unnamed now.
* Unmounting a kdbusfs will automatically also detroy the
associated domain.
* Hence, the action of creating a kdbus domain is now as
privileged as mounting a filesystem.
* This way, we can get around creating dev nodes for everything,
which is last but not least something that is not limited by
20-bit minor numbers.
The kdbus specific bits in nspawn have all been dropped now, as nspawn
can rely on the container OS to set up its own kdbus domain, simply by
mounting a new instance.
A new set of mounts has been added to mount things *after* the kernel
modules have been loaded. For now, only kdbus is in this set, which is
invoked with mount_setup_late().
2014-11-13 20:33:03 +01:00
|
|
|
p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL);
|
2013-11-30 03:53:42 +01:00
|
|
|
if (!p) {
|
2014-03-18 19:22:43 +01:00
|
|
|
safe_close(fd);
|
2013-11-30 03:53:42 +01:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
*s = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
2013-11-30 16:36:46 +01:00
|
|
|
|
2014-08-18 22:07:47 +02:00
|
|
|
static int bus_kernel_translate_access(BusPolicyAccess access) {
|
2014-06-05 12:24:03 +02:00
|
|
|
assert(access >= 0);
|
2014-08-18 22:07:47 +02:00
|
|
|
assert(access < _BUS_POLICY_ACCESS_MAX);
|
2014-06-05 12:24:03 +02:00
|
|
|
|
|
|
|
switch (access) {
|
|
|
|
|
2014-08-18 22:07:47 +02:00
|
|
|
case BUS_POLICY_ACCESS_SEE:
|
2014-06-05 12:24:03 +02:00
|
|
|
return KDBUS_POLICY_SEE;
|
|
|
|
|
2014-08-18 22:07:47 +02:00
|
|
|
case BUS_POLICY_ACCESS_TALK:
|
2014-06-05 12:24:03 +02:00
|
|
|
return KDBUS_POLICY_TALK;
|
|
|
|
|
2014-08-18 22:07:47 +02:00
|
|
|
case BUS_POLICY_ACCESS_OWN:
|
2014-06-05 12:24:03 +02:00
|
|
|
return KDBUS_POLICY_OWN;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert_not_reached("Unknown policy access");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
|
|
|
|
int r;
|
2014-03-19 04:17:00 +01:00
|
|
|
|
|
|
|
assert(policy);
|
|
|
|
assert(item);
|
|
|
|
|
2014-03-07 17:29:01 +01:00
|
|
|
switch (policy->type) {
|
2014-03-19 04:17:00 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
case BUSNAME_POLICY_TYPE_USER: {
|
|
|
|
const char *user = policy->name;
|
|
|
|
uid_t uid;
|
|
|
|
|
|
|
|
r = get_user_creds(&user, &uid, NULL, NULL, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2014-03-07 17:29:01 +01:00
|
|
|
item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
|
2014-06-05 12:24:03 +02:00
|
|
|
item->policy_access.id = uid;
|
2014-03-07 17:29:01 +01:00
|
|
|
break;
|
2014-06-05 12:24:03 +02:00
|
|
|
}
|
2014-03-07 17:29:01 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
case BUSNAME_POLICY_TYPE_GROUP: {
|
|
|
|
const char *group = policy->name;
|
|
|
|
gid_t gid;
|
2014-03-07 17:29:01 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
r = get_group_creds(&group, &gid);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
|
|
|
|
item->policy_access.id = gid;
|
2014-03-07 17:29:01 +01:00
|
|
|
break;
|
2014-06-05 12:24:03 +02:00
|
|
|
}
|
2014-03-07 17:29:01 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
assert_not_reached("Unknown policy type");
|
|
|
|
}
|
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
item->policy_access.access = bus_kernel_translate_access(policy->access);
|
2014-03-19 04:17:00 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2014-03-07 17:29:01 +01:00
|
|
|
|
2014-07-26 20:59:52 +02:00
|
|
|
int bus_kernel_open_bus_fd(const char *bus, char **path) {
|
2014-06-05 12:24:03 +02:00
|
|
|
char *p;
|
|
|
|
int fd;
|
2014-07-26 20:59:52 +02:00
|
|
|
size_t len;
|
2014-03-07 17:29:01 +01:00
|
|
|
|
2014-11-26 02:54:11 +01:00
|
|
|
assert(bus);
|
|
|
|
|
sd-bus: sync with kdbus upstream (ABI break)
kdbus has seen a larger update than expected lately, most notably with
kdbusfs, a file system to expose the kdbus control files:
* Each time a file system of this type is mounted, a new kdbus
domain is created.
* The layout inside each mount point is the same as before, except
that domains are not hierarchically nested anymore.
* Domains are therefore also unnamed now.
* Unmounting a kdbusfs will automatically also detroy the
associated domain.
* Hence, the action of creating a kdbus domain is now as
privileged as mounting a filesystem.
* This way, we can get around creating dev nodes for everything,
which is last but not least something that is not limited by
20-bit minor numbers.
The kdbus specific bits in nspawn have all been dropped now, as nspawn
can rely on the container OS to set up its own kdbus domain, simply by
mounting a new instance.
A new set of mounts has been added to mount things *after* the kernel
modules have been loaded. For now, only kdbus is in this set, which is
invoked with mount_setup_late().
2014-11-13 20:33:03 +01:00
|
|
|
len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
|
2014-07-26 20:59:52 +02:00
|
|
|
|
|
|
|
if (path) {
|
2014-11-26 02:54:11 +01:00
|
|
|
p = new(char, len);
|
2014-07-26 20:59:52 +02:00
|
|
|
if (!p)
|
|
|
|
return -ENOMEM;
|
|
|
|
} else
|
2014-11-26 02:54:11 +01:00
|
|
|
p = newa(char, len);
|
|
|
|
|
sd-bus: sync with kdbus upstream (ABI break)
kdbus has seen a larger update than expected lately, most notably with
kdbusfs, a file system to expose the kdbus control files:
* Each time a file system of this type is mounted, a new kdbus
domain is created.
* The layout inside each mount point is the same as before, except
that domains are not hierarchically nested anymore.
* Domains are therefore also unnamed now.
* Unmounting a kdbusfs will automatically also detroy the
associated domain.
* Hence, the action of creating a kdbus domain is now as
privileged as mounting a filesystem.
* This way, we can get around creating dev nodes for everything,
which is last but not least something that is not limited by
20-bit minor numbers.
The kdbus specific bits in nspawn have all been dropped now, as nspawn
can rely on the container OS to set up its own kdbus domain, simply by
mounting a new instance.
A new set of mounts has been added to mount things *after* the kernel
modules have been loaded. For now, only kdbus is in this set, which is
invoked with mount_setup_late().
2014-11-13 20:33:03 +01:00
|
|
|
sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
|
2014-03-07 17:29:01 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
|
2014-11-26 02:54:11 +01:00
|
|
|
if (fd < 0) {
|
|
|
|
if (path)
|
|
|
|
free(p);
|
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
return -errno;
|
2014-11-26 02:54:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (path)
|
|
|
|
*path = p;
|
2014-06-05 12:24:03 +02:00
|
|
|
|
|
|
|
return fd;
|
2014-03-07 17:29:01 +01:00
|
|
|
}
|
|
|
|
|
2014-08-18 19:58:42 +02:00
|
|
|
int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
|
2014-10-02 20:36:58 +02:00
|
|
|
_cleanup_free_ char *path = NULL;
|
2014-08-18 19:58:42 +02:00
|
|
|
struct kdbus_cmd_make *make;
|
|
|
|
struct kdbus_item *n;
|
|
|
|
size_t size;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = bus_kernel_open_bus_fd(bus_name, &path);
|
|
|
|
if (fd < 0)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
size = ALIGN8(offsetof(struct kdbus_cmd_make, items));
|
|
|
|
size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(ep_name) + 1);
|
|
|
|
|
2014-09-22 12:49:47 +02:00
|
|
|
make = alloca0_align(size, 8);
|
2014-08-18 19:58:42 +02:00
|
|
|
make->size = size;
|
|
|
|
make->flags = KDBUS_MAKE_ACCESS_WORLD;
|
|
|
|
|
|
|
|
n = make->items;
|
|
|
|
|
|
|
|
n->type = KDBUS_ITEM_MAKE_NAME;
|
|
|
|
n->size = offsetof(struct kdbus_item, str) + strlen(ep_name) + 1;
|
|
|
|
strcpy(n->str, ep_name);
|
|
|
|
|
2014-10-08 15:32:41 +02:00
|
|
|
if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
|
2014-08-18 19:58:42 +02:00
|
|
|
safe_close(fd);
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ep_path) {
|
2014-10-02 20:37:36 +02:00
|
|
|
char *p;
|
|
|
|
|
|
|
|
p = strjoin(dirname(path), "/", ep_name, NULL);
|
|
|
|
if (!p) {
|
2014-09-17 23:10:21 +02:00
|
|
|
safe_close(fd);
|
2014-08-18 19:58:42 +02:00
|
|
|
return -ENOMEM;
|
2014-09-17 23:10:21 +02:00
|
|
|
}
|
2014-10-02 20:37:36 +02:00
|
|
|
|
|
|
|
*ep_path = p;
|
2014-08-18 19:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) {
|
|
|
|
|
|
|
|
struct kdbus_cmd_update *update;
|
|
|
|
struct kdbus_item *n;
|
|
|
|
BusEndpointPolicy *po;
|
|
|
|
Iterator i;
|
|
|
|
size_t size;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
size = ALIGN8(offsetof(struct kdbus_cmd_update, items));
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(po, ep->policy_hash, i) {
|
|
|
|
size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1);
|
|
|
|
size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
|
|
|
|
}
|
|
|
|
|
2014-09-22 12:49:47 +02:00
|
|
|
update = alloca0_align(size, 8);
|
2014-08-18 19:58:42 +02:00
|
|
|
update->size = size;
|
|
|
|
|
|
|
|
n = update->items;
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(po, ep->policy_hash, i) {
|
|
|
|
n->type = KDBUS_ITEM_NAME;
|
|
|
|
n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1;
|
|
|
|
strcpy(n->str, po->name);
|
|
|
|
n = KDBUS_ITEM_NEXT(n);
|
|
|
|
|
|
|
|
n->type = KDBUS_ITEM_POLICY_ACCESS;
|
|
|
|
n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
|
|
|
|
|
|
|
|
n->policy_access.type = KDBUS_POLICY_ACCESS_USER;
|
|
|
|
n->policy_access.access = bus_kernel_translate_access(po->access);
|
|
|
|
n->policy_access.id = uid;
|
|
|
|
|
|
|
|
n = KDBUS_ITEM_NEXT(n);
|
|
|
|
}
|
|
|
|
|
2014-10-08 15:32:41 +02:00
|
|
|
r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update);
|
2014-08-18 19:58:42 +02:00
|
|
|
if (r < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
int bus_kernel_make_starter(
|
|
|
|
int fd,
|
|
|
|
const char *name,
|
|
|
|
bool activating,
|
|
|
|
bool accept_fd,
|
|
|
|
BusNamePolicy *policy,
|
2014-08-18 22:07:47 +02:00
|
|
|
BusPolicyAccess world_policy) {
|
2014-06-05 12:24:03 +02:00
|
|
|
|
2013-12-02 23:30:19 +01:00
|
|
|
struct kdbus_cmd_hello *hello;
|
|
|
|
struct kdbus_item *n;
|
2014-03-07 17:29:01 +01:00
|
|
|
size_t policy_cnt = 0;
|
|
|
|
BusNamePolicy *po;
|
|
|
|
size_t size;
|
2014-06-05 12:24:03 +02:00
|
|
|
int r;
|
2013-12-02 23:30:19 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
assert(fd >= 0);
|
2013-12-02 23:30:19 +01:00
|
|
|
assert(name);
|
|
|
|
|
2014-03-07 17:29:01 +01:00
|
|
|
LIST_FOREACH(policy, po, policy)
|
|
|
|
policy_cnt++;
|
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
if (world_policy >= 0)
|
|
|
|
policy_cnt++;
|
|
|
|
|
2014-11-26 02:50:49 +01:00
|
|
|
size = offsetof(struct kdbus_cmd_hello, items) +
|
2014-03-07 17:29:01 +01:00
|
|
|
ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) +
|
|
|
|
policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
|
|
|
|
|
2014-09-22 12:49:47 +02:00
|
|
|
hello = alloca0_align(size, 8);
|
2013-12-02 23:30:19 +01:00
|
|
|
|
|
|
|
n = hello->items;
|
|
|
|
strcpy(n->str, name);
|
|
|
|
n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
|
2013-12-17 12:25:20 +01:00
|
|
|
n->type = KDBUS_ITEM_NAME;
|
2014-03-07 17:29:01 +01:00
|
|
|
n = KDBUS_ITEM_NEXT(n);
|
|
|
|
|
|
|
|
LIST_FOREACH(policy, po, policy) {
|
|
|
|
n->type = KDBUS_ITEM_POLICY_ACCESS;
|
|
|
|
n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
|
2014-06-05 12:24:03 +02:00
|
|
|
|
|
|
|
r = bus_kernel_translate_policy(po, n);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2014-03-07 17:29:01 +01:00
|
|
|
n = KDBUS_ITEM_NEXT(n);
|
|
|
|
}
|
2013-12-02 23:30:19 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
if (world_policy >= 0) {
|
|
|
|
n->type = KDBUS_ITEM_POLICY_ACCESS;
|
|
|
|
n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
|
|
|
|
n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
|
|
|
|
n->policy_access.access = bus_kernel_translate_access(world_policy);
|
|
|
|
}
|
|
|
|
|
2014-03-07 17:29:01 +01:00
|
|
|
hello->size = size;
|
2014-10-21 19:19:44 +02:00
|
|
|
hello->flags =
|
2014-03-17 11:41:21 +01:00
|
|
|
(activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
|
|
|
|
(accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
|
2013-12-02 23:30:19 +01:00
|
|
|
hello->pool_size = KDBUS_POOL_SIZE;
|
2014-11-05 18:54:50 +01:00
|
|
|
hello->attach_flags_send = _KDBUS_ATTACH_ANY;
|
2014-11-26 02:54:41 +01:00
|
|
|
hello->attach_flags_recv = _KDBUS_ATTACH_ANY;
|
2013-12-02 23:30:19 +01:00
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0)
|
2013-12-02 23:30:19 +01:00
|
|
|
return -errno;
|
|
|
|
|
2014-10-18 20:57:53 +02:00
|
|
|
/* The higher 32bit of the bus_flags fields are considered
|
2013-12-02 23:30:19 +01:00
|
|
|
* 'incompatible flags'. Refuse them all for now. */
|
2014-10-18 20:57:53 +02:00
|
|
|
if (hello->bus_flags > 0xFFFFFFFFULL)
|
2013-12-02 23:30:19 +01:00
|
|
|
return -ENOTSUP;
|
|
|
|
|
2014-06-05 12:24:03 +02:00
|
|
|
if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash))
|
2013-12-02 23:30:19 +01:00
|
|
|
return -ENOTSUP;
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2013-12-20 23:25:43 +01:00
|
|
|
int bus_kernel_try_close(sd_bus *bus) {
|
|
|
|
assert(bus);
|
|
|
|
assert(bus->is_kernel);
|
|
|
|
|
|
|
|
if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE) < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-01-22 23:36:06 +01:00
|
|
|
|
|
|
|
int bus_kernel_drop_one(int fd) {
|
|
|
|
struct kdbus_cmd_recv recv = {
|
|
|
|
.flags = KDBUS_RECV_DROP
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(fd >= 0);
|
|
|
|
|
|
|
|
if (ioctl(fd, KDBUS_CMD_MSG_RECV, &recv) < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-11-26 02:20:28 +01:00
|
|
|
|
|
|
|
int bus_kernel_realize_attach_flags(sd_bus *bus) {
|
|
|
|
struct kdbus_cmd_update *update;
|
|
|
|
struct kdbus_item *n;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(bus->is_kernel);
|
|
|
|
|
2014-11-26 02:50:49 +01:00
|
|
|
update = alloca0_align(offsetof(struct kdbus_cmd_update, items) +
|
|
|
|
ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
|
|
|
|
8);
|
2014-11-26 02:20:28 +01:00
|
|
|
|
|
|
|
n = update->items;
|
|
|
|
n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
|
|
|
|
n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
|
|
|
|
n->data64[0] = bus->attach_flags;
|
|
|
|
|
2014-11-26 02:50:49 +01:00
|
|
|
update->size =
|
|
|
|
offsetof(struct kdbus_cmd_update, items) +
|
|
|
|
ALIGN8(n->size);
|
2014-11-26 02:20:28 +01:00
|
|
|
|
|
|
|
if (ioctl(bus->input_fd, KDBUS_CMD_CONN_UPDATE, update) < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|