summaryrefslogtreecommitdiff
path: root/src/libsystemd
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-06-05 12:24:03 +0200
committerLennart Poettering <lennart@poettering.net>2014-06-05 13:09:46 +0200
commita4152e3fe28b53b8919cc404dd7eca7ead1bf9bd (patch)
tree6d19cc912c50c123de8d4d599f802f83aea73b4a /src/libsystemd
parent5331194c120520579eede9dba4bd9c3329629601 (diff)
downloadsystemd-a4152e3fe28b53b8919cc404dd7eca7ead1bf9bd.tar.gz
kdbus: when uploading bus name policy, resolve users/groups out-of-process
It's not safe invoking NSS from PID 1, hence fork off worker processes that upload the policy into the kernel for busnames.
Diffstat (limited to 'src/libsystemd')
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c136
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.h4
2 files changed, 89 insertions, 51 deletions
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index 8bab6ad1be..f49fb5b394 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1305,7 +1305,7 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) {
make->size += ALIGN8(n->size);
n = KDBUS_ITEM_NEXT(n);
- sprintf(n->str, UID_FMT"-%s", 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);
@@ -1339,72 +1339,107 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) {
return fd;
}
-static void bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
+static int bus_kernel_translate_access(BusNamePolicyAccess access) {
+ assert(access >= 0);
+ assert(access < _BUSNAME_POLICY_ACCESS_MAX);
+
+ switch (access) {
+
+ 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 access");
+ }
+}
+
+static int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
+ int r;
assert(policy);
assert(item);
switch (policy->type) {
- case BUSNAME_POLICY_TYPE_USER:
+ 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 = policy->uid;
+ item->policy_access.id = 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_GROUP: {
+ const char *group = policy->name;
+ gid_t gid;
- case BUSNAME_POLICY_TYPE_WORLD:
- item->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
+ 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 type");
}
- switch (policy->access) {
+ item->policy_access.access = bus_kernel_translate_access(policy->access);
- case BUSNAME_POLICY_ACCESS_SEE:
- item->policy_access.access = KDBUS_POLICY_SEE;
- break;
+ return 0;
+}
- case BUSNAME_POLICY_ACCESS_TALK:
- item->policy_access.access = KDBUS_POLICY_TALK;
- break;
+int bus_kernel_open_bus_fd(const char *bus) {
+ char *p;
+ int fd;
- case BUSNAME_POLICY_ACCESS_OWN:
- item->policy_access.access = KDBUS_POLICY_OWN;
- break;
+ p = alloca(strlen("/dev/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1);
+ sprintf(p, "/dev/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
- default:
- assert_not_reached("Unknown policy access");
- }
+ fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ return fd;
}
-int bus_kernel_create_starter(const char *bus, const char *name, bool activating, bool accept_fd, BusNamePolicy *policy) {
+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;
- char *p;
- int fd;
+ int r;
- assert(bus);
+ assert(fd >= 0);
assert(name);
- p = alloca(strlen("/dev/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1);
- sprintf(p, "/dev/kdbus/"UID_FMT"-%s/bus", getuid(), bus);
-
- fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
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));
@@ -1420,10 +1455,21 @@ int bus_kernel_create_starter(const char *bus, const char *name, bool activating
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 =
(activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
@@ -1431,23 +1477,17 @@ int bus_kernel_create_starter(const char *bus, const char *name, bool activating
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;
}
@@ -1505,17 +1545,13 @@ int bus_kernel_create_domain(const char *name, char **s) {
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/"UID_FMT"-%s/bus", getuid(), bus);
-
- fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ fd = bus_kernel_open_bus_fd(bus);
if (fd < 0)
- return -errno;
+ return fd;
hello = alloca0(sizeof(struct kdbus_cmd_hello));
hello->size = sizeof(struct kdbus_cmd_hello);
diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h
index 4ef26fce64..2fe2495a6c 100644
--- a/src/libsystemd/sd-bus/bus-kernel.h
+++ b/src/libsystemd/sd-bus/bus-kernel.h
@@ -65,9 +65,11 @@ int bus_kernel_take_fd(sd_bus *b);
int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call);
int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority);
+int bus_kernel_open_bus_fd(const char *bus);
+int bus_kernel_make_starter(int fd, const char *name, bool activating, bool accept_fd, BusNamePolicy *policy, BusNamePolicyAccess world_policy);
+
int bus_kernel_create_bus(const char *name, bool world, char **s);
int bus_kernel_create_domain(const char *name, char **s);
-int bus_kernel_create_starter(const char *bus, const char *name, bool activating, bool accept_fd, BusNamePolicy *policy);
int bus_kernel_create_monitor(const char *bus);
int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated);