summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-11-26 02:20:28 +0100
committerLennart Poettering <lennart@poettering.net>2014-11-26 02:20:55 +0100
commitb5dae4c7f77f7c87b91e0afb60a31c690dda4a1f (patch)
tree0bc1ce84ed97884bae8f4c332074c532c28f6470
parentf3c0588651927ebac691130aa861b878fa22e527 (diff)
sd-bus: add suppot for renegotiating message credential attach flags
-rw-r--r--man/sd_bus_negotiate_fds.xml45
-rw-r--r--src/libsystemd/sd-bus/bus-control.c6
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c37
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.h6
-rw-r--r--src/libsystemd/sd-bus/busctl.c2
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c38
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel.c9
-rw-r--r--src/systemd/sd-bus.h2
8 files changed, 102 insertions, 43 deletions
diff --git a/man/sd_bus_negotiate_fds.xml b/man/sd_bus_negotiate_fds.xml
index 3d7a20b2ff..4fbffdf38c 100644
--- a/man/sd_bus_negotiate_fds.xml
+++ b/man/sd_bus_negotiate_fds.xml
@@ -70,6 +70,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<funcdef>int <function>sd_bus_negotiate_creds</function></funcdef>
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
<paramdef>int <parameter>b</parameter></paramdef>
+ <paramdef>uint64_t <parameter>flags</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -107,25 +108,34 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<citerefentry><refentrytitle>sd_bus_message_get_seqno</refentrytitle><manvolnum>3</manvolnum></citerefentry>
fail with <constant>-ENODATA</constant> on incoming messages. Note
that not all transports support timestamping of messages. On local
- transports, the timestamping is applied by the kernel and cannot be
- manipulated by userspace.</para>
+ transports, the timestamping is applied by the kernel and cannot
+ be manipulated by userspace. By default, message timestamping is
+ not negotiated for all connections.</para>
<para><function>sd_bus_negotiate_creds()</function> controls
whether implicit sender credentials shall be attached
- automatically to all incoming messages. Takes a bus object and a
- bit mask value, which controls which credential parameters are
- attached. If this is not used,
- <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- fails with <constant>-ENODATA</constant> on incoming
- messages. Note that not all transports support attaching sender
- credentials to messages, or do not support all types of sender
- credential parameters. On local transports, the sender credentials
- are attached by the kernel and cannot be manipulated by
- userspace. By default, no sender credentials are attached.</para>
-
- <para>These functions may be called only before the connection has
- been started with
- <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+ automatically to all incoming messages. Takes a bus object, a
+ boolean indicating wether to enable or disable the credential
+ parts encoded in the bit mask value argument. Note that not all
+ transports support attaching sender credentials to messages, or do
+ not support all types of sender credential parameters, or might
+ suppress them under certain circumstances for individual
+ messages. On local transports, the sender credentials are attached
+ by the kernel and cannot be manipulated by userspace. By default,
+ no sender credentials are attached.</para>
+
+ <para>The <function>sd_bus_negotiate_fds()</function> function may
+ be called only before the connection has been started with
+ <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Both
+ <function>sd_bus_negotiate_timestamp()</function> and
+ <function>sd_bus_negotiate_creds()</function> also may be called
+ after a connection has been set up. Note that when operating on a
+ connection that is shared between multiple components of the same
+ program (for example via
+ <citerefentry><refentrytitle>sd_bus_default</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
+ it is highly recommended to only enable additional per message
+ metadata fields, but never disable them again, in order not to
+ disable functionality needed by other components.</para>
</refsect1>
<refsect1>
@@ -169,7 +179,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.busname</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index 0ebaf85d57..9cd5cd5fb6 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -62,7 +62,7 @@ static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags
size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
n = alloca0_align(size, 8);
n->size = size;
- kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
+ n->flags = request_name_flags_to_kdbus(flags);
n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
n->items[0].type = KDBUS_ITEM_NAME;
@@ -643,7 +643,7 @@ static int bus_get_name_creds_kdbus(
}
cmd->size = size;
- kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
+ cmd->flags = attach_flags_to_kdbus(mask);
/* If augmentation is on, and the bus doesn't didn't allow us
* to get the bits we want, then ask for the PID/TID so that we
@@ -927,7 +927,7 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
struct kdbus_info *creator_info;
cmd.size = sizeof(cmd);
- kdbus_translate_attach_flags(mask, (uint64_t*) &cmd.flags);
+ cmd.flags = attach_flags_to_kdbus(mask);
/* If augmentation is on, and the bus doesn't didn't allow us
* to get the bits we want, then ask for the PID/TID so that we
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index e03e4471ce..d0cb7eec1b 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1313,11 +1313,9 @@ void bus_kernel_flush_memfd(sd_bus *b) {
close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
}
-int kdbus_translate_request_name_flags(uint64_t flags, uint64_t *kdbus_flags) {
+uint64_t request_name_flags_to_kdbus(uint64_t flags) {
uint64_t f = 0;
- assert(kdbus_flags);
-
if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
f |= KDBUS_NAME_ALLOW_REPLACEMENT;
@@ -1327,15 +1325,12 @@ int kdbus_translate_request_name_flags(uint64_t flags, uint64_t *kdbus_flags) {
if (flags & SD_BUS_NAME_QUEUE)
f |= KDBUS_NAME_QUEUE;
- *kdbus_flags = f;
- return 0;
+ return f;
}
-int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
+uint64_t attach_flags_to_kdbus(uint64_t mask) {
uint64_t m = 0;
- assert(kdbus_mask);
-
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))
m |= KDBUS_ATTACH_CREDS;
@@ -1376,8 +1371,7 @@ int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
m |= KDBUS_ATTACH_AUXGROUPS;
- *kdbus_mask = m;
- return 0;
+ return m;
}
int bus_kernel_create_bus(const char *name, bool world, char **s) {
@@ -1713,3 +1707,26 @@ int bus_kernel_drop_one(int fd) {
return 0;
}
+
+int bus_kernel_realize_attach_flags(sd_bus *bus) {
+ struct kdbus_cmd_update *update;
+ struct kdbus_item *n;
+
+ assert(bus);
+ assert(bus->is_kernel);
+
+ update = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd_update, items) +
+ offsetof(struct kdbus_item, data64) + sizeof(uint64_t)), 8);
+
+ 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;
+
+ update->size = offsetof(struct kdbus_cmd_update, items) + n->size;
+
+ if (ioctl(bus->input_fd, KDBUS_CMD_CONN_UPDATE, update) < 0)
+ return -errno;
+
+ return 0;
+}
diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h
index c1ee285cd1..8994b35f52 100644
--- a/src/libsystemd/sd-bus/bus-kernel.h
+++ b/src/libsystemd/sd-bus/bus-kernel.h
@@ -81,9 +81,11 @@ void bus_kernel_flush_memfd(sd_bus *bus);
int bus_kernel_parse_unique_name(const char *s, uint64_t *id);
-int kdbus_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags);
-int kdbus_translate_attach_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags);
+uint64_t request_name_flags_to_kdbus(uint64_t sd_bus_flags);
+uint64_t attach_flags_to_kdbus(uint64_t sd_bus_flags);
int bus_kernel_try_close(sd_bus *bus);
int bus_kernel_drop_one(int fd);
+
+int bus_kernel_realize_attach_flags(sd_bus *bus);
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index 50291bafc1..e432db406b 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -1975,7 +1975,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = sd_bus_negotiate_creds(bus, _SD_BUS_CREDS_ALL);
+ r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
if (r < 0) {
log_error("Failed to enable credentials: %s", strerror(-r));
goto finish;
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 5aa8eacebb..6b01c0cab5 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -274,24 +274,50 @@ _public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) {
}
_public_ int sd_bus_negotiate_timestamp(sd_bus *bus, int b) {
+ uint64_t new_flags;
assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
+ assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_TIMESTAMP, b);
+ new_flags = bus->attach_flags;
+ SET_FLAG(new_flags, KDBUS_ATTACH_TIMESTAMP, b);
+
+ if (bus->attach_flags == new_flags)
+ return 0;
+
+ bus->attach_flags = new_flags;
+ if (bus->state != BUS_UNSET && bus->is_kernel)
+ bus_kernel_realize_attach_flags(bus);
+
return 0;
}
-_public_ int sd_bus_negotiate_creds(sd_bus *bus, uint64_t mask) {
+_public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
+ uint64_t new_flags;
+
assert_return(bus, -EINVAL);
assert_return(mask <= _SD_BUS_CREDS_ALL, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
+ assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
+ if (b)
+ bus->creds_mask |= mask;
+ else
+ bus->creds_mask &= ~mask;
+
/* The well knowns we need unconditionally, so that matches can work */
- bus->creds_mask = mask | SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
+ bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
+
+ /* Make sure we don't lose the timestamp flag */
+ new_flags = (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) | attach_flags_to_kdbus(bus->creds_mask);
+ if (bus->attach_flags == new_flags)
+ return 0;
+
+ bus->attach_flags = new_flags;
+ if (bus->state != BUS_UNSET && bus->is_kernel)
+ bus_kernel_realize_attach_flags(bus);
- return kdbus_translate_attach_flags(bus->creds_mask, &bus->attach_flags);
+ return 0;
}
_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c
index 9cc0f01c5b..0e6c2ac402 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel.c
@@ -70,10 +70,10 @@ int main(int argc, char *argv[]) {
assert_se(r >= 0);
assert_se(sd_bus_negotiate_timestamp(a, 1) >= 0);
- assert_se(sd_bus_negotiate_creds(a, _SD_BUS_CREDS_ALL) >= 0);
+ assert_se(sd_bus_negotiate_creds(a, true, _SD_BUS_CREDS_ALL) >= 0);
- assert_se(sd_bus_negotiate_timestamp(b, 1) >= 0);
- assert_se(sd_bus_negotiate_creds(b, _SD_BUS_CREDS_ALL) >= 0);
+ assert_se(sd_bus_negotiate_timestamp(b, 0) >= 0);
+ assert_se(sd_bus_negotiate_creds(b, true, 0) >= 0);
r = sd_bus_start(a);
assert_se(r >= 0);
@@ -81,6 +81,9 @@ int main(int argc, char *argv[]) {
r = sd_bus_start(b);
assert_se(r >= 0);
+ assert_se(sd_bus_negotiate_timestamp(b, 1) >= 0);
+ assert_se(sd_bus_negotiate_creds(b, true, _SD_BUS_CREDS_ALL) >= 0);
+
r = sd_bus_get_unique_name(a, &ua);
assert_se(r >= 0);
printf("unique a: %s\n", ua);
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index cb53a323c5..28c7ee4634 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -127,7 +127,7 @@ int sd_bus_set_description(sd_bus *bus, const char *description);
int sd_bus_set_monitor(sd_bus *bus, int b);
int sd_bus_negotiate_fds(sd_bus *bus, int b);
int sd_bus_negotiate_timestamp(sd_bus *bus, int b);
-int sd_bus_negotiate_creds(sd_bus *bus, uint64_t creds_mask);
+int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t creds_mask);
int sd_bus_start(sd_bus *ret);
int sd_bus_try_close(sd_bus *bus);