diff options
author | Lennart Poettering <lennart@poettering.net> | 2014-11-26 02:20:28 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-11-26 02:20:55 +0100 |
commit | b5dae4c7f77f7c87b91e0afb60a31c690dda4a1f (patch) | |
tree | 0bc1ce84ed97884bae8f4c332074c532c28f6470 | |
parent | f3c0588651927ebac691130aa861b878fa22e527 (diff) |
sd-bus: add suppot for renegotiating message credential attach flags
-rw-r--r-- | man/sd_bus_negotiate_fds.xml | 45 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-control.c | 6 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-kernel.c | 37 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-kernel.h | 6 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/busctl.c | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/sd-bus.c | 38 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/test-bus-kernel.c | 9 | ||||
-rw-r--r-- | src/systemd/sd-bus.h | 2 |
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); |