if (bus->n_memfd_cache <= 0) {
_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);
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);
+ r = memfd_create(g, MFD_ALLOW_SEALING);
if (r < 0)
return -errno;
*address = NULL;
*mapped = 0;
*allocated = 0;
- return cmd->fd;
+ return r;
}
c = &bus->memfd_cache[--bus->n_memfd_cache];
/* If overly long, let's return a bit to the OS */
if (mapped > max_mapped) {
- assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_mapped) >= 0);
+ assert_se(ftruncate(fd, max_mapped) >= 0);
assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
c->mapped = c->allocated = max_mapped;
} else {
make->size += ALIGN8(n->size);
n = KDBUS_ITEM_NEXT(n);
- sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
+ sprintf(n->str, UID_FMT "-%s", getuid(), name);
n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
n->type = KDBUS_ITEM_MAKE_NAME;
make->size += ALIGN8(n->size);
return fd;
}
-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;
+static int bus_kernel_translate_access(BusNamePolicyAccess access) {
+ assert(access >= 0);
+ assert(access < _BUSNAME_POLICY_ACCESS_MAX);
- case BUSNAME_POLICY_TYPE_GROUP:
- item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
- item->policy_access.id = policy->gid;
- break;
+ switch (access) {
- case BUSNAME_POLICY_TYPE_WORLD:
- item->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
- break;
+ case BUSNAME_POLICY_ACCESS_SEE:
+ return KDBUS_POLICY_SEE;
+
+ case BUSNAME_POLICY_ACCESS_TALK:
+ return KDBUS_POLICY_TALK;
+
+ case BUSNAME_POLICY_ACCESS_OWN:
+ return KDBUS_POLICY_OWN;
default:
- assert_not_reached("Unknown policy type");
+ assert_not_reached("Unknown policy access");
}
+}
- switch (policy->access) {
- case BUSNAME_POLICY_ACCESS_SEE:
- item->policy_access.access = KDBUS_POLICY_SEE;
- break;
+static int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
+ int r;
- case BUSNAME_POLICY_ACCESS_TALK:
- item->policy_access.access = KDBUS_POLICY_TALK;
+ assert(policy);
+ assert(item);
+
+ switch (policy->type) {
+
+ 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;
+
+ item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
+ item->policy_access.id = uid;
break;
+ }
- case BUSNAME_POLICY_ACCESS_OWN:
- item->policy_access.access = KDBUS_POLICY_OWN;
+ case BUSNAME_POLICY_TYPE_GROUP: {
+ const char *group = policy->name;
+ gid_t gid;
+
+ r = get_group_creds(&group, &gid);
+ if (r < 0)
+ return r;
+
+ item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
+ item->policy_access.id = gid;
break;
+ }
default:
- assert_not_reached("Unknown policy access");
+ assert_not_reached("Unknown policy type");
}
+
+ item->policy_access.access = bus_kernel_translate_access(policy->access);
+
+ return 0;
}
-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;
+int bus_kernel_open_bus_fd(const char *bus, char **path) {
char *p;
int fd;
+ size_t len;
- assert(bus);
- assert(name);
+ len = strlen("/dev/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
- 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);
+ if (path) {
+ p = malloc(len);
+ if (!p)
+ return -ENOMEM;
+ *path = p;
+ } else
+ p = alloca(len);
+ sprintf(p, "/dev/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return -errno;
+ return fd;
+}
+
+int bus_kernel_make_starter(
+ int fd,
+ const char *name,
+ bool activating,
+ bool accept_fd,
+ BusNamePolicy *policy,
+ BusNamePolicyAccess world_policy) {
+
+ struct kdbus_cmd_hello *hello;
+ struct kdbus_item *n;
+ size_t policy_cnt = 0;
+ BusNamePolicy *po;
+ size_t size;
+ int r;
+
+ assert(fd >= 0);
+ assert(name);
+
LIST_FOREACH(policy, po, policy)
policy_cnt++;
+ if (world_policy >= 0)
+ 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));
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);
+
+ r = bus_kernel_translate_policy(po, n);
+ if (r < 0)
+ return r;
+
n = KDBUS_ITEM_NEXT(n);
}
+ 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);
+ }
+
hello->size = size;
- hello->conn_flags = KDBUS_HELLO_ACTIVATOR;
+ hello->conn_flags =
+ (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
+ (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
hello->pool_size = KDBUS_POOL_SIZE;
+ hello->attach_flags = _KDBUS_ATTACH_ALL;
- if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
- safe_close(fd);
+ if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0)
return -errno;
- }
/* The higher 32bit of both flags fields are considered
* 'incompatible flags'. Refuse them all for now. */
if (hello->bus_flags > 0xFFFFFFFFULL ||
- hello->conn_flags > 0xFFFFFFFFULL) {
- safe_close(fd);
+ hello->conn_flags > 0xFFFFFFFFULL)
return -ENOTSUP;
- }
- if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash)) {
- safe_close(fd);
+ if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash))
return -ENOTSUP;
- }
return fd;
}
int bus_kernel_create_monitor(const char *bus) {
struct kdbus_cmd_hello *hello;
- char *p;
int fd;
assert(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);
+ fd = bus_kernel_open_bus_fd(bus, NULL);
if (fd < 0)
- return -errno;
+ return fd;
hello = alloca0(sizeof(struct kdbus_cmd_hello));
hello->size = sizeof(struct kdbus_cmd_hello);