chiark / gitweb /
bus: always consider well-known names sender credentials as attached to messages
[elogind.git] / src / libsystemd-bus / bus-kernel.c
index 5be91d46468fbb29d9f62ce379abc452ac54fcd1..5913d42346cca3df02ae70cb568dd6a78e194591 100644 (file)
@@ -515,19 +515,19 @@ static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_
         assert(k);
         assert(d);
 
-        if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
+        if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
                 old_owner[0] = 0;
         else
-                sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id);
+                sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old.id);
 
-        if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
+        if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
 
                 if (isempty(old_owner))
                         return 0;
 
                 new_owner[0] = 0;
         } else
-                sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id);
+                sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new.id);
 
         return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner);
 }
@@ -636,7 +636,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
 
                 case KDBUS_ITEM_PAYLOAD_OFF:
                         if (!h) {
-                                h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
+                                h = (struct bus_header *)((uint8_t *)k + d->vec.offset);
 
                                 if (!bus_header_is_complete(h, d->vec.size))
                                         return -EBADMSG;
@@ -693,6 +693,13 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
         if (r < 0)
                 return r;
 
+        /* The well-known names list is different from the other
+        credentials. If we asked for it, but nothing is there, this
+        means that the list of well-known names is simply empty, not
+        that we lack any data */
+
+        m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
+
         KDBUS_ITEM_FOREACH(d, k, items) {
                 size_t l;
 
@@ -721,11 +728,11 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
 
                                 if (idx >= begin_body) {
                                         if (!part->is_zero)
-                                                part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
+                                                part->data = (uint8_t *)k + d->vec.offset;
                                         part->size = d->vec.size;
                                 } else {
                                         if (!part->is_zero)
-                                                part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
+                                                part->data = (uint8_t *)k + d->vec.offset + (begin_body - idx);
                                         part->size = d->vec.size - (begin_body - idx);
                                 }
 
@@ -818,7 +825,6 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                         r = strv_extend(&m->creds.well_known_names, d->name.name);
                         if (r < 0)
                                 goto fail;
-                        m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask;
                         break;
 
                 case KDBUS_ITEM_FDS:
@@ -836,11 +842,10 @@ 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 = "org.freedesktop.DBus";
+                m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
         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;
-                m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & bus->creds_mask;
         }
 
         if (!m->destination) {
@@ -919,12 +924,13 @@ int bus_kernel_read_message(sd_bus *bus) {
         return r < 0 ? r : 1;
 }
 
-int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
+int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
         struct memfd_cache *c;
         int fd;
 
         assert(address);
-        assert(size);
+        assert(mapped);
+        assert(allocated);
 
         if (!bus || !bus->is_kernel)
                 return -ENOTSUP;
@@ -941,17 +947,19 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
                         return -errno;
 
                 *address = NULL;
-                *size = 0;
+                *mapped = 0;
+                *allocated = 0;
                 return fd;
         }
 
         c = &bus->memfd_cache[--bus->n_memfd_cache];
 
         assert(c->fd >= 0);
-        assert(c->size == 0 || c->address);
+        assert(c->mapped == 0 || c->address);
 
         *address = c->address;
-        *size = c->size;
+        *mapped = c->mapped;
+        *allocated = c->allocated;
         fd = c->fd;
 
         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
@@ -966,15 +974,15 @@ static void close_and_munmap(int fd, void *address, size_t size) {
         close_nointr_nofail(fd);
 }
 
-void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
+void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
         struct memfd_cache *c;
-        uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
+        uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
 
         assert(fd >= 0);
-        assert(size == 0 || address);
+        assert(mapped == 0 || address);
 
         if (!bus || !bus->is_kernel) {
-                close_and_munmap(fd, address, size);
+                close_and_munmap(fd, address, mapped);
                 return;
         }
 
@@ -983,7 +991,7 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
         if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
 
-                close_and_munmap(fd, address, size);
+                close_and_munmap(fd, address, mapped);
                 return;
         }
 
@@ -992,12 +1000,14 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
         c->address = address;
 
         /* If overly long, let's return a bit to the OS */
-        if (size > max_sz) {
-                assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
-                assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
-                c->size = max_sz;
-        } else
-                c->size = size;
+        if (mapped > max_mapped) {
+                assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_mapped) >= 0);
+                assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
+                c->mapped = c->allocated = max_mapped;
+        } else {
+                c->mapped = mapped;
+                c->allocated = allocated;
+        }
 
         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
 }
@@ -1008,7 +1018,7 @@ void bus_kernel_flush_memfd(sd_bus *b) {
         assert(b);
 
         for (i = 0; i < b->n_memfd_cache; i++)
-                close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
+                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) {
@@ -1261,3 +1271,13 @@ int bus_kernel_create_monitor(const char *bus) {
 
         return fd;
 }
+
+int bus_kernel_try_close(sd_bus *bus) {
+        assert(bus);
+        assert(bus->is_kernel);
+
+        if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE) < 0)
+                return -errno;
+
+        return 0;
+}