diff mbox series

[scarthgap,v3,6/6] glib-2.0: fix CVE-2026-58015

Message ID 20260731101013.208779-1-deeratho@cisco.com
State New
Headers show
Series None | expand

Commit Message

From: Deepak Rathore <deeratho@cisco.com>

This patch applies the upstream glib-2-88 stable backport chain for
CVE-2026-58015. The issue is in the D-Bus SHA-1 authentication
mechanism, where a malicious peer could provide an unchecked cookie
context and cause the client to access unintended files while resolving
the cookie challenge.

Backport the upstream GLib fix chain from the glib-2-88 stable branch:
- db9c8fae398b validates cookie_context before keyring lookup. This is
the primary security fix for CVE-2026-58015 [1].
- c0531125344b tightens cookie ID parsing so empty, negative, and
out-of-range values are rejected. This hardens the same SHA-1 cookie
challenge parser and is covered by the upstream regression test [2].
- 060aea67de75 exposes the private client reject-reason vfunc. This is
test-support plumbing required by the upstream regression test [3].
- 091930196229 adds the upstream regression test for SHA-1 cookie
challenge parsing [4].

Add dbus-native to PACKAGECONFIG[tests] so Meson can find dbus-daemon
when building the new installed D-Bus regression test for ptest. This is
kept as a native-only test dependency to avoid adding a target dbus
dependency to glib.

[1] https://gitlab.gnome.org/GNOME/glib/-/commit/db9c8fae398b0c457e660ce63dd5afec8993046a
[2] https://gitlab.gnome.org/GNOME/glib/-/commit/c0531125344bb25fd66ffb7435ed6c285de09aeb
[3] https://gitlab.gnome.org/GNOME/glib/-/commit/060aea67de7517d531b8fe2cdc07aa1a00ddeb22
[4] https://gitlab.gnome.org/GNOME/glib/-/commit/0919301962291a712067ee0c5d273cc392f33277
[5] https://nvd.nist.gov/vuln/detail/CVE-2026-58015

Signed-off-by: Deepak Rathore <deeratho@cisco.com>
---
Changes in v3:
- Carry the full upstream stable backport chain for CVE-2026-58015,
  including the cookie ID hardening, private test-support vfunc, and
  regression test commits.
- Add dbus-native to PACKAGECONFIG[tests] so Meson can find dbus-daemon
  and build/install the new D-Bus regression test for ptest.
- Expand the commit message references so each upstream commit in the
  backport chain is linked from the explanatory text.

 .../glib-2.0/glib-2.0/CVE-2026-58015_p1.patch |  98 ++++++++
 .../glib-2.0/glib-2.0/CVE-2026-58015_p2.patch |  55 +++++
 .../glib-2.0/glib-2.0/CVE-2026-58015_p3.patch | 198 ++++++++++++++++
 .../glib-2.0/glib-2.0/CVE-2026-58015_p4.patch | 219 ++++++++++++++++++
 meta/recipes-core/glib-2.0/glib-2.0_2.78.6.bb |   4 +
 meta/recipes-core/glib-2.0/glib.inc           |   2 +-
 6 files changed, 575 insertions(+), 1 deletion(-)
 create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p1.patch
 create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p2.patch
 create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p3.patch
 create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p4.patch

Comments

patchtest@automation.yoctoproject.org July 31, 2026, 10:16 a.m. UTC | #1
Thank you for your submission. Patchtest identified one
or more issues with the patch. Please see the log below for
more information:

---
Testing patch /home/patchtest/share/mboxes/scarthgap-v3-6-6-glib-2.0-fix-CVE-2026-58015.patch

FAIL: test mbox format: Series has malformed diff lines. Create the series again using git-format-patch and ensure it applies using git am (test_mbox.TestMbox.test_mbox_format)

PASS: test Signed-off-by presence (test_mbox.TestMbox.test_signed_off_by_presence)
PASS: test author valid (test_mbox.TestMbox.test_author_valid)
PASS: test commit message presence (test_mbox.TestMbox.test_commit_message_presence)
PASS: test commit message user tags (test_mbox.TestMbox.test_commit_message_user_tags)
PASS: test max line length (test_metadata.TestMetadata.test_max_line_length)
PASS: test non-AUH upgrade (test_mbox.TestMbox.test_non_auh_upgrade)
PASS: test shortlog format (test_mbox.TestMbox.test_shortlog_format)
PASS: test shortlog length (test_mbox.TestMbox.test_shortlog_length)
PASS: test target mailing list (test_mbox.TestMbox.test_target_mailing_list)

SKIP: pretest pylint: Python-unidiff parse error (test_python_pylint.PyLint.pretest_pylint)
SKIP: pretest src uri left files: Patch cannot be merged (test_metadata.TestMetadata.pretest_src_uri_left_files)
SKIP: test CVE check ignore: No modified recipes or older target branch, skipping test (test_metadata.TestMetadata.test_cve_check_ignore)
SKIP: test CVE tag format: Parse error Hunk is shorter than expected (test_patch.TestPatch.test_cve_tag_format)
SKIP: test Signed-off-by presence: Parse error Hunk is shorter than expected (test_patch.TestPatch.test_signed_off_by_presence)
SKIP: test Upstream-Status presence: Parse error Hunk is shorter than expected (test_patch.TestPatch.test_upstream_status_presence_format)
SKIP: test bugzilla entry format: No bug ID found (test_mbox.TestMbox.test_bugzilla_entry_format)
SKIP: test lic files chksum modified not mentioned: No modified recipes, skipping test (test_metadata.TestMetadata.test_lic_files_chksum_modified_not_mentioned)
SKIP: test lic files chksum presence: No added recipes, skipping test (test_metadata.TestMetadata.test_lic_files_chksum_presence)
SKIP: test license presence: No added recipes, skipping test (test_metadata.TestMetadata.test_license_presence)
SKIP: test pylint: Python-unidiff parse error (test_python_pylint.PyLint.test_pylint)
SKIP: test series merge on head: Merge test is disabled for now (test_mbox.TestMbox.test_series_merge_on_head)
SKIP: test src uri left files: Patch cannot be merged (test_metadata.TestMetadata.test_src_uri_left_files)
SKIP: test summary presence: No added recipes, skipping test (test_metadata.TestMetadata.test_summary_presence)

---

Please address the issues identified and
submit a new revision of the patch, or alternatively, reply to this
email with an explanation of why the patch should be accepted. If you
believe these results are due to an error in patchtest, please submit a
bug at https://bugzilla.yoctoproject.org/ (use the 'Patchtest' category
under 'Yocto Project Subprojects'). For more information on specific
failures, see: https://wiki.yoctoproject.org/wiki/Patchtest. Thank
you!
diff mbox series

Patch

diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p1.patch
new file mode 100644
index 0000000000..3c3b74fc58
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p1.patch
@@ -0,0 +1,98 @@ 
+From 1d0d0dc891399e8572a6c96b116149d076e2de28 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Tue, 28 Apr 2026 15:47:30 +0100
+Subject: [PATCH 1/4] gdbusauthmechanismsha1: Validate cookie context
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Without validation, the server could send a malicious context which
+contains path traversal characters, allowing it to exfiltrate a SHA-1
+hashed copy of arbitrary data from the client's file system.
+
+To exploit this successfully would require the client to choose to
+connect peer-to-peer to a malicious D-Bus server and to choose the SHA-1
+authentication mechanism in preference to all the other mechanisms. This
+is vanishingly unlikely.
+
+CVE: CVE-2026-58015
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/db9c8fae398b0c457e660ce63dd5afec8993046a]
+
+Backport Changes:
+- Added <stdint.h> include because the target branch does not otherwise
+  expose uint8_t used by the upstream validation code during native builds.
+
+Signed-off-by: Philip Withnall <pwithnall@gnome.org>
+
+Fixes: #3931
+(cherry picked from commit db9c8fae398b0c457e660ce63dd5afec8993046a)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ gio/gdbusauthmechanismsha1.c | 37 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
+index c8aa08977..7d8fc1922 100644
+--- a/gio/gdbusauthmechanismsha1.c
++++ b/gio/gdbusauthmechanismsha1.c
+@@ -22,6 +22,7 @@
+ 
+ #include "config.h"
+ 
++#include <stdint.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <errno.h>
+@@ -1198,6 +1199,34 @@ mechanism_client_initiate (GDBusAuthMechanism   *mechanism,
+   return initial_response;
+ }
+ 
++/* Context names must be valid ASCII, nonzero length, and may not contain the
++ * characters slash ("/"), backslash ("\"), space (" "), newline ("\n"),
++ * carriage return ("\r"), tab ("\t"), or period (".").
++ *
++ * See https://dbus.freedesktop.org/doc/dbus-specification.html#auth-mechanisms-sha */
++static gboolean
++validate_cookie_context (const char *cookie_context)
++{
++  size_t i = 0;
++
++  g_return_val_if_fail (cookie_context != NULL, FALSE);
++
++  for (i = 0; cookie_context[i] != '\0'; i++)
++    {
++      if ((uint8_t) cookie_context[i] >= 128 ||
++          cookie_context[i] == '/' ||
++          cookie_context[i] == '\\' ||
++          cookie_context[i] == ' ' ||
++          cookie_context[i] == '\n' ||
++          cookie_context[i] == '\r' ||
++          cookie_context[i] == '\t' ||
++          cookie_context[i] == '.')
++        return FALSE;
++    }
++
++  return (i > 0);
++}
++
+ static void
+ mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
+                                const gchar          *data,
+@@ -1232,6 +1261,14 @@ mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
+     }
+ 
+   cookie_context = tokens[0];
++  if (!validate_cookie_context (tokens[0]))
++    {
++      g_free (m->priv->reject_reason);
++      m->priv->reject_reason = g_strdup_printf ("Malformed cookie_context '%s'", tokens[0]);
++      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
++      goto out;
++    }
++
+   cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
+   if (*endp != '\0')
+     {
+-- 
+2.35.6
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p2.patch
new file mode 100644
index 0000000000..28f496734a
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p2.patch
@@ -0,0 +1,55 @@ 
+From a94b2df7e2bc5f49661e53c2781ce99ae48d18aa Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Tue, 28 Apr 2026 15:49:54 +0100
+Subject: [PATCH 2/4] gdbusauthmechanismsha1: Improve validation of cookie ID
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The D-Bus specification says the cookie ID has to be non-negative, but
+we weren’t checking that (or checking that it was non-empty).
+
+CVE: CVE-2026-58015
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/c0531125344bb25fd66ffb7435ed6c285de09aeb]
+
+Signed-off-by: Philip Withnall <pwithnall@gnome.org>
+(cherry picked from commit c0531125344bb25fd66ffb7435ed6c285de09aeb)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ gio/gdbusauthmechanismsha1.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
+index 7d8fc1922..e753d139d 100644
+--- a/gio/gdbusauthmechanismsha1.c
++++ b/gio/gdbusauthmechanismsha1.c
+@@ -1235,7 +1235,7 @@ mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
+   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
+   gchar **tokens;
+   const gchar *cookie_context;
+-  guint cookie_id;
++  int64_t cookie_id;
+   const gchar *server_challenge;
+   gchar *client_challenge;
+   gchar *endp;
+@@ -1270,7 +1270,7 @@ mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
+     }
+ 
+   cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
+-  if (*endp != '\0')
++  if (*endp != '\0' || endp == tokens[1] || cookie_id < 0 || cookie_id > UINT32_MAX)
+     {
+       g_free (m->priv->reject_reason);
+       m->priv->reject_reason = g_strdup_printf ("Malformed cookie_id '%s'", tokens[1]);
+@@ -1280,7 +1280,7 @@ mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
+   server_challenge = tokens[2];
+ 
+   error = NULL;
+-  cookie = keyring_lookup_entry (cookie_context, cookie_id, &error);
++  cookie = keyring_lookup_entry (cookie_context, (unsigned int) cookie_id, &error);
+   if (cookie == NULL)
+     {
+       g_free (m->priv->reject_reason);
+-- 
+2.35.6
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p3.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p3.patch
new file mode 100644
index 0000000000..b6bd2baeb3
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p3.patch
@@ -0,0 +1,198 @@ 
+From 99c7abffbd1d549f6c625de6f2028efcdeea5c49 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Tue, 28 Apr 2026 15:51:00 +0100
+Subject: [PATCH 3/4] gdbusauthmechanism: Expose client reject reason as a new
+ vfunc
+
+We can do this because `gdbusauthmechanism.h` is a private header.
+
+Hook it up to the existing `reject_reason` code in each
+`GDBusAuthMechanism` implementation, as all three implementations
+currently intermingle reject reasons from the server and client code, so
+there would currently be no benefit to having a separate server and
+client implementation of `*_get_reject_reason()`.
+
+This new private API will be used in a new unit test in the following
+commit.
+
+CVE: CVE-2026-58015
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/060aea67de7517d531b8fe2cdc07aa1a00ddeb22]
+
+Signed-off-by: Philip Withnall <pwithnall@gnome.org>
+(cherry picked from commit 060aea67de7517d531b8fe2cdc07aa1a00ddeb22)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ gio/gdbusauthmechanism.c         | 7 +++++++
+ gio/gdbusauthmechanism.h         | 2 ++
+ gio/gdbusauthmechanismanon.c     | 8 ++++----
+ gio/gdbusauthmechanismexternal.c | 8 ++++----
+ gio/gdbusauthmechanismsha1.c     | 8 ++++----
+ 5 files changed, 21 insertions(+), 12 deletions(-)
+
+diff --git a/gio/gdbusauthmechanism.c b/gio/gdbusauthmechanism.c
+index 6e494dbd9..0d4ef4389 100644
+--- a/gio/gdbusauthmechanism.c
++++ b/gio/gdbusauthmechanism.c
+@@ -328,6 +328,13 @@ _g_dbus_auth_mechanism_client_data_send (GDBusAuthMechanism *mechanism,
+   return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_data_send (mechanism, out_data_len);
+ }
+ 
++gchar *
++_g_dbus_auth_mechanism_client_get_reject_reason (GDBusAuthMechanism *mechanism)
++{
++  g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM (mechanism), NULL);
++  return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_get_reject_reason (mechanism);
++}
++
+ void
+ _g_dbus_auth_mechanism_client_shutdown (GDBusAuthMechanism *mechanism)
+ {
+diff --git a/gio/gdbusauthmechanism.h b/gio/gdbusauthmechanism.h
+index f0edd19a3..e906a47ac 100644
+--- a/gio/gdbusauthmechanism.h
++++ b/gio/gdbusauthmechanism.h
+@@ -100,6 +100,7 @@ struct _GDBusAuthMechanismClass
+                                                          gsize                 data_len);
+   gchar                    *(*client_data_send)         (GDBusAuthMechanism   *mechanism,
+                                                          gsize                *out_data_len);
++  gchar                    *(*client_get_reject_reason) (GDBusAuthMechanism   *mechanism);
+   void                      (*client_shutdown)          (GDBusAuthMechanism   *mechanism);
+ };
+ 
+@@ -148,6 +149,7 @@ void                      _g_dbus_auth_mechanism_client_data_receive      (GDBus
+                                                                            gsize                 data_len);
+ gchar                    *_g_dbus_auth_mechanism_client_data_send         (GDBusAuthMechanism   *mechanism,
+                                                                           gsize                *out_data_len);
++gchar                    *_g_dbus_auth_mechanism_client_get_reject_reason (GDBusAuthMechanism   *mechanism);
+ void                      _g_dbus_auth_mechanism_client_shutdown          (GDBusAuthMechanism   *mechanism);
+ 
+ 
+diff --git a/gio/gdbusauthmechanismanon.c b/gio/gdbusauthmechanismanon.c
+index 5f59d4a61..3d80ec15f 100644
+--- a/gio/gdbusauthmechanismanon.c
++++ b/gio/gdbusauthmechanismanon.c
+@@ -56,7 +56,7 @@ static void                     mechanism_server_data_receive       (GDBusAuthMe
+                                                                      gsize                 data_len);
+ static gchar                   *mechanism_server_data_send          (GDBusAuthMechanism   *mechanism,
+                                                                      gsize                *out_data_len);
+-static gchar                   *mechanism_server_get_reject_reason  (GDBusAuthMechanism   *mechanism);
++static gchar                   *mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism   *mechanism);
+ static void                     mechanism_server_shutdown           (GDBusAuthMechanism   *mechanism);
+ static GDBusAuthMechanismState  mechanism_client_get_state          (GDBusAuthMechanism   *mechanism);
+ static gchar                   *mechanism_client_initiate           (GDBusAuthMechanism   *mechanism,
+@@ -103,12 +103,13 @@ _g_dbus_auth_mechanism_anon_class_init (GDBusAuthMechanismAnonClass *klass)
+   mechanism_class->server_initiate           = mechanism_server_initiate;
+   mechanism_class->server_data_receive       = mechanism_server_data_receive;
+   mechanism_class->server_data_send          = mechanism_server_data_send;
+-  mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
++  mechanism_class->server_get_reject_reason  = mechanism_server_or_client_get_reject_reason;
+   mechanism_class->server_shutdown           = mechanism_server_shutdown;
+   mechanism_class->client_get_state          = mechanism_client_get_state;
+   mechanism_class->client_initiate           = mechanism_client_initiate;
+   mechanism_class->client_data_receive       = mechanism_client_data_receive;
+   mechanism_class->client_data_send          = mechanism_client_data_send;
++  mechanism_class->client_get_reject_reason  = mechanism_server_or_client_get_reject_reason;
+   mechanism_class->client_shutdown           = mechanism_client_shutdown;
+ }
+ 
+@@ -222,12 +223,11 @@ mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
+ }
+ 
+ static gchar *
+-mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
++mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism   *mechanism)
+ {
+   GDBusAuthMechanismAnon *m = G_DBUS_AUTH_MECHANISM_ANON (mechanism);
+ 
+   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_ANON (mechanism), NULL);
+-  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
+   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
+ 
+   /* can never end up here because we are never in the REJECTED state */
+diff --git a/gio/gdbusauthmechanismexternal.c b/gio/gdbusauthmechanismexternal.c
+index 6fe8b1bed..b223ead04 100644
+--- a/gio/gdbusauthmechanismexternal.c
++++ b/gio/gdbusauthmechanismexternal.c
+@@ -64,7 +64,7 @@ static void                     mechanism_server_data_receive       (GDBusAuthMe
+                                                                      gsize                 data_len);
+ static gchar                   *mechanism_server_data_send          (GDBusAuthMechanism   *mechanism,
+                                                                      gsize                *out_data_len);
+-static gchar                   *mechanism_server_get_reject_reason  (GDBusAuthMechanism   *mechanism);
++static gchar                   *mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism   *mechanism);
+ static void                     mechanism_server_shutdown           (GDBusAuthMechanism   *mechanism);
+ static GDBusAuthMechanismState  mechanism_client_get_state          (GDBusAuthMechanism   *mechanism);
+ static gchar                   *mechanism_client_initiate           (GDBusAuthMechanism   *mechanism,
+@@ -111,12 +111,13 @@ _g_dbus_auth_mechanism_external_class_init (GDBusAuthMechanismExternalClass *kla
+   mechanism_class->server_initiate           = mechanism_server_initiate;
+   mechanism_class->server_data_receive       = mechanism_server_data_receive;
+   mechanism_class->server_data_send          = mechanism_server_data_send;
+-  mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
++  mechanism_class->server_get_reject_reason  = mechanism_server_or_client_get_reject_reason;
+   mechanism_class->server_shutdown           = mechanism_server_shutdown;
+   mechanism_class->client_get_state          = mechanism_client_get_state;
+   mechanism_class->client_initiate           = mechanism_client_initiate;
+   mechanism_class->client_data_receive       = mechanism_client_data_receive;
+   mechanism_class->client_data_send          = mechanism_client_data_send;
++  mechanism_class->client_get_reject_reason  = mechanism_server_or_client_get_reject_reason;
+   mechanism_class->client_shutdown           = mechanism_client_shutdown;
+ }
+ 
+@@ -321,12 +322,11 @@ mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
+ }
+ 
+ static gchar *
+-mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
++mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism   *mechanism)
+ {
+   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
+ 
+   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
+-  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
+   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
+ 
+   /* can never end up here because we are never in the REJECTED state */
+diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
+index e753d139d..6c1682d3a 100644
+--- a/gio/gdbusauthmechanismsha1.c
++++ b/gio/gdbusauthmechanismsha1.c
+@@ -120,7 +120,7 @@ static void                     mechanism_server_data_receive       (GDBusAuthMe
+                                                                      gsize                 data_len);
+ static gchar                   *mechanism_server_data_send          (GDBusAuthMechanism   *mechanism,
+                                                                      gsize                *out_data_len);
+-static gchar                   *mechanism_server_get_reject_reason  (GDBusAuthMechanism   *mechanism);
++static gchar                   *mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism   *mechanism);
+ static void                     mechanism_server_shutdown           (GDBusAuthMechanism   *mechanism);
+ static GDBusAuthMechanismState  mechanism_client_get_state          (GDBusAuthMechanism   *mechanism);
+ static gchar                   *mechanism_client_initiate           (GDBusAuthMechanism   *mechanism,
+@@ -173,12 +173,13 @@ _g_dbus_auth_mechanism_sha1_class_init (GDBusAuthMechanismSha1Class *klass)
+   mechanism_class->server_initiate           = mechanism_server_initiate;
+   mechanism_class->server_data_receive       = mechanism_server_data_receive;
+   mechanism_class->server_data_send          = mechanism_server_data_send;
+-  mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
++  mechanism_class->server_get_reject_reason  = mechanism_server_or_client_get_reject_reason;
+   mechanism_class->server_shutdown           = mechanism_server_shutdown;
+   mechanism_class->client_get_state          = mechanism_client_get_state;
+   mechanism_class->client_initiate           = mechanism_client_initiate;
+   mechanism_class->client_data_receive       = mechanism_client_data_receive;
+   mechanism_class->client_data_send          = mechanism_client_data_send;
++  mechanism_class->client_get_reject_reason  = mechanism_server_or_client_get_reject_reason;
+   mechanism_class->client_shutdown           = mechanism_client_shutdown;
+ }
+ 
+@@ -1129,12 +1130,11 @@ mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
+ }
+ 
+ static gchar *
+-mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
++mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism *mechanism)
+ {
+   GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
+ 
+   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
+-  g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
+   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
+ 
+   return g_strdup (m->priv->reject_reason);
+-- 
+2.35.6
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p4.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p4.patch
new file mode 100644
index 0000000000..e7072bc6b4
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58015_p4.patch
@@ -0,0 +1,219 @@ 
+From 80d2edcc14f476d0ec82dc0733964afa6e9ca74d Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Tue, 28 Apr 2026 15:52:53 +0100
+Subject: [PATCH 4/4] tests: Add a unit test for GDBusAuthMechanismSha1 cookie
+ context parsing
+
+This checks for regressions in the fixes from the previous few commits.
+
+CVE: CVE-2026-58015
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/0919301962291a712067ee0c5d273cc392f33277]
+
+Signed-off-by: Philip Withnall <pwithnall@gnome.org>
+Helps: #3931
+(cherry picked from commit 0919301962291a712067ee0c5d273cc392f33277)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ gio/tests/gdbus-auth-mechanism-sha1.c | 177 ++++++++++++++++++++++++++
+ gio/tests/meson.build                 |   1 +
+ 2 files changed, 178 insertions(+)
+ create mode 100644 gio/tests/gdbus-auth-mechanism-sha1.c
+
+diff --git a/gio/tests/gdbus-auth-mechanism-sha1.c b/gio/tests/gdbus-auth-mechanism-sha1.c
+new file mode 100644
+index 000000000..abcdb4e3e
+--- /dev/null
++++ b/gio/tests/gdbus-auth-mechanism-sha1.c
+@@ -0,0 +1,177 @@
++/* GLib testing framework examples and tests
++ *
++ * Copyright (C) 2026 Philip Withnall
++ *
++ * SPDX-License-Identifier: LGPL-2.1-or-later
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General
++ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
++ *
++ * Author: Philip Withnall <pwithnall@gnome.org>
++ */
++
++#include <locale.h>
++#include <gio/gio.h>
++
++#include <string.h>
++#include <unistd.h>
++
++#include "gdbus-tests.h"
++
++#ifdef G_OS_UNIX
++#include <gio/gunixconnection.h>
++#include <gio/gnetworkingprivate.h>
++#include <gio/gunixsocketaddress.h>
++#include <gio/gunixfdlist.h>
++#endif
++
++#define GIO_COMPILATION 1
++#include "gdbusauthmechanism.h"
++#include "gdbusauthmechanismsha1.h"
++
++/* Vfunc wrappers copied from gdbusauthmechanism.c as they are not public. */
++static gboolean
++dbus_auth_mechanism_is_supported (GDBusAuthMechanism *mechanism)
++{
++  return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->is_supported (mechanism);
++}
++
++static GDBusAuthMechanismState
++dbus_auth_mechanism_client_get_state (GDBusAuthMechanism *mechanism)
++{
++  return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_get_state (mechanism);
++}
++
++static gchar *
++dbus_auth_mechanism_client_initiate (GDBusAuthMechanism   *mechanism,
++                                     GDBusConnectionFlags  conn_flags,
++                                     size_t               *out_initial_response_len)
++{
++  return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_initiate (mechanism,
++                                                                       conn_flags,
++                                                                       out_initial_response_len);
++}
++
++static void
++dbus_auth_mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
++                                         const char         *data,
++                                         size_t              data_len)
++{
++  G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_data_receive (mechanism, data, data_len);
++}
++
++static char *
++dbus_auth_mechanism_client_get_reject_reason (GDBusAuthMechanism *mechanism)
++{
++  return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_get_reject_reason (mechanism);
++}
++
++static void
++dbus_auth_mechanism_client_shutdown (GDBusAuthMechanism *mechanism)
++{
++  G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_shutdown (mechanism);
++}
++
++static void
++test_server_challenge_validation (void)
++{
++  const struct
++    {
++      const char *server_challenge;
++      const char *expected_reject_reason_prefix;
++    }
++  vectors[] = {
++    { "valid_context 123 456", "Problems looking up entry in keyring" },
++    { "invalid/context 123 456", "Malformed cookie_context" },
++    { "invalid.context 123 456", "Malformed cookie_context" },
++    { " 123 456", "Malformed cookie_context" },
++    { "