chiark / gitweb /
sd-bus: the attach_mask kernel module parameter is 64bit now, hence initialize it...
[elogind.git] / src / libsystemd / sd-bus / bus-kernel.c
index ef157d69f2eb6bea061450ee8ee0b1cc7591139a..a7d18e337b874244b97cccfc9348ffa10c68f74d 100644 (file)
@@ -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;
@@ -660,9 +670,23 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                         }
 
                         if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
-                                r = strv_extend(&m->creds.well_known_names, d->name.name);
-                                if (r < 0)
+                                char **wkn;
+                                size_t n;
+
+                                /* We just extend the array here, but
+                                 * do not allocate the strings inside
+                                 * of it, instead we just point to our
+                                 * buffer directly. */
+                                n = strv_length(m->creds.well_known_names);
+                                wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
+                                if (!wkn) {
+                                        r = -ENOMEM;
                                         goto fail;
+                                }
+
+                                wkn[n] = d->name.name;
+                                wkn[n+1] = NULL;
+                                m->creds.well_known_names = wkn;
 
                                 m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
                         }
@@ -694,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;
@@ -724,7 +756,7 @@ 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";
+                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;
@@ -1059,7 +1091,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";
+        bus_message_set_sender_driver(bus, m);
 
         r = bus_seal_synthetic_message(bus, m);
         if (r < 0)
@@ -1128,7 +1160,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";
+        bus_message_set_sender_driver(bus, m);
 
         r = bus_seal_synthetic_message(bus, m);
         if (r < 0)
@@ -1765,3 +1797,40 @@ 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) {
+                log_warning_errno(-r, "Failed to read kernel command line: %m");
+                return r;
+        }
+
+        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) {
+                log_warning_errno(-r, "Failed to write kdbus attach mask: %m");
+                return r;
+        }
+
+        return 0;
+}