diff --git a/CVE-2026-58013.patch b/CVE-2026-58013.patch new file mode 100644 index 0000000..d90f25a --- /dev/null +++ b/CVE-2026-58013.patch @@ -0,0 +1,127 @@ +From bb5c37897584ca09c583161f908046edc2ec9d85 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +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 +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 ++#include ++#include ++ ++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 (); ++} diff --git a/glib2.spec b/glib2.spec index 6519af1..b239ac7 100644 --- a/glib2.spec +++ b/glib2.spec @@ -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 - 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 - 2.56.4-172 - Fix CVE-2026-58015: validate D-Bus DBUS_COOKIE_SHA1 cookie context - Resolves: RHEL-212254