Package: release.debian.org Severity: normal Tags: bullseye User: release.debian.org@packages.debian.org Usertags: pu X-Debbugs-CC: pkg-utopia-maintainers@lists.alioth.debian.org jmm@inutil.org Dear release team, In accordance with the Security Team, we want to fix CVE-2022-31213 via a p-u upload rather than a DSA. https://security-tracker.debian.org/tracker/CVE-2022-31213 I have prepared the backports for the CVE fix, a memory leak fix, and an assertion fix that were merged upstream in the latest release. I have tested the new version in a bullseye nspawn container and found no issue. I have already done the upload as dbus-broker was approved for bullseye-p-u already in the past. debdiff attached. -- Kind regards, Luca Boccassi
diff -Nru dbus-broker-26/debian/changelog dbus-broker-26/debian/changelog
--- dbus-broker-26/debian/changelog 2022-06-22 22:27:17.000000000 +0100
+++ dbus-broker-26/debian/changelog 2022-08-04 12:55:19.000000000 +0100
@@ -1,3 +1,11 @@
+dbus-broker (26-1+deb11u2) bullseye; urgency=medium
+
+ * Backport patch to fix assertion failure when disconnecting peer groups
+ * Backport patch to fix memory leak
+ * Backport patches to fix null pointer dereference (CVE-2022-31213)
+
+ -- Luca Boccassi <bluca@debian.org> Thu, 04 Aug 2022 12:55:19 +0100
+
dbus-broker (26-1+deb11u1) bullseye; urgency=medium
* Backport strnspn-fix-buffer-overflow.patch to fix CVE-2022-31212
diff -Nru dbus-broker-26/debian/patches/c-stdaux-add-c_memcpy.patch dbus-broker-26/debian/patches/c-stdaux-add-c_memcpy.patch
--- dbus-broker-26/debian/patches/c-stdaux-add-c_memcpy.patch 1970-01-01 01:00:00.000000000 +0100
+++ dbus-broker-26/debian/patches/c-stdaux-add-c_memcpy.patch 2022-08-04 12:55:19.000000000 +0100
@@ -0,0 +1,64 @@
+Author: David Rheinsberg <david.rheinsberg@gmail.com>
+Origin: backport, https://github.com/c-util/c-stdaux/commit/7a8493bebc595f94ea57fa1cb6a765a66185aa95
+Description: add c_memcpy()
+ Alongside c_memset(), this adds c_memcpy() with the same trick of
+ allowing empty copies.
+--- a/subprojects/c-stdaux/src/c-stdaux.h
++++ b/subprojects/c-stdaux/src/c-stdaux.h
+@@ -488,6 +488,24 @@
+ return p;
+ }
+
++/**
++ * c_memcpy() - copy memory area
++ * @dst: pointer to target area
++ * @src: pointer to source area
++ * @n: length of area to copy
++ *
++ * Copy the memory of size @n from @src to @dst, just as `memcpy(3)` does,
++ * except this function allows either to be NULL if @n is zero. In the latter
++ * case, the operation is a no-op.
++ *
++ * Return: @p is returned.
++ */
++static inline void *c_memcpy(void *dst, const void *src, size_t n) {
++ if (n > 0)
++ memcpy(dst, src, n);
++ return dst;
++}
++
+ /*
+ * Common Destructors
+ *
+--- a/subprojects/c-stdaux/src/test-api.c
++++ b/subprojects/c-stdaux/src/test-api.c
+@@ -188,6 +188,7 @@
+ void *fns[] = {
+ (void *)c_errno,
+ (void *)c_memset,
++ (void *)c_memcpy,
+ (void *)c_free,
+ (void *)c_close,
+ (void *)c_fclose,
+--- a/subprojects/c-stdaux/src/test-basic.c
++++ b/subprojects/c-stdaux/src/test-basic.c
+@@ -332,6 +332,19 @@
+ abort();
+ c_assert(p == NULL);
+ }
++
++ /*
++ * Test c_memcpy() with a simple 8-byte copy.
++ */
++ {
++ uint64_t v1 = (uint64_t)-1, v2 = (uint64_t)0;
++
++ c_assert(v1 == (uint64_t)-1);
++ c_memcpy(&v1, &v2, sizeof(v1));
++ c_assert(v1 == (uint64_t)0);
++
++ c_memcpy(NULL, NULL, 0);
++ }
+ }
+
+ /*
diff -Nru dbus-broker-26/debian/patches/c-stdaux-add-c_memset.patch dbus-broker-26/debian/patches/c-stdaux-add-c_memset.patch
--- dbus-broker-26/debian/patches/c-stdaux-add-c_memset.patch 1970-01-01 01:00:00.000000000 +0100
+++ dbus-broker-26/debian/patches/c-stdaux-add-c_memset.patch 2022-08-04 12:55:19.000000000 +0100
@@ -0,0 +1,85 @@
+Author: David Rheinsberg <david.rheinsberg@gmail.com>
+Origin: backport, https://github.com/c-util/c-stdaux/commit/1257244f886a4799a1ed739aa2c632e9eb033b8d
+Description: add c_memset()
+ The memset(3) function causes UB if its area pointer is NULL, even if
+ the area is 0-bytes in length. This is very unfortunate and requires
+ unnecessary guards in most callers. We really want to be able to call
+ memset(3) with NULL pointers on empty areas to avoid needless branching
+ and complexity.
+ .
+ Provide c_memset() which is exactly like memset(3) for non-NULL areas,
+ but a no-op for empty areas.
+--- a/subprojects/c-stdaux/src/c-stdaux.h
++++ b/subprojects/c-stdaux/src/c-stdaux.h
+@@ -470,6 +470,24 @@
+ return _c_likely_(errno > 0) ? errno : ENOTRECOVERABLE;
+ }
+
++/**
++ * c_memset() - fill memory region with constant byte
++ * @p: pointer to memory region, if non-empty
++ * @c: value to fill with
++ * @n: size of the memory region in bytes
++ *
++ * This function works like `memset(3)` if @n is non-zero. If @n is zero, this
++ * function is a no-op. Therefore, unlike `memset(3)` it is safe to call this
++ * function with NULL as @p if @n is 0.
++ *
++ * Return: @p is returned.
++ */
++static inline void *c_memset(void *p, int c, size_t n) {
++ if (n > 0)
++ memset(p, c, n);
++ return p;
++}
++
+ /*
+ * Common Destructors
+ *
+--- a/subprojects/c-stdaux/src/test-api.c
++++ b/subprojects/c-stdaux/src/test-api.c
+@@ -187,6 +187,7 @@
+ static void test_api_functions(void) {
+ void *fns[] = {
+ (void *)c_errno,
++ (void *)c_memset,
+ (void *)c_free,
+ (void *)c_close,
+ (void *)c_fclose,
+--- a/subprojects/c-stdaux/src/test-basic.c
++++ b/subprojects/c-stdaux/src/test-basic.c
+@@ -304,6 +304,34 @@
+ errno = 0;
+ c_assert(c_errno() != errno);
+ }
++
++ /*
++ * Test c_memset(). Simply verify its most basic behavior, as well as
++ * calling it on empty regions.
++ */
++ {
++ uint64_t v = (uint64_t)-1;
++ size_t n;
++ void *p;
++
++ /* try filling with 0 and 0xff */
++ c_assert(v == (uint64_t)-1);
++ c_memset(&v, 0, sizeof(v));
++ c_assert(v == (uint64_t)0);
++ c_memset(&v, 0xff, sizeof(v));
++ c_assert(v == (uint64_t)-1);
++
++ /*
++ * Try tricking the optimizer into thinking @p cannot be NULL,
++ * as normal `memset(3)` would allow.
++ */
++ p = NULL;
++ n = 0;
++ c_memset(p, 0, n);
++ if (p)
++ abort();
++ c_assert(p == NULL);
++ }
+ }
+
+ /*
diff -Nru dbus-broker-26/debian/patches/global-use-c_mem-over-mem.patch dbus-broker-26/debian/patches/global-use-c_mem-over-mem.patch
--- dbus-broker-26/debian/patches/global-use-c_mem-over-mem.patch 1970-01-01 01:00:00.000000000 +0100
+++ dbus-broker-26/debian/patches/global-use-c_mem-over-mem.patch 2022-08-04 12:55:19.000000000 +0100
@@ -0,0 +1,372 @@
+Author: David Rheinsberg <david.rheinsberg@gmail.com>
+Origin: backport, https://github.com/bus1/dbus-broker/commit/701759a08f5982f515308c269a8e224fc433f4af
+Description: global: use c_mem*() over mem*()
+ Use the new c_mem*() functions rather than mem*() so we protect against
+ NULL pointers in empty areas, which are UB with the classic mem*()
+ functions.
+--- a/src/broker/controller.c
++++ b/src/broker/controller.c
+@@ -56,7 +56,7 @@
+ name->controller = controller;
+ name->controller_node = (CRBNode)C_RBNODE_INIT(name->controller_node);
+ name->activation = (Activation)ACTIVATION_NULL(name->activation);
+- memcpy(name->path, path, n_path + 1);
++ c_memcpy(name->path, path, n_path + 1);
+
+ c_rbtree_add(&controller->name_tree, parent, slot, &name->controller_node);
+ *namep = name;
+@@ -192,7 +192,7 @@
+
+ listener->controller = controller;
+ listener->controller_node = (CRBNode)C_RBNODE_INIT(listener->controller_node);
+- memcpy(listener->path, path, n_path + 1);
++ c_memcpy(listener->path, path, n_path + 1);
+
+ c_rbtree_add(&controller->listener_tree, parent, slot, &listener->controller_node);
+ *listenerp = listener;
+--- a/src/bus/bus.c
++++ b/src/bus/bus.c
+@@ -36,11 +36,11 @@
+ *bus = (Bus)BUS_NULL(*bus);
+ bus->log = log;
+
+- memcpy(bus->machine_id, machine_id, sizeof(bus->machine_id));
++ c_memcpy(bus->machine_id, machine_id, sizeof(bus->machine_id));
+
+ random = (void *)getauxval(AT_RANDOM);
+ c_assert(random);
+- memcpy(bus->guid, random, sizeof(bus->guid));
++ c_memcpy(bus->guid, random, sizeof(bus->guid));
+
+ r = user_registry_init(&bus->users, log, _USER_SLOT_N, maxima);
+ if (r)
+--- a/src/bus/name.c
++++ b/src/bus/name.c
+@@ -214,7 +214,7 @@
+
+ *name = (Name)NAME_INIT(*name);
+ name->registry = registry;
+- memcpy(name->name, name_str, n_name + 1);
++ c_memcpy(name->name, name_str, n_name + 1);
+
+ *namep = name;
+ name = NULL;
+--- a/src/dbus/message.c
++++ b/src/dbus/message.c
+@@ -83,7 +83,7 @@
+ message->vecs[3] = (struct iovec){ message->body, n_body };
+
+ message->n_copied += sizeof(header);
+- memcpy(message->data, &header, sizeof(header));
++ c_memcpy(message->data, &header, sizeof(header));
+
+ *messagep = message;
+ message = NULL;
+@@ -616,11 +616,11 @@
+ message->patch[2] = 's';
+ message->patch[3] = 0;
+ if (message->big_endian)
+- memcpy(message->patch + 4, (uint32_t[1]){ htobe32(n_sender) }, sizeof(uint32_t));
++ c_memcpy(message->patch + 4, (uint32_t[1]){ htobe32(n_sender) }, sizeof(uint32_t));
+ else
+- memcpy(message->patch + 4, (uint32_t[1]){ htole32(n_sender) }, sizeof(uint32_t));
+- memcpy(message->patch + 8, sender, n_sender + 1);
+- memset(message->patch + 8 + n_sender + 1, 0, n_stitch - n_field);
++ c_memcpy(message->patch + 4, (uint32_t[1]){ htole32(n_sender) }, sizeof(uint32_t));
++ c_memcpy(message->patch + 8, sender, n_sender + 1);
++ c_memset(message->patch + 8 + n_sender + 1, 0, n_stitch - n_field);
+
+ /*
+ * After we cut the previous sender field and inserted the new, adjust
+--- a/src/dbus/queue.c
++++ b/src/dbus/queue.c
+@@ -170,14 +170,14 @@
+ c_assert(!iq->data_start);
+ c_assert(iq->data == iq->buffer);
+
+- memcpy(p, iq->data, iq->data_end);
++ c_memcpy(p, iq->data, iq->data_end);
+ iq->data = p;
+ iq->data_size = IQUEUE_LINE_MAX;
+ } else if (_c_unlikely_(iq->data != iq->buffer && iq->pending.data)) {
+ c_assert(!iq->data_start);
+ c_assert(iq->data_end <= sizeof(iq->buffer));
+
+- memcpy(iq->buffer, iq->data, iq->data_end);
++ c_memcpy(iq->buffer, iq->data, iq->data_end);
+ free(iq->data);
+ user_charge_deinit(&iq->charge_data);
+ iq->data = iq->buffer;
+@@ -314,9 +314,9 @@
+ if (n_data > 0) {
+ n = c_min(n_data, iq->pending.n_data - iq->pending.n_copied);
+
+- memcpy(iq->pending.data + iq->pending.n_copied,
+- iq->data + iq->data_start,
+- n);
++ c_memcpy(iq->pending.data + iq->pending.n_copied,
++ iq->data + iq->data_start,
++ n);
+
+ n_data -= n;
+ iq->data_start += n;
+--- a/src/dbus/socket.c
++++ b/src/dbus/socket.c
+@@ -115,7 +115,7 @@
+ return error_trace(r);
+
+ buffer->message = message_ref(message);
+- memcpy(buffer->vecs, message->vecs, sizeof(message->vecs));
++ c_memcpy(buffer->vecs, message->vecs, sizeof(message->vecs));
+
+ r = user_charge(socket->user,
+ &buffer->charges[0],
+@@ -472,11 +472,11 @@
+
+ socket_buffer_get_line_cursor(buffer, &line_out, &pos);
+
+- memcpy(line_out, line_in, n);
++ c_memcpy(line_out, line_in, n);
+ line_out += n;
+ *pos += n;
+
+- memcpy(line_out, "\r\n", strlen("\r\n"));
++ c_memcpy(line_out, "\r\n", strlen("\r\n"));
+ *pos += strlen("\r\n");
+
+ return 0;
+--- a/src/dbus/test-queue.c
++++ b/src/dbus/test-queue.c
+@@ -59,7 +59,7 @@
+ if (!n)
+ break;
+
+- memcpy(buffer + *from, blob, n);
++ c_memcpy(buffer + *from, blob, n);
+ *from += n;
+ total += n;
+
+@@ -110,7 +110,7 @@
+ c_assert(!r);
+ c_assert(to - *from >= 128);
+
+- memcpy(buffer + *from, (char [1]){}, 1);
++ c_memcpy(buffer + *from, (char [1]){}, 1);
+ *from += 1;
+ r = fdlist_new_with_fds(fds, (int [1]){}, 1);
+ c_assert(!r);
+@@ -149,7 +149,7 @@
+ c_assert(!r);
+ c_assert(to - *from >= 128);
+
+- memcpy(buffer + *from, (char [2]){}, 2);
++ c_memcpy(buffer + *from, (char [2]){}, 2);
+ *from += 2;
+ r = fdlist_new_with_fds(fds, (int [1]){ 1 }, 1);
+ c_assert(!r);
+@@ -199,7 +199,7 @@
+ c_assert(!r);
+ c_assert(to - *from >= 128);
+
+- memcpy(buffer + *from, (char [1]){}, 1);
++ c_memcpy(buffer + *from, (char [1]){}, 1);
+ *from += 1;
+ r = fdlist_new_with_fds(fds, (int [1]){}, 1);
+ c_assert(!r);
+@@ -307,7 +307,7 @@
+ n = rand() % c_min(n, strlen(send) - i_send);
+ ++n;
+
+- memcpy(buffer + *from, send + i_send, n);
++ c_memcpy(buffer + *from, send + i_send, n);
+ i_send += n;
+ *from += n;
+ }
+--- a/src/dbus/test-stitching.c
++++ b/src/dbus/test-stitching.c
+@@ -62,7 +62,7 @@
+ if (before) {
+ p = malloc(before + 1);
+ c_assert(p);
+- memset(p, 'a', before);
++ c_memset(p, 'a', before);
+ p[before] = 0;
+
+ c_dvar_write(&v, "(y<s>)",
+@@ -82,7 +82,7 @@
+ if (after) {
+ p = malloc(after + 1);
+ c_assert(p);
+- memset(p, 'a', after);
++ c_memset(p, 'a', after);
+ p[0] = '/';
+ p[after] = 0;
+
+@@ -127,7 +127,7 @@
+ c_assert(p);
+
+ for (n = 0, i = 0; i < C_ARRAY_SIZE(message->vecs); ++i) {
+- memcpy(p + n, message->vecs[i].iov_base, message->vecs[i].iov_len);
++ c_memcpy(p + n, message->vecs[i].iov_base, message->vecs[i].iov_len);
+ n += message->vecs[i].iov_len;
+ }
+
+@@ -155,7 +155,7 @@
+ n = 8 + i % 8;
+ from = malloc(n + 1);
+ c_assert(from);
+- memset(from, '1', n);
++ c_memset(from, '1', n);
+ from[0] = ':';
+ from[1] = '1';
+ from[2] = '.';
+@@ -164,7 +164,7 @@
+ n = 8 + i % 11;
+ to = malloc(n + 1);
+ c_assert(to);
+- memset(to, '2', n);
++ c_memset(to, '2', n);
+ to[0] = ':';
+ to[1] = '1';
+ to[2] = '.';
+--- a/src/launch/config.c
++++ b/src/launch/config.c
+@@ -64,11 +64,11 @@
+ file->parent = config_path_ref(parent);
+
+ if (n_prefix) {
+- memcpy(file->path, prefix, n_prefix);
++ c_memcpy(file->path, prefix, n_prefix);
+ file->path[n_prefix] = '/';
+- memcpy(file->path + n_prefix + 1, path, n_path + 1);
++ c_memcpy(file->path + n_prefix + 1, path, n_path + 1);
+ } else {
+- memcpy(file->path, path, n_path + 1);
++ c_memcpy(file->path, path, n_path + 1);
+ }
+
+ *filep = file;
+@@ -1195,8 +1195,8 @@
+ return;
+ }
+
+- memcpy(t, state->current->cdata, state->current->n_cdata);
+- memcpy(t + state->current->n_cdata, data, n_data);
++ c_memcpy(t, state->current->cdata, state->current->n_cdata);
++ c_memcpy(t + state->current->n_cdata, data, n_data);
+ t[state->current->n_cdata + n_data] = 0;
+ free(state->current->cdata);
+ state->current->cdata = t;
+@@ -1232,7 +1232,7 @@
+ c_assert(node->type == CONFIG_NODE_INCLUDE);
+ c_assert(node->include.file);
+
+- memset(&parser->state, 0, sizeof(parser->state));
++ c_memset(&parser->state, 0, sizeof(parser->state));
+ parser->state.nss = nss_cache;
+ parser->state.dirwatch = dirwatch;
+ parser->state.file = node->include.file;
+--- a/src/launch/nss-cache.c
++++ b/src/launch/nss-cache.c
+@@ -210,7 +210,7 @@
+ return error_trace(r);
+
+ if (node) {
+- memset(&node->pw, 0, sizeof(node->pw));
++ c_memset(&node->pw, 0, sizeof(node->pw));
+ node->pw.pw_name = node->name;
+ node->pw.pw_uid = pw->pw_uid;
+ node->pw.pw_gid = pw->pw_gid;
+@@ -232,7 +232,7 @@
+ return error_trace(r);
+
+ if (node) {
+- memset(&node->gr, 0, sizeof(node->gr));
++ c_memset(&node->gr, 0, sizeof(node->gr));
+ node->gr.gr_name = node->name;
+ node->gr.gr_gid = gr->gr_gid;
+ }
+--- a/src/util/fdlist.c
++++ b/src/util/fdlist.c
+@@ -37,7 +37,7 @@
+ list->cmsg->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
+ list->cmsg->cmsg_level = SOL_SOCKET;
+ list->cmsg->cmsg_type = SCM_RIGHTS;
+- memcpy(fdlist_data(list), fds, n_fds * sizeof(int));
++ c_memcpy(fdlist_data(list), fds, n_fds * sizeof(int));
+
+ *listp = list;
+ return 0;
+--- a/src/util/log.c
++++ b/src/util/log.c
+@@ -278,7 +278,7 @@
+ control.cmsg.cmsg_len = CMSG_LEN(sizeof(int));
+ control.cmsg.cmsg_level = SOL_SOCKET;
+ control.cmsg.cmsg_type = SCM_RIGHTS;
+- memcpy(CMSG_DATA(&control.cmsg), &payload_fd, sizeof(int));
++ c_memcpy(CMSG_DATA(&control.cmsg), &payload_fd, sizeof(int));
+
+ msg = (struct msghdr){
+ .msg_control = &control.cmsg,
+@@ -590,7 +590,7 @@
+ return;
+ }
+
+- memcpy(log->map + log->offset, data, n_data);
++ c_memcpy(log->map + log->offset, data, n_data);
+ log->offset += n_data;
+ }
+
+--- a/src/util/selinux.c
++++ b/src/util/selinux.c
+@@ -71,7 +71,7 @@
+ return error_origin(-ENOMEM);
+ selinux_name->rb = (CRBNode)C_RBNODE_INIT(selinux_name->rb);
+ selinux_name->context = NULL;
+- memcpy(selinux_name->name, name, n_name);
++ c_memcpy(selinux_name->name, name, n_name);
+
+ selinux_name->context = strdup(context);
+ if (!selinux_name->context)
+@@ -105,7 +105,7 @@
+ registry->n_refs = REF_INIT;
+ registry->fallback_context = (const char *)(registry + 1);
+ registry->names = (CRBTree)C_RBTREE_INIT;
+- memcpy((char *)registry->fallback_context, fallback_context, n_fallback_context);
++ c_memcpy((char *)registry->fallback_context, fallback_context, n_fallback_context);
+
+ *registryp = registry;
+ registry = NULL;
+--- a/src/util/user.c
++++ b/src/util/user.c
+@@ -389,7 +389,7 @@
+
+ registry->log = log;
+ registry->n_slots = n_slots;
+- memcpy(registry->maxima, maxima, n_slots * sizeof(*registry->maxima));
++ c_memcpy(registry->maxima, maxima, n_slots * sizeof(*registry->maxima));
+
+ return 0;
+ }
+--- a/test/dbus/test-fdstream.c
++++ b/test/dbus/test-fdstream.c
+@@ -74,7 +74,7 @@
+ if (n_fds > 0) {
+ int fds[n_fds];
+
+- memset(fds, 0, sizeof(fds));
++ c_memset(fds, 0, sizeof(fds));
+ r = fdlist_new_with_fds(&m->fds, fds, n_fds);
+ c_assert(!r);
+ }
+--- a/test/dbus/util-message.c
++++ b/test/dbus/util-message.c
+@@ -43,7 +43,7 @@
+ p = realloc(*buf, *n_buf + n_data);
+ c_assert(p);
+
+- memcpy(p + *n_buf, data, n_data);
++ c_memcpy(p + *n_buf, data, n_data);
+
+ *buf = p;
+ *n_buf += n_data;
diff -Nru dbus-broker-26/debian/patches/launch-service-fix-release-of-argv-array.patch dbus-broker-26/debian/patches/launch-service-fix-release-of-argv-array.patch
--- dbus-broker-26/debian/patches/launch-service-fix-release-of-argv-array.patch 1970-01-01 01:00:00.000000000 +0100
+++ dbus-broker-26/debian/patches/launch-service-fix-release-of-argv-array.patch 2022-08-04 12:55:19.000000000 +0100
@@ -0,0 +1,30 @@
+Author: David Rheinsberg <david.rheinsberg@gmail.com>
+Origin: backport, https://github.com/bus1/dbus-broker/commit/6d9b817b7c165be9addbc28b9e84d7ed1697d11a
+Description: launch/service: fix release of argv array
+ While service_free() correctly releases the strv in `argv`, the
+ service_update() path does not. It frees `argv`, but not the individual
+ entries. Fix this and properly release all entries.
+--- a/src/launch/service.c
++++ b/src/launch/service.c
+@@ -96,8 +96,12 @@
+ }
+
+ int service_update(Service *service, const char *path, const char *unit, size_t argc, char **argv, const char *user, uid_t uid) {
++ size_t i;
++
+ service->path = c_free(service->path);
+ service->unit = c_free(service->unit);
++ for (i = 0; i < service->argc; ++i)
++ free(service->argv[i]);
+ service->argc = 0;
+ service->argv = c_free(service->argv);
+ service->user = c_free(service->user);
+@@ -122,7 +126,7 @@
+
+ service->argc = argc;
+
+- for (size_t i = 0; i < argc; ++i) {
++ for (i = 0; i < argc; ++i) {
+ service->argv[i] = strdup(argv[i]);
+ if (!service->argv[i])
+ return error_origin(-ENOMEM);
diff -Nru dbus-broker-26/debian/patches/series dbus-broker-26/debian/patches/series
--- dbus-broker-26/debian/patches/series 2022-06-22 22:23:12.000000000 +0100
+++ dbus-broker-26/debian/patches/series 2022-08-04 12:55:19.000000000 +0100
@@ -1 +1,6 @@
strnspn-fix-buffer-overflow.patch
+util-user-keep-reference-to-user-in-each-usage-table.patch
+launch-service-fix-release-of-argv-array.patch
+c-stdaux-add-c_memset.patch
+c-stdaux-add-c_memcpy.patch
+global-use-c_mem-over-mem.patch
diff -Nru dbus-broker-26/debian/patches/util-user-keep-reference-to-user-in-each-usage-table.patch dbus-broker-26/debian/patches/util-user-keep-reference-to-user-in-each-usage-table.patch
--- dbus-broker-26/debian/patches/util-user-keep-reference-to-user-in-each-usage-table.patch 1970-01-01 01:00:00.000000000 +0100
+++ dbus-broker-26/debian/patches/util-user-keep-reference-to-user-in-each-usage-table.patch 2022-08-04 12:55:19.000000000 +0100
@@ -0,0 +1,49 @@
+Author: David Rheinsberg <david.rheinsberg@gmail.com>
+Origin: backport, https://github.com/bus1/dbus-broker/commit/608b259e25ef1348b9e4a8e022c35b5c68d3df98
+Description: util/user: keep reference to user in each usage table
+ Keep a reference to an owning user in each usage table. We want to allow
+ callers to hold charges without holding on to any user references.
+ .
+ Also fix the peer-deinitialization to be ordered correctly and free the
+ user references last (in particular, after the charges). This is not
+ strictly necessary, but now follows our coding style and would have
+ avoided possible failures.
+ .
+ This fixes an assertion failure when disconnecting entire groups of
+ peers of the same user, due to the recent fix that actually made
+ peer-accounting do something.
+--- a/src/bus/peer.c
++++ b/src/bus/peer.c
+@@ -358,12 +358,12 @@
+ name_owner_deinit(&peer->owned_names);
+ policy_snapshot_free(peer->policy);
+ connection_deinit(&peer->connection);
+- user_unref(peer->user);
+ user_charge_deinit(&peer->charges[2]);
+ user_charge_deinit(&peer->charges[1]);
+ user_charge_deinit(&peer->charges[0]);
+ free(peer->seclabel);
+ free(peer->gids);
++ user_unref(peer->user);
+ free(peer);
+
+ close(fd);
+--- a/src/util/user.c
++++ b/src/util/user.c
+@@ -48,7 +48,7 @@
+ return error_origin(-ENOMEM);
+
+ usage->n_refs = REF_INIT;
+- usage->user = user;
++ usage->user = user_ref(user);
+ usage->uid = uid;
+ usage->user_node = (CRBNode)C_RBNODE_INIT(usage->user_node);
+
+@@ -64,6 +64,7 @@
+ c_assert(!usage->slots[i]);
+
+ user_usage_unlink(usage);
++ user_unref(usage->user);
+ free(usage);
+ }
+
Attachment:
signature.asc
Description: This is a digitally signed message part