X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-kernel.c;h=e229baf2664f9d99e4b9e8cf3528d5e47850d0e8;hb=03e334a1c7dc8c20c38902aa039440763acc9b17;hp=f85b4d5676ff252c0642e0dbd2082dc23d196727;hpb=607553f9306286fdccf0b356bc3d1087adfe21c4;p=elogind.git diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index f85b4d567..e229baf26 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "util.h" #include "strv.h" @@ -35,6 +36,7 @@ #include "bus-kernel.h" #include "bus-bloom.h" #include "bus-util.h" +#include "bus-label.h" #include "cgroup-util.h" #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t)) @@ -100,20 +102,21 @@ static void append_destination(struct kdbus_item **d, const char *s, size_t leng *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } -static void* append_bloom(struct kdbus_item **d, size_t length) { - void *r; +static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) { + struct kdbus_item *i; assert(d); - *d = ALIGN8_PTR(*d); + i = ALIGN8_PTR(*d); - (*d)->size = offsetof(struct kdbus_item, data) + length; - (*d)->type = KDBUS_ITEM_BLOOM; - r = (*d)->data; + i->size = offsetof(struct kdbus_item, bloom_filter) + + offsetof(struct kdbus_bloom_filter, data) + + length; + i->type = KDBUS_ITEM_BLOOM_FILTER; - *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); + *d = (struct kdbus_item *) ((uint8_t*) i + i->size); - return r; + return &i->bloom_filter; } static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) { @@ -129,25 +132,28 @@ static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) { *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } -static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) { +static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) { + void *data; unsigned i; int r; assert(m); assert(bloom); - memset(bloom, 0, BLOOM_SIZE); + data = bloom->data; + memzero(data, m->bus->bloom_size); + bloom->generation = 0; - bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type)); + bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type)); if (m->interface) - bloom_add_pair(bloom, "interface", m->interface); + bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface); if (m->member) - bloom_add_pair(bloom, "member", m->member); + bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member); if (m->path) { - bloom_add_pair(bloom, "path", m->path); - bloom_add_pair(bloom, "path-slash-prefix", m->path); - bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/'); + 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, '/'); } r = sd_bus_message_rewind(m, true); @@ -182,12 +188,12 @@ static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) { } *e = 0; - bloom_add_pair(bloom, buf, t); + bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t); strcpy(e, "-dot-prefix"); - bloom_add_prefixes(bloom, buf, t, '.'); + bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '.'); strcpy(e, "-slash-prefix"); - bloom_add_prefixes(bloom, buf, t, '/'); + bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '/'); } return 0; @@ -206,6 +212,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { assert(m); assert(m->sealed); + /* We put this together only once, if this message is reused + * we reuse the earlier-built version */ if (m->kdbus) return 0; @@ -228,7 +236,9 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)); /* Add space for bloom filter */ - sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE); + sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) + + offsetof(struct kdbus_bloom_filter, data) + + m->bus->bloom_size); /* Add in well-known destination header */ if (well_known) { @@ -247,7 +257,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { } m->free_kdbus = true; - memset(m->kdbus, 0, sz); + memzero(m->kdbus, sz); m->kdbus->flags = ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) | @@ -256,7 +266,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { well_known ? 0 : m->destination ? unique : KDBUS_DST_ID_BROADCAST; m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS; - m->kdbus->cookie = m->header->serial; + m->kdbus->cookie = (uint64_t) m->header->serial; + m->kdbus->priority = m->priority; if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) m->kdbus->cookie_reply = m->reply_cookie; @@ -289,8 +300,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { continue; } - /* Otherwise let's send a vector to the actual data, - * for that we need to map it first. */ + /* Otherwise, let's send a vector to the actual data. + * For that, we need to map it first. */ r = bus_body_part_map(part); if (r < 0) goto fail; @@ -299,10 +310,10 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { } if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) { - void *p; + struct kdbus_bloom_filter *bloom; - p = append_bloom(&d, BLOOM_SIZE); - r = bus_message_setup_bloom(m, p); + bloom = append_bloom(&d, m->bus->bloom_size); + r = bus_message_setup_bloom(m, bloom); if (r < 0) goto fail; } @@ -497,8 +508,13 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { break; case KDBUS_ITEM_TIMESTAMP: - m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC; - m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC; + + 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; + } + break; case KDBUS_ITEM_PID_COMM: @@ -564,6 +580,11 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { goto fail; break; + case KDBUS_ITEM_CONN_NAME: + m->creds.conn_name = d->str; + m->creds.mask |= SD_BUS_CREDS_CONNECTION_NAME & bus->creds_mask; + break; + case KDBUS_ITEM_FDS: case KDBUS_ITEM_SECLABEL: break; @@ -625,7 +646,9 @@ fail: int bus_kernel_take_fd(sd_bus *b) { struct kdbus_cmd_hello *hello; struct kdbus_item *item; - size_t l = 0, sz; + _cleanup_free_ char *g = NULL; + const char *name; + size_t l = 0, m = 0, sz; int r; assert(b); @@ -635,10 +658,52 @@ int bus_kernel_take_fd(sd_bus *b) { b->use_memfd = 1; - sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)); + if (b->connection_name) { + g = bus_label_escape(b->connection_name); + 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; + + e = bus_label_escape(pr); + if (!e) + return -ENOMEM; + + g = strappend(b->is_system ? "sd-system-" : + b->is_user ? "sd-user-" : "sd-", + e); + if (!g) + return -ENOMEM; + + name = g; + } + + b->connection_name = bus_label_unescape(name); + if (!b->connection_name) + return -ENOMEM; + } + + m = strlen(name); + + sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) + + ALIGN8(offsetof(struct kdbus_item, str) + m + 1); if (b->fake_creds_valid) - sz += ALIGN8(offsetof(struct kdbus_item, creds)) + sizeof(struct kdbus_creds); + sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds)); if (b->fake_label) { l = strlen(b->fake_label); @@ -653,6 +718,11 @@ int bus_kernel_take_fd(sd_bus *b) { item = hello->items; + item->size = offsetof(struct kdbus_item, str) + m + 1; + item->type = KDBUS_ITEM_CONN_NAME; + memcpy(item->str, name, m + 1); + item = KDBUS_ITEM_NEXT(item); + if (b->fake_creds_valid) { item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds); item->type = KDBUS_ITEM_CREDS; @@ -663,6 +733,7 @@ int bus_kernel_take_fd(sd_bus *b) { if (b->fake_label) { item->size = offsetof(struct kdbus_item, str) + l + 1; + item->type = KDBUS_ITEM_SECLABEL; memcpy(item->str, b->fake_label, l+1); } @@ -684,9 +755,12 @@ int bus_kernel_take_fd(sd_bus *b) { hello->conn_flags > 0xFFFFFFFFULL) return -ENOTSUP; - if (hello->bloom_size != BLOOM_SIZE) + if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash)) return -ENOTSUP; + b->bloom_size = (size_t) hello->bloom.size; + b->bloom_n_hash = (unsigned) hello->bloom.n_hash; + if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) return -ENOMEM; @@ -722,7 +796,26 @@ int bus_kernel_connect(sd_bus *b) { return bus_kernel_take_fd(b); } -int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) { +static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) { + uint64_t off; + struct kdbus_item *d; + + assert(bus); + assert(k); + + off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer; + ioctl(bus->input_fd, KDBUS_CMD_FREE, &off); + + 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) + safe_close(d->memfd.fd); + } +} + +int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) { int r; assert(bus); @@ -738,6 +831,14 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) { if (r < 0) return r; + /* 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; + 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; @@ -785,29 +886,31 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) { bus->rqueue[bus->rqueue_size++] = reply; - return 0; - } - - return 1; -} - -static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) { - uint64_t off; - struct kdbus_item *d; + } else if (hint_sync_call) { + struct kdbus_msg *k; - assert(bus); - assert(k); + k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + m->kdbus->offset_reply); + assert(k); - off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer; - ioctl(bus->input_fd, KDBUS_CMD_FREE, &off); + if (k->payload_type == KDBUS_PAYLOAD_DBUS) { - KDBUS_ITEM_FOREACH(d, k, items) { + r = bus_kernel_make_message(bus, k); + if (r < 0) { + close_kdbus_msg(bus, k); - 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) - close_nointr_nofail(d->memfd.fd); + /* 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); + } } + + return 1; } static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) { @@ -818,10 +921,10 @@ static int push_name_owner_changed(sd_bus *bus, const char *name, const char *ol r = sd_bus_message_new_signal( bus, + &m, "/org/freedesktop/DBus", "org.freedesktop.DBus", - "NameOwnerChanged", - &m); + "NameOwnerChanged"); if (r < 0) return r; @@ -946,7 +1049,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found); } -int bus_kernel_read_message(sd_bus *bus) { +int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { struct kdbus_cmd_recv recv = {}; struct kdbus_msg *k; int r; @@ -957,6 +1060,11 @@ int bus_kernel_read_message(sd_bus *bus) { if (r < 0) return r; + if (hint_priority) { + recv.flags |= KDBUS_RECV_USE_PRIORITY; + recv.priority = priority; + } + r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &recv); if (r < 0) { if (errno == EAGAIN) @@ -964,8 +1072,8 @@ int bus_kernel_read_message(sd_bus *bus) { return -errno; } - k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset); + k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset); if (k->payload_type == KDBUS_PAYLOAD_DBUS) { r = bus_kernel_make_message(bus, k); @@ -977,8 +1085,10 @@ int bus_kernel_read_message(sd_bus *bus) { } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) r = bus_kernel_translate_message(bus, k); - else + else { + log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type); r = 0; + } if (r <= 0) close_kdbus_msg(bus, k); @@ -1000,21 +1110,40 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0); if (bus->n_memfd_cache <= 0) { - struct kdbus_cmd_memfd_make cmd = { - .size = sizeof(struct kdbus_cmd_memfd_make), - }; + _cleanup_free_ char *g = NULL; + struct kdbus_cmd_memfd_make *cmd; + struct kdbus_item *item; + size_t l, sz; int r; assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0); - r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &cmd); + assert(bus->connection_name); + + g = bus_label_escape(bus->connection_name); + if (!g) + return -ENOMEM; + + l = strlen(g); + sz = ALIGN8(offsetof(struct kdbus_cmd_memfd_make, items)) + + ALIGN8(offsetof(struct kdbus_item, str)) + + l + 1; + cmd = alloca0(sz); + cmd->size = sz; + + item = cmd->items; + item->size = ALIGN8(offsetof(struct kdbus_item, str)) + l + 1; + item->type = KDBUS_ITEM_MEMFD_NAME; + memcpy(item->str, g, l + 1); + + r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, cmd); if (r < 0) return -errno; *address = NULL; *mapped = 0; *allocated = 0; - return cmd.fd; + return cmd->fd; } c = &bus->memfd_cache[--bus->n_memfd_cache]; @@ -1036,7 +1165,7 @@ static void close_and_munmap(int fd, void *address, size_t size) { if (size > 0) assert_se(munmap(address, PAGE_ALIGN(size)) >= 0); - close_nointr_nofail(fd); + safe_close(fd); } void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) { @@ -1136,6 +1265,9 @@ int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) { if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) m |= KDBUS_ATTACH_NAMES; + if (mask & SD_BUS_CREDS_CONNECTION_NAME) + m |= KDBUS_ATTACH_CONN_NAME; + *kdbus_mask = m; return 0; } @@ -1160,10 +1292,16 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { make->size = offsetof(struct kdbus_cmd_make, items); n = make->items; - n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t); - n->type = KDBUS_ITEM_BLOOM_SIZE; - n->data64[0] = BLOOM_SIZE; - assert_cc(BLOOM_SIZE % 8 == 0); + n->size = offsetof(struct kdbus_item, bloom_parameter) + + sizeof(struct kdbus_bloom_parameter); + n->type = KDBUS_ITEM_BLOOM_PARAMETER; + + 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); + make->size += ALIGN8(n->size); n = KDBUS_ITEM_NEXT(n); @@ -1172,17 +1310,17 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { n->type = KDBUS_ITEM_MAKE_NAME; make->size += ALIGN8(n->size); - make->flags = KDBUS_MAKE_POLICY_OPEN | (world ? KDBUS_MAKE_ACCESS_WORLD : 0); + make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0; if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) { - close_nointr_nofail(fd); + safe_close(fd); return -errno; } /* The higher 32bit of the flags field are considered * 'incompatible flags'. Refuse them all for now. */ if (make->flags > 0xFFFFFFFFULL) { - close_nointr_nofail(fd); + safe_close(fd); return -ENOTSUP; } @@ -1191,7 +1329,7 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { p = strjoin("/dev/kdbus/", n->str, "/bus", NULL); if (!p) { - close_nointr_nofail(fd); + safe_close(fd); return -ENOMEM; } @@ -1201,37 +1339,92 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { return fd; } -int bus_kernel_create_starter(const char *bus, const char *name) { +static void bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) +{ + switch (policy->type) { + case BUSNAME_POLICY_TYPE_USER: + item->policy_access.type = KDBUS_POLICY_ACCESS_USER; + item->policy_access.id = policy->uid; + break; + + case BUSNAME_POLICY_TYPE_GROUP: + item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP; + item->policy_access.id = policy->gid; + break; + + case BUSNAME_POLICY_TYPE_WORLD: + item->policy_access.type = KDBUS_POLICY_ACCESS_WORLD; + break; + + default: + assert_not_reached("Unknown policy type"); + } + + switch (policy->access) { + case BUSNAME_POLICY_ACCESS_SEE: + item->policy_access.access = KDBUS_POLICY_SEE; + break; + + case BUSNAME_POLICY_ACCESS_TALK: + item->policy_access.access = KDBUS_POLICY_TALK; + break; + + case BUSNAME_POLICY_ACCESS_OWN: + item->policy_access.access = KDBUS_POLICY_OWN; + break; + + default: + assert_not_reached("Unknown policy access"); + } +} + +int bus_kernel_create_starter(const char *bus, const char *name, BusNamePolicy *policy) { struct kdbus_cmd_hello *hello; struct kdbus_item *n; + size_t policy_cnt = 0; + BusNamePolicy *po; + size_t size; char *p; int fd; assert(bus); assert(name); - p = alloca(sizeof("/dev/kdbus/") - 1 + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + sizeof("/bus")); + p = alloca(strlen("/dev/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1); sprintf(p, "/dev/kdbus/%lu-%s/bus", (unsigned long) getuid(), bus); fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; - hello = alloca0(ALIGN8(offsetof(struct kdbus_cmd_hello, items) + - offsetof(struct kdbus_item, str) + - strlen(name) + 1)); + LIST_FOREACH(policy, po, policy) + policy_cnt++; + + size = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) + + ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) + + policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); + + hello = alloca0(size); n = hello->items; strcpy(n->str, name); n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1; n->type = KDBUS_ITEM_NAME; + 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); + bus_kernel_translate_policy(po, n); + n = KDBUS_ITEM_NEXT(n); + } - hello->size = ALIGN8(offsetof(struct kdbus_cmd_hello, items) + n->size); + hello->size = size; hello->conn_flags = KDBUS_HELLO_ACTIVATOR; hello->pool_size = KDBUS_POOL_SIZE; if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) { - close_nointr_nofail(fd); + safe_close(fd); return -errno; } @@ -1239,19 +1432,19 @@ int bus_kernel_create_starter(const char *bus, const char *name) { * 'incompatible flags'. Refuse them all for now. */ if (hello->bus_flags > 0xFFFFFFFFULL || hello->conn_flags > 0xFFFFFFFFULL) { - close_nointr_nofail(fd); + safe_close(fd); return -ENOTSUP; } - if (hello->bloom_size != BLOOM_SIZE) { - close_nointr_nofail(fd); + if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash)) { + safe_close(fd); return -ENOTSUP; } return fd; } -int bus_kernel_create_namespace(const char *name, char **s) { +int bus_kernel_create_domain(const char *name, char **s) { struct kdbus_cmd_make *make; struct kdbus_item *n; int fd; @@ -1273,26 +1466,26 @@ int bus_kernel_create_namespace(const char *name, char **s) { n->type = KDBUS_ITEM_MAKE_NAME; make->size = ALIGN8(offsetof(struct kdbus_cmd_make, items) + n->size); - make->flags = KDBUS_MAKE_POLICY_OPEN | KDBUS_MAKE_ACCESS_WORLD; + make->flags = KDBUS_MAKE_ACCESS_WORLD; - if (ioctl(fd, KDBUS_CMD_NS_MAKE, make) < 0) { - close_nointr_nofail(fd); + if (ioctl(fd, KDBUS_CMD_DOMAIN_MAKE, make) < 0) { + safe_close(fd); return -errno; } /* The higher 32bit of the flags field are considered * 'incompatible flags'. Refuse them all for now. */ if (make->flags > 0xFFFFFFFFULL) { - close_nointr_nofail(fd); + safe_close(fd); return -ENOTSUP; } if (s) { char *p; - p = strappend("/dev/kdbus/ns/", name); + p = strappend("/dev/kdbus/domain/", name); if (!p) { - close_nointr_nofail(fd); + safe_close(fd); return -ENOMEM; } @@ -1309,7 +1502,7 @@ int bus_kernel_create_monitor(const char *bus) { assert(bus); - p = alloca(sizeof("/dev/kdbus/") - 1 + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + sizeof("/bus")); + p = alloca(strlen("/dev/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1); sprintf(p, "/dev/kdbus/%lu-%s/bus", (unsigned long) getuid(), bus); fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC); @@ -1322,7 +1515,7 @@ int bus_kernel_create_monitor(const char *bus) { hello->pool_size = KDBUS_POOL_SIZE; if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) { - close_nointr_nofail(fd); + safe_close(fd); return -errno; } @@ -1330,7 +1523,7 @@ int bus_kernel_create_monitor(const char *bus) { * 'incompatible flags'. Refuse them all for now. */ if (hello->bus_flags > 0xFFFFFFFFULL || hello->conn_flags > 0xFFFFFFFFULL) { - close_nointr_nofail(fd); + safe_close(fd); return -ENOTSUP; } @@ -1346,3 +1539,16 @@ int bus_kernel_try_close(sd_bus *bus) { return 0; } + +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; +}