+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_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
+
+ assert(fd >= 0);
+ assert(mapped == 0 || address);
+
+ if (!bus || !bus->is_kernel) {
+ close_and_munmap(fd, address, mapped);
+ return;
+ }
+
+ assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
+
+ if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+
+ close_and_munmap(fd, address, mapped);
+ return;
+ }
+
+ c = &bus->memfd_cache[bus->n_memfd_cache++];
+ c->fd = fd;
+ c->address = address;
+
+ /* If overly long, let's return a bit to the OS */
+ 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);
+}
+
+void bus_kernel_flush_memfd(sd_bus *b) {
+ unsigned i;
+
+ 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].mapped);
+}
+
+int kdbus_translate_request_name_flags(uint64_t flags, uint64_t *kdbus_flags) {
+ uint64_t f = 0;
+
+ assert(kdbus_flags);
+
+ if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
+ f |= KDBUS_NAME_ALLOW_REPLACEMENT;
+
+ if (flags & SD_BUS_NAME_REPLACE_EXISTING)
+ f |= KDBUS_NAME_REPLACE_EXISTING;
+
+ if (flags & SD_BUS_NAME_QUEUE)
+ f |= KDBUS_NAME_QUEUE;
+
+ *kdbus_flags = f;
+ return 0;
+}
+
+int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
+ uint64_t m = 0;
+
+ assert(kdbus_mask);
+
+ if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
+ m |= KDBUS_ATTACH_CREDS;
+
+ if (mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))
+ m |= KDBUS_ATTACH_COMM;
+
+ if (mask & SD_BUS_CREDS_EXE)
+ m |= KDBUS_ATTACH_EXE;
+
+ if (mask & SD_BUS_CREDS_CMDLINE)
+ m |= KDBUS_ATTACH_CMDLINE;
+
+ if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
+ m |= KDBUS_ATTACH_CGROUP;
+
+ if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
+ m |= KDBUS_ATTACH_CAPS;
+
+ if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
+ m |= KDBUS_ATTACH_SECLABEL;
+
+ if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
+ m |= KDBUS_ATTACH_AUDIT;
+
+ if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
+ m |= KDBUS_ATTACH_NAMES;
+
+ *kdbus_mask = m;
+ return 0;
+}
+
+int bus_kernel_create_bus(const char *name, char **s) {
+ struct kdbus_cmd_make *make;
+ struct kdbus_item *n;