Fix CVE-2026-58013: buffer over-read in GIOChannel with long terminators
Backport fix for CVE-2026-58013 to glib2-2.56.4. The patch
fixes a buffer over-read in giochannel.c where memcmp()
could read past the end of the buffer when a multi-byte
line terminator is used and the line extends to the end of
the buffer. A bounds check is added before the memcmp()
call. A minimal test file (io-channel.c) is included,
adapted for 2.56.4 API compatibility.
CVE: CVE-2026-58013
Upstream patches:
- 9f557746c5.patch
Resolves: RHEL-212229
This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.
Assisted-by: Ymir
This commit is contained in:
parent
a0bcad8847
commit
b3d5305454
127
CVE-2026-58013.patch
Normal file
127
CVE-2026-58013.patch
Normal file
@ -0,0 +1,127 @@
|
||||
From bb5c37897584ca09c583161f908046edc2ec9d85 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Tue, 28 Apr 2026 16:45:14 +0100
|
||||
Subject: [PATCH] giochannel: Fix memcmp() off the end of the buffer with long
|
||||
terminators
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
If the line terminator is longer than a single byte, and the current
|
||||
line extends to the end of the buffer, and the buffer (which is a
|
||||
`GString`) is near a power of two in length (as that’s how `GString`s
|
||||
are allocated) it’s possible for the `memcmp()` which checks the
|
||||
terminator to read off the end of the string buffer.
|
||||
|
||||
Fix that by checking the terminator length against the last character
|
||||
before calling `memcmp()`. Add a unit test.
|
||||
|
||||
Spotted by linhlhq as #YWH-PGM9867-199. The fix is theirs (validated by
|
||||
me), and the unit test is adapted from their proof of concept.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
Fixes: #3925
|
||||
---
|
||||
glib/giochannel.c | 3 +-
|
||||
glib/tests/io-channel.c | 78 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 80 insertions(+), 1 deletion(-)
|
||||
create mode 100644 glib/tests/io-channel.c
|
||||
|
||||
diff --git a/glib/giochannel.c b/glib/giochannel.c
|
||||
index f01817a83..32a1550b7 100644
|
||||
--- a/glib/giochannel.c
|
||||
+++ b/glib/giochannel.c
|
||||
@@ -1807,7 +1807,8 @@ read_again:
|
||||
{
|
||||
if (channel->line_term)
|
||||
{
|
||||
- if (memcmp (channel->line_term, nextchar, line_term_len) == 0)
|
||||
+ if ((size_t) (lastchar - nextchar) >= line_term_len &&
|
||||
+ memcmp (channel->line_term, nextchar, line_term_len) == 0)
|
||||
{
|
||||
line_length = nextchar - use_buf->str;
|
||||
got_term_len = line_term_len;
|
||||
diff --git a/glib/tests/io-channel.c b/glib/tests/io-channel.c
|
||||
new file mode 100644
|
||||
index 000000000..447675ee8
|
||||
--- /dev/null
|
||||
+++ b/glib/tests/io-channel.c
|
||||
@@ -0,0 +1,78 @@
|
||||
+/* Test for CVE-2026-58013: memcmp() off the end of the buffer with long terminators
|
||||
+ *
|
||||
+ * Copyright © 2026 Philip Withnall
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+ */
|
||||
+
|
||||
+#include <glib.h>
|
||||
+#include <glib/gstdio.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+static void
|
||||
+test_read_line_long_terminator (void)
|
||||
+{
|
||||
+ guint8 *test_data = NULL;
|
||||
+ gsize test_data_len = 0;
|
||||
+ gint fd;
|
||||
+ gchar *filename = NULL;
|
||||
+ GIOChannel *channel = NULL;
|
||||
+ GError *local_error = NULL;
|
||||
+ gchar *line = NULL;
|
||||
+ gsize line_length, terminator_pos;
|
||||
+ const gchar *line_term;
|
||||
+ gint line_term_length;
|
||||
+ GIOStatus status;
|
||||
+
|
||||
+ /* Write out a temporary file containing 2047 bytes. This is enough to make it
|
||||
+ * near the length of the GString buffer when read back in. */
|
||||
+ fd = g_file_open_tmp ("glib-test-io-channel-XXXXXX", &filename, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+ g_close (fd, NULL);
|
||||
+ fd = -1;
|
||||
+
|
||||
+ test_data_len = 2047;
|
||||
+ test_data = g_malloc (test_data_len);
|
||||
+ memset (test_data, 'M', test_data_len);
|
||||
+ g_file_set_contents (filename, (const gchar *) test_data, test_data_len, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ /* Create the channel. */
|
||||
+ channel = g_io_channel_new_file (filename, "r", &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ /* Use a long line terminator so it could potentially over-read the end of the buffer. */
|
||||
+ g_io_channel_set_line_term (channel, "DEADBEEF", 8);
|
||||
+
|
||||
+ line_term = g_io_channel_get_line_term (channel, &line_term_length);
|
||||
+ g_assert_cmpstr (line_term, ==, "DEADBEEF");
|
||||
+ g_assert_cmpint (line_term_length, ==, 8);
|
||||
+
|
||||
+ g_io_channel_set_encoding (channel, "UTF-8", &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ status = g_io_channel_read_line (channel, &line, &line_length,
|
||||
+ &terminator_pos, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+ g_assert_cmpint (status, ==, G_IO_STATUS_NORMAL);
|
||||
+ g_assert_cmpuint (line_length, ==, 2047);
|
||||
+ g_assert_cmpuint (terminator_pos, ==, 2047);
|
||||
+ g_assert_cmpmem (line, line_length, test_data, test_data_len);
|
||||
+
|
||||
+ g_free (line);
|
||||
+ g_io_channel_unref (channel);
|
||||
+ g_free (test_data);
|
||||
+ g_unlink (filename);
|
||||
+ g_free (filename);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (int argc,
|
||||
+ char *argv[])
|
||||
+{
|
||||
+ g_test_init (&argc, &argv, NULL);
|
||||
+
|
||||
+ g_test_add_func ("/io-channel/read-line/long-terminator", test_read_line_long_terminator);
|
||||
+
|
||||
+ return g_test_run ();
|
||||
+}
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
Name: glib2
|
||||
Version: 2.56.4
|
||||
Release: 172%{?dist}
|
||||
Release: 173%{?dist}
|
||||
Summary: A library of handy utility functions
|
||||
|
||||
License: LGPLv2+
|
||||
@ -178,6 +178,9 @@ Patch37: CVE-2026-58014.patch
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/commit/8b72ad09c874ddff122b3e67b3470c5e2eab7690
|
||||
Patch38: CVE-2026-58015.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/commit/9f557746c52ae2a62fd5929f532b77024a18abe2
|
||||
Patch39: CVE-2026-58013.patch
|
||||
|
||||
%description
|
||||
GLib is the low-level core library that forms the basis for projects
|
||||
such as GTK+ and GNOME. It provides data structure handling for C,
|
||||
@ -378,6 +381,10 @@ make %{?_smp_mflags} check
|
||||
%{_datadir}/installed-tests
|
||||
|
||||
%changelog
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.56.4-173
|
||||
- Fix CVE-2026-58013: buffer over-read in GIOChannel with long terminators
|
||||
- Resolves: RHEL-212229
|
||||
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.56.4-172
|
||||
- Fix CVE-2026-58015: validate D-Bus DBUS_COOKIE_SHA1 cookie context
|
||||
- Resolves: RHEL-212254
|
||||
|
||||
Loading…
Reference in New Issue
Block a user