sd-bus: add suppot for renegotiating message credential attach flags

This commit is contained in:
Lennart Poettering 2014-11-26 02:20:28 +01:00
parent f3c0588651
commit b5dae4c7f7
8 changed files with 102 additions and 43 deletions

View File

@ -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>
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>These functions may be called only before the connection has
been started with
<citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</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>

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);
/* 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;
if (b)
bus->creds_mask |= mask;
else
bus->creds_mask &= ~mask;
return kdbus_translate_attach_flags(bus->creds_mask, &bus->attach_flags);
/* The well knowns we need unconditionally, so that matches can work */
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 0;
}
_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {

View File

@ -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);

View File

@ -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);