X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-kernel.c;h=58f011ff86b65a83827b420f382f2afc7e5ab76c;hp=9349c1d79d594c3f31eff74a5762cc6b34de48fe;hb=3acc1dafd14420872f7f13319260eeb5d62c2533;hpb=ac653862e0a99505727dc8861e734d8d6f2b0afd diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 9349c1d79..58f011ff8 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -32,6 +32,8 @@ #include "util.h" #include "strv.h" #include "memfd-util.h" +#include "cgroup-util.h" +#include "fileio.h" #include "bus-internal.h" #include "bus-message.h" @@ -39,7 +41,6 @@ #include "bus-bloom.h" #include "bus-util.h" #include "bus-label.h" -#include "cgroup-util.h" #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t)) @@ -348,6 +349,15 @@ fail: return r; } +static void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) { + assert(bus); + assert(m); + + m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus"; + m->creds.well_known_names_driver = true; + m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask; +} + static void unset_memfds(struct sd_bus_message *m) { struct bus_body_part *part; unsigned i; @@ -708,6 +718,14 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { } } + /* If we requested the list of well-known names to be appended + * and the sender had none no item for it will be + * attached. However, this does *not* mean that we the kernel + * didn't want to provide this information to us. Hence, let's + * explicitly mark this information as available if it was + * requested. */ + m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES; + r = bus_message_parse_fields(m); if (r < 0) goto fail; @@ -737,11 +755,9 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { } /* Override information from the user header with data from the kernel */ - if (k->src_id == KDBUS_SRC_ID_KERNEL) { - m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus"; - m->creds.well_known_names_driver = true; - m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask; - } else { + if (k->src_id == KDBUS_SRC_ID_KERNEL) + bus_message_set_sender_driver(bus, m); + else { snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id); m->sender = m->creds.unique_name = m->sender_buffer; } @@ -938,24 +954,37 @@ int bus_kernel_connect(sd_bus *b) { return bus_kernel_take_fd(b); } +int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) { + struct kdbus_cmd_free cmd = { + .flags = 0, + .offset = offset, + }; + int r; + + assert(bus); + assert(bus->is_kernel); + + r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd); + if (r < 0) + return -errno; + + return 0; +} + static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) { - struct kdbus_cmd_free cmd = {}; struct kdbus_item *d; assert(bus); assert(k); - cmd.offset = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer; - KDBUS_ITEM_FOREACH(d, k, items) { - if (d->type == KDBUS_ITEM_FDS) close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int)); else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD) safe_close(d->memfd.fd); } - (void) ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd); + bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer); } int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) { @@ -1043,7 +1072,7 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call /* Anybody can send us invalid messages, let's just drop them. */ if (r == -EBADMSG || r == -EPROTOTYPE) - log_debug("Ignoring invalid message: %s", strerror(-r)); + log_debug_errno(r, "Ignoring invalid message: %m"); else return r; } @@ -1075,9 +1104,7 @@ static int push_name_owner_changed(sd_bus *bus, const char *name, const char *ol if (r < 0) return r; - m->sender = "org.freedesktop.DBus"; - m->creds.well_known_names_driver = true; - m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask; + bus_message_set_sender_driver(bus, m); r = bus_seal_synthetic_message(bus, m); if (r < 0) @@ -1146,9 +1173,7 @@ static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item * if (r < 0) return r; - m->sender = "org.freedesktop.DBus"; - m->creds.well_known_names_driver = true; - m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask; + bus_message_set_sender_driver(bus, m); r = bus_seal_synthetic_message(bus, m); if (r < 0) @@ -1231,7 +1256,7 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { /* Anybody can send us invalid messages, let's just drop them. */ if (r == -EBADMSG || r == -EPROTOTYPE) { - log_debug("Ignoring invalid message: %s", strerror(-r)); + log_debug_errno(r, "Ignoring invalid message: %m"); r = 0; } @@ -1785,3 +1810,74 @@ int bus_kernel_realize_attach_flags(sd_bus *bus) { return 0; } + +int bus_kernel_fix_attach_mask(void) { + _cleanup_free_ char *mask = NULL; + uint64_t m = (uint64_t) -1; + char buf[2+16+2]; + int r; + + /* By default we don't want any kdbus metadata fields to be + * suppressed, hence we reset the kernel mask for it to + * (uint64_t) -1. This is overridable via a kernel command + * line option, however. */ + + r = get_proc_cmdline_key("systemd.kdbus_attach_flags_mask=", &mask); + if (r < 0) + return log_warning_errno(r, "Failed to read kernel command line: %m"); + + if (mask) { + const char *p = mask; + + if (startswith(p, "0x")) + p += 2; + + if (sscanf(p, "%" PRIx64, &m) != 1) + log_warning("Couldn't parse systemd.kdbus_attach_flags_mask= kernel command line parameter."); + } + + sprintf(buf, "0x%" PRIx64 "\n", m); + r = write_string_file("/sys/module/kdbus/parameters/attach_flags_mask", buf); + if (r < 0) + return log_full_errno( + r == -EROFS ? LOG_DEBUG : LOG_WARNING, r, + "Failed to write kdbus attach mask: %m"); + + return 0; +} + +int bus_kernel_get_bus_name(sd_bus *bus, char **name) { + struct kdbus_cmd_info cmd = { + .size = sizeof(struct kdbus_cmd_info), + }; + struct kdbus_info *info; + struct kdbus_item *item; + char *n = NULL; + int r; + + assert(bus); + assert(name); + assert(bus->is_kernel); + + r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd); + if (r < 0) + return -errno; + + info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset); + + KDBUS_ITEM_FOREACH(item, info, items) + if (item->type == KDBUS_ITEM_MAKE_NAME) { + r = free_and_strdup(&n, item->str); + break; + } + + bus_kernel_cmd_free(bus, cmd.offset); + + if (r < 0) + return r; + if (!n) + return -EIO; + + *name = n; + return 0; +}