import UBI glib2-2.68.4-19.el9_8.9
This commit is contained in:
parent
b7baf20903
commit
68914497a3
263
SOURCES/CVE-2026-15588.patch
Normal file
263
SOURCES/CVE-2026-15588.patch
Normal file
@ -0,0 +1,263 @@
|
||||
From 35d3b26e37a5f7f754ef8316729a5bdce2c18a26 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Sat, 4 Jul 2026 18:13:08 +0100
|
||||
Subject: [PATCH] gdbusauth: Limit length of lines read from client
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The client isn’t trusted at this point, and there was previously nothing
|
||||
limiting how long a line `GDBusAuth` would read. So an untrusted client
|
||||
could exhaust the server’s memory by sending anything except `\r\n`.
|
||||
|
||||
Fix that by applying a reasonably length limit when reading a line, and
|
||||
add a unit test.
|
||||
|
||||
Spotted by Gitee Codepecker Lab.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
Fixes: #3985
|
||||
---
|
||||
gio/gdbusauth.c | 44 +++++++++++++++
|
||||
gio/tests/gdbus-auth.c | 119 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 163 insertions(+)
|
||||
|
||||
diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c
|
||||
index cb84d0d64..72ffd0b4d 100644
|
||||
--- a/gio/gdbusauth.c
|
||||
+++ b/gio/gdbusauth.c
|
||||
@@ -262,6 +262,21 @@ find_mech_by_name (GDBusAuth *auth,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static size_t
|
||||
+get_longest_mechanism_name_length (GDBusAuth *auth)
|
||||
+{
|
||||
+ size_t len = 0;
|
||||
+
|
||||
+ for (GList *l = auth->priv->available_mechanisms; l != NULL; l = l->next)
|
||||
+ {
|
||||
+ Mechanism *m = l->data;
|
||||
+
|
||||
+ len = MAX (len, strlen (m->name));
|
||||
+ }
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
GDBusAuth *
|
||||
_g_dbus_auth_new (GIOStream *stream)
|
||||
{
|
||||
@@ -270,6 +285,20 @@ _g_dbus_auth_new (GIOStream *stream)
|
||||
NULL);
|
||||
}
|
||||
|
||||
+/* Arbitrarily chosen limit on the length of a DATA command payload, to prevent
|
||||
+ * unbounded reads from malicious clients.
|
||||
+ *
|
||||
+ * - The ANONYMOUS mechanism doesn’t use DATA.
|
||||
+ * - The EXTERNAL mechanism just uses it to transfer a decimal-encoded UID.
|
||||
+ * - The DBUS_COOKIE_SHA1 mechanism transfers a challenge and a SHA1 hash. The
|
||||
+ * hash is bounded in length, but the challenge is not, so could potentially
|
||||
+ * hit this limit. It doesn’t seem unreasonable to bound the challenge to
|
||||
+ * ~4KB though. GDBus itself generates a 16 byte challenge.
|
||||
+ *
|
||||
+ * See https://dbus.freedesktop.org/doc/dbus-specification.html#auth-command-data
|
||||
+ */
|
||||
+#define MAX_DATA_PAYLOAD_LENGTH_BYTES 4096
|
||||
+
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
/* like g_data_input_stream_read_line() but sets error if there's no content to read */
|
||||
static gchar *
|
||||
@@ -307,6 +336,7 @@ _my_g_data_input_stream_read_line (GDataInputStream *dis,
|
||||
*/
|
||||
static gchar *
|
||||
_my_g_input_stream_read_line_safe (GInputStream *i,
|
||||
+ size_t max_line_length,
|
||||
gsize *out_line_length,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -316,11 +346,22 @@ _my_g_input_stream_read_line_safe (GInputStream *i,
|
||||
gssize num_read;
|
||||
gboolean last_was_cr;
|
||||
|
||||
+ g_assert (max_line_length <= SIZE_MAX - 2);
|
||||
+
|
||||
str = g_string_new (NULL);
|
||||
|
||||
last_was_cr = FALSE;
|
||||
while (TRUE)
|
||||
{
|
||||
+ if (str->len >= max_line_length + 2 /* allow for \r\n */)
|
||||
+ {
|
||||
+ g_set_error_literal (error,
|
||||
+ G_IO_ERROR,
|
||||
+ G_IO_ERROR_FAILED,
|
||||
+ _("Malformed D-Bus authentication line"));
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
num_read = g_input_stream_read (i,
|
||||
&c,
|
||||
1,
|
||||
@@ -1075,6 +1116,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
|
||||
case SERVER_STATE_WAITING_FOR_AUTH:
|
||||
debug_print ("SERVER: WaitingForAuth");
|
||||
line = _my_g_input_stream_read_line_safe (g_io_stream_get_input_stream (auth->priv->stream),
|
||||
+ strlen ("AUTH ") + get_longest_mechanism_name_length (auth) + strlen (" ") + MAX_DATA_PAYLOAD_LENGTH_BYTES,
|
||||
&line_length,
|
||||
cancellable,
|
||||
error);
|
||||
@@ -1296,6 +1338,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
|
||||
case SERVER_STATE_WAITING_FOR_DATA:
|
||||
debug_print ("SERVER: WaitingForData");
|
||||
line = _my_g_input_stream_read_line_safe (g_io_stream_get_input_stream (auth->priv->stream),
|
||||
+ strlen ("DATA ") + MAX_DATA_PAYLOAD_LENGTH_BYTES,
|
||||
&line_length,
|
||||
cancellable,
|
||||
error);
|
||||
@@ -1338,6 +1381,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
|
||||
case SERVER_STATE_WAITING_FOR_BEGIN:
|
||||
debug_print ("SERVER: WaitingForBegin");
|
||||
line = _my_g_input_stream_read_line_safe (g_io_stream_get_input_stream (auth->priv->stream),
|
||||
+ MAX (strlen ("BEGIN"), strlen ("NEGOTIATE_UNIX_FD")),
|
||||
&line_length,
|
||||
cancellable,
|
||||
error);
|
||||
diff --git a/gio/tests/gdbus-auth.c b/gio/tests/gdbus-auth.c
|
||||
index 18288f36d..ed1894969 100644
|
||||
--- a/gio/tests/gdbus-auth.c
|
||||
+++ b/gio/tests/gdbus-auth.c
|
||||
@@ -278,6 +278,124 @@ temp_dbus_keyrings_teardown (void)
|
||||
g_unsetenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION");
|
||||
}
|
||||
|
||||
+static void
|
||||
+async_result_cb (GObject *obj,
|
||||
+ GAsyncResult *result,
|
||||
+ void *user_data)
|
||||
+{
|
||||
+ GAsyncResult **result_out = user_data;
|
||||
+
|
||||
+ g_assert (result_out != NULL);
|
||||
+ g_assert (*result_out == NULL);
|
||||
+
|
||||
+ *result_out = g_object_ref (result);
|
||||
+ g_main_context_wakeup (g_main_context_get_thread_default ());
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+server_new_connection_unexpected_cb (GDBusServer *server,
|
||||
+ GDBusConnection *connection,
|
||||
+ void *user_data)
|
||||
+{
|
||||
+ g_assert_not_reached ();
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_auth_server_read_limit (void)
|
||||
+{
|
||||
+ GDBusServer *server = NULL;
|
||||
+ unsigned long new_connection_id = 0;
|
||||
+ const char *server_address;
|
||||
+ GIOStream *client_stream = NULL;
|
||||
+ GOutputStream *client_output_stream;
|
||||
+ GInputStream *client_input_stream;
|
||||
+ GAsyncResult *result = NULL;
|
||||
+ char *write_buffer = NULL;
|
||||
+ char read_buffer[100];
|
||||
+ ssize_t read_len;
|
||||
+ size_t bytes_written;
|
||||
+ GError *local_error = NULL;
|
||||
+
|
||||
+ g_test_summary ("Test that GDBusServer limits the lengths of reads it does during auth from a client");
|
||||
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3985");
|
||||
+
|
||||
+ server = server_new_for_mechanism (NULL);
|
||||
+
|
||||
+ new_connection_id = g_signal_connect (server,
|
||||
+ "new-connection",
|
||||
+ G_CALLBACK (server_new_connection_unexpected_cb),
|
||||
+ NULL);
|
||||
+ server_address = g_dbus_server_get_client_address (server);
|
||||
+ g_dbus_server_start (server);
|
||||
+
|
||||
+ /* Start connecting as a client */
|
||||
+ g_dbus_address_get_stream (server_address, NULL, async_result_cb, &result);
|
||||
+
|
||||
+ while (result == NULL)
|
||||
+ g_main_context_iteration (NULL, TRUE);
|
||||
+
|
||||
+ client_stream = g_dbus_address_get_stream_finish (result, NULL, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+ g_clear_object (&result);
|
||||
+
|
||||
+ /* Send an over-long AUTH line, maliciously */
|
||||
+ client_output_stream = g_io_stream_get_output_stream (client_stream);
|
||||
+ client_input_stream = g_io_stream_get_input_stream (client_stream);
|
||||
+
|
||||
+ write_buffer = g_strdup_printf ("AUTH DBUS_COOKIE_SHA1 context%0*d 123 456\r\n", 5000, 0);
|
||||
+
|
||||
+ g_output_stream_write_all_async (client_output_stream,
|
||||
+ write_buffer,
|
||||
+ strlen (write_buffer),
|
||||
+ G_PRIORITY_DEFAULT,
|
||||
+ NULL,
|
||||
+ async_result_cb,
|
||||
+ &result);
|
||||
+
|
||||
+ while (result == NULL)
|
||||
+ g_main_context_iteration (NULL, TRUE);
|
||||
+
|
||||
+ g_output_stream_write_all_finish (client_output_stream, result, &bytes_written, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+ g_assert_cmpuint (bytes_written, ==, strlen (write_buffer));
|
||||
+ g_clear_object (&result);
|
||||
+
|
||||
+ g_clear_pointer (&write_buffer, g_free);
|
||||
+
|
||||
+ /* Authentication should have been rejected, so reading or writing the stream
|
||||
+ * should now fail. */
|
||||
+ read_len = g_input_stream_read (client_input_stream,
|
||||
+ read_buffer,
|
||||
+ sizeof (read_buffer),
|
||||
+ NULL,
|
||||
+ &local_error);
|
||||
+ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
|
||||
+ g_assert_cmpint (read_len, <, 0);
|
||||
+ g_clear_error (&local_error);
|
||||
+
|
||||
+ write_buffer = g_strdup_printf ("AUTH\r\n");
|
||||
+
|
||||
+ g_output_stream_write_all (client_output_stream,
|
||||
+ write_buffer,
|
||||
+ strlen (write_buffer),
|
||||
+ &bytes_written,
|
||||
+ NULL,
|
||||
+ &local_error);
|
||||
+ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
|
||||
+ g_assert_cmpuint (bytes_written, ==, 0);
|
||||
+ g_clear_error (&local_error);
|
||||
+
|
||||
+ g_clear_pointer (&write_buffer, g_free);
|
||||
+
|
||||
+ /* Cleanup */
|
||||
+ g_clear_object (&client_stream);
|
||||
+ g_dbus_server_stop (server);
|
||||
+
|
||||
+ g_clear_signal_handler (&new_connection_id, server);
|
||||
+ g_clear_object (&server);
|
||||
+}
|
||||
+
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
@@ -297,6 +415,7 @@ main (int argc,
|
||||
g_test_add_func ("/gdbus/auth/server/ANONYMOUS", auth_server_anonymous);
|
||||
g_test_add_func ("/gdbus/auth/server/EXTERNAL", auth_server_external);
|
||||
g_test_add_func ("/gdbus/auth/server/DBUS_COOKIE_SHA1", auth_server_dbus_cookie_sha1);
|
||||
+ g_test_add_func ("/gdbus/auth/server/read-limit", test_auth_server_read_limit);
|
||||
|
||||
/* TODO: we currently don't have tests for
|
||||
*
|
||||
133
SOURCES/CVE-2026-58010.patch
Normal file
133
SOURCES/CVE-2026-58010.patch
Normal file
@ -0,0 +1,133 @@
|
||||
From 13dfcc636cdf78b22e9a207553e42537661719db Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Sun, 29 Mar 2026 19:10:41 +0100
|
||||
Subject: [PATCH 1/2] gvariant: Fix an off-by-one error in an offset comparison
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This allows a single byte out-of-bounds read off the end of the
|
||||
(potentially untrusted) byte array backing a `GVariant` when it’s
|
||||
being checked for normal form.
|
||||
|
||||
I can’t see how this could practically be exploited, but it’s certainly
|
||||
a security bug as the `GVariant` normal form checking code is supposed
|
||||
to be robust to malicious inputs.
|
||||
|
||||
Spotted by linhlhq as #YWH-PGM9867-190, and fix and reproducer provided
|
||||
by them too, thanks. Confirmed and turned into a unit test by me.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
|
||||
Fixes: #3915
|
||||
---
|
||||
glib/gvariant-serialiser.c | 2 +-
|
||||
glib/tests/gvariant.c | 48 ++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 49 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index 0c2b119bc..7746ec4d0 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -1241,7 +1241,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
|
||||
|
||||
while (offset & alignment)
|
||||
{
|
||||
- if (offset > value.size || value.data[offset] != '\0')
|
||||
+ if (offset >= value.size || value.data[offset] != '\0')
|
||||
return FALSE;
|
||||
offset++;
|
||||
}
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index fa8b05a20..6bdea5b74 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -5517,6 +5517,52 @@ test_normal_checking_tuple_offsets5 (void)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
+/* This is a regression test that looping over the padding bytes in a short
|
||||
+ * (non-normal) tuple doesn’t overflow the input data.
|
||||
+ *
|
||||
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/3915 */
|
||||
+static void
|
||||
+test_normal_checking_tuple_offsets6 (void)
|
||||
+{
|
||||
+ /*
|
||||
+ * Type: (ynqiuxthdsog) — 12 members, first member 'y' (byte) has
|
||||
+ * alignment 0, second 'n' (int16) has alignment 1.
|
||||
+ * With 1 byte of data (0x28), after reading the first byte member,
|
||||
+ * offset=1, alignment check for 'n' requires offset to be even,
|
||||
+ * so the while loop checks value.data[1] — but size is only 1.
|
||||
+ *
|
||||
+ * Use heap allocation via GBytes so ASan reports heap-buffer-overflow.
|
||||
+ */
|
||||
+ uint8_t *heap_data = NULL;
|
||||
+ GBytes *bytes = NULL;
|
||||
+ const GVariantType *data_type = G_VARIANT_TYPE ("(ynqiuxthdsog)");
|
||||
+ GVariant *variant = NULL;
|
||||
+ GVariant *normal_variant = NULL;
|
||||
+ GVariant *expected = NULL;
|
||||
+
|
||||
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3915");
|
||||
+
|
||||
+ heap_data = g_malloc (1);
|
||||
+ heap_data[0] = 0x28;
|
||||
+ bytes = g_bytes_new_take (heap_data, 1);
|
||||
+
|
||||
+ variant = g_variant_new_from_bytes (data_type, bytes, FALSE);
|
||||
+ g_assert_nonnull (variant);
|
||||
+
|
||||
+ g_assert_false (g_variant_is_normal_form (variant));
|
||||
+
|
||||
+ normal_variant = g_variant_get_normal_form (variant);
|
||||
+ g_assert_nonnull (normal_variant);
|
||||
+
|
||||
+ expected = g_variant_new_parsed ("(byte 0x28, int16 0, uint16 0, 0, uint32 0, int64 0, uint64 0, handle 0, 0.0, '', objectpath '/', signature '')");
|
||||
+ g_assert_cmpvariant (expected, variant);
|
||||
+ g_assert_cmpvariant (expected, normal_variant);
|
||||
+
|
||||
+ g_variant_unref (expected);
|
||||
+ g_variant_unref (normal_variant);
|
||||
+ g_variant_unref (variant);
|
||||
+}
|
||||
+
|
||||
/* Test that an otherwise-valid serialised GVariant is considered non-normal if
|
||||
* its offset table entries are too wide.
|
||||
*
|
||||
@@ -5769,6 +5815,8 @@ main (int argc, char **argv)
|
||||
test_normal_checking_tuple_offsets4);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets5",
|
||||
test_normal_checking_tuple_offsets5);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets6",
|
||||
+ test_normal_checking_tuple_offsets6);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
|
||||
test_normal_checking_tuple_offsets_minimal_sized);
|
||||
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
|
||||
|
||||
From c3897156fdc595ed2c627781e7b4024eb593e3e0 Mon Sep 17 00:00:00 2001
|
||||
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
|
||||
Date: Mon, 20 Jul 2026 08:15:13 +0000
|
||||
Subject: [PATCH 2/2] Fix: use guint8 instead of uint8_t for compatibility with
|
||||
older glib
|
||||
|
||||
The test file gvariant.c does not include <stdint.h>, so uint8_t is not
|
||||
available. Use guint8 (GLib's equivalent type) which is always available
|
||||
through <glib.h>.
|
||||
---
|
||||
glib/tests/gvariant.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index 6bdea5b74..5546d72dc 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -5533,7 +5533,7 @@ test_normal_checking_tuple_offsets6 (void)
|
||||
*
|
||||
* Use heap allocation via GBytes so ASan reports heap-buffer-overflow.
|
||||
*/
|
||||
- uint8_t *heap_data = NULL;
|
||||
+ guint8 *heap_data = NULL;
|
||||
GBytes *bytes = NULL;
|
||||
const GVariantType *data_type = G_VARIANT_TYPE ("(ynqiuxthdsog)");
|
||||
GVariant *variant = NULL;
|
||||
122
SOURCES/CVE-2026-58011.patch
Normal file
122
SOURCES/CVE-2026-58011.patch
Normal file
@ -0,0 +1,122 @@
|
||||
From b211d727cfe971040409c2d73768a60a901b2dc7 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Sun, 29 Mar 2026 23:19:47 +0100
|
||||
Subject: [PATCH 1/2] gdatetime: Factor out a couple of magic constants
|
||||
|
||||
This introduces no functional changes, it just makes the code a little
|
||||
clearer.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
---
|
||||
glib/gdatetime.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/glib/gdatetime.c b/glib/gdatetime.c
|
||||
index ffdeddd81..4cbc6835f 100644
|
||||
--- a/glib/gdatetime.c
|
||||
+++ b/glib/gdatetime.c
|
||||
@@ -130,7 +130,7 @@ struct _GDateTime
|
||||
gint interval;
|
||||
|
||||
/* 1 is 0001-01-01 in Proleptic Gregorian */
|
||||
- gint32 days;
|
||||
+ gint32 days; /* in range [MIN_DAYS, MAX_DAYS] */
|
||||
|
||||
gint ref_count; /* (atomic) */
|
||||
};
|
||||
@@ -172,6 +172,9 @@ struct _GDateTime
|
||||
#define JULIAN_YEAR(d) ((d)->julian / 365.25)
|
||||
#define DAYS_PER_PERIOD (G_GINT64_CONSTANT (2914695))
|
||||
|
||||
+#define MIN_DAYS 1 /* the days count for 0001-01-01 in Proleptic Gregorian */
|
||||
+#define MAX_DAYS 3652059 /* the days count for 9999-12-31 in Proleptic Gregorian */
|
||||
+
|
||||
static const guint16 days_in_months[2][13] =
|
||||
{
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
@@ -781,7 +784,7 @@ g_date_time_from_instant (GTimeZone *tz,
|
||||
datetime->days = instant / USEC_PER_DAY;
|
||||
datetime->usec = instant % USEC_PER_DAY;
|
||||
|
||||
- if (datetime->days < 1 || 3652059 < datetime->days)
|
||||
+ if (datetime->days < MIN_DAYS || datetime->days > MAX_DAYS)
|
||||
{
|
||||
g_date_time_unref (datetime);
|
||||
datetime = NULL;
|
||||
@@ -817,7 +820,7 @@ g_date_time_deal_with_date_change (GDateTime *datetime)
|
||||
gint64 full_time;
|
||||
gint64 usec;
|
||||
|
||||
- if (datetime->days < 1 || datetime->days > 3652059)
|
||||
+ if (datetime->days < MIN_DAYS || datetime->days > MAX_DAYS)
|
||||
return FALSE;
|
||||
|
||||
was_dst = g_time_zone_is_dst (datetime->tz, datetime->interval);
|
||||
|
||||
From fe5a23ec62238a38f86f4fb4362bc62529a20a03 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Sun, 29 Mar 2026 23:46:17 +0100
|
||||
Subject: [PATCH 2/2] gdatetime: Add missing range validation to
|
||||
g_date_time_add_full()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Otherwise it’s possible to create a non-`NULL` but invalid `GDateTime`,
|
||||
which breaks all kinds of internal assumptions.
|
||||
|
||||
Spotted by linhlhq as #YWH-PGM9867-191. Thanks to them for providing a
|
||||
suggested fix and a test case, which I have adapted and validated.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
|
||||
Fixes: #3917
|
||||
---
|
||||
glib/gdatetime.c | 4 +++-
|
||||
glib/tests/gdatetime.c | 18 ++++++++++++++++++
|
||||
2 files changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/gdatetime.c b/glib/gdatetime.c
|
||||
index 4cbc6835f..a6b3919f5 100644
|
||||
--- a/glib/gdatetime.c
|
||||
+++ b/glib/gdatetime.c
|
||||
@@ -2022,7 +2022,9 @@ g_date_time_add_full (GDateTime *datetime,
|
||||
new->days = full_time / USEC_PER_DAY;
|
||||
new->usec = full_time % USEC_PER_DAY;
|
||||
|
||||
- /* XXX validate */
|
||||
+ /* Validate it’s still in the range 0001-01-01 to 9999-12-31 */
|
||||
+ if (new->days < MIN_DAYS || new->days > MAX_DAYS)
|
||||
+ g_clear_pointer (&new, g_date_time_unref);
|
||||
|
||||
return new;
|
||||
}
|
||||
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
|
||||
index 7512389e0..32f7e54e7 100644
|
||||
--- a/glib/tests/gdatetime.c
|
||||
+++ b/glib/tests/gdatetime.c
|
||||
@@ -1098,6 +1098,24 @@ test_GDateTime_add_full (void)
|
||||
TEST_ADD_FULL (2010, 8, 25, 22, 45, 0,
|
||||
0, 1, 6, 1, 25, 0,
|
||||
2010, 10, 2, 0, 10, 0);
|
||||
+
|
||||
+#define TEST_ADD_FULL_ERROR(y,m,d,h,mi,s,ay,am,ad,ah,ami,as) G_STMT_START { \
|
||||
+ GDateTime *dt; \
|
||||
+ dt = g_date_time_new_utc (y, m, d, h, mi, s); \
|
||||
+ g_assert_null (g_date_time_add_full (dt, ay, am, ad, ah, ami, as)); \
|
||||
+ g_date_time_unref (dt); \
|
||||
+} G_STMT_END
|
||||
+
|
||||
+ TEST_ADD_FULL_ERROR ( 1, 12, 1, 0, 0, 0,
|
||||
+ -1, 0, 0, 0, 0, 0);
|
||||
+ TEST_ADD_FULL_ERROR ( 1, 12, 1, 0, 0, 0,
|
||||
+ 10000, 0, 0, 0, 0, 0);
|
||||
+ TEST_ADD_FULL_ERROR ( 9999, 12, 1, 0, 0, 0,
|
||||
+ -10000, 0, 0, 0, 0, 0);
|
||||
+ TEST_ADD_FULL_ERROR ( 1, 12, 1, 0, 0, 0,
|
||||
+ 0, 0, 3660001, 0, 0, 0);
|
||||
+ TEST_ADD_FULL_ERROR ( 9999, 12, 1, 0, 0, 0,
|
||||
+ 0, 0, -3660001, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
283
SOURCES/CVE-2026-58012.patch
Normal file
283
SOURCES/CVE-2026-58012.patch
Normal file
@ -0,0 +1,283 @@
|
||||
From 49bd6b7eb4d7c4d4780e86ee67435cfc263f9993 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Tue, 31 Mar 2026 16:13:57 +0100
|
||||
Subject: [PATCH 1/2] gregex: Fix case changing substitutions with G_REGEX_RAW
|
||||
|
||||
In `G_REGEX_RAW` mode, the input string is treated as a byte array
|
||||
(basically ASCII) rather than a unichar array. Accordingly, the case
|
||||
changing code for substitutions needs to operate on bytes with
|
||||
`G_REGEX_RAW`, rather than operating on unichars.
|
||||
|
||||
This fixes a potential buffer overflow when trying to do a case change
|
||||
on a match of a set of bytes which are a truncated multi-byte UTF-8
|
||||
encoding at the end of the input buffer.
|
||||
|
||||
Spotted by linhlhq as #YWH-PGM9867-193. I adapted their reproducer as
|
||||
the unit test, but implemented the fix in `gregex.c` independently.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
|
||||
Fixes: #3918
|
||||
---
|
||||
glib/gregex.c | 59 ++++++++++++++++++++++++++++++++++------------
|
||||
glib/tests/regex.c | 53 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 97 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/glib/gregex.c b/glib/gregex.c
|
||||
index 5e6ddfb46..7cd8106ae 100644
|
||||
--- a/glib/gregex.c
|
||||
+++ b/glib/gregex.c
|
||||
@@ -2647,19 +2647,25 @@ split_replacement (const gchar *replacement,
|
||||
return g_list_reverse (list);
|
||||
}
|
||||
|
||||
-/* Change the case of c based on change_case. */
|
||||
-#define CHANGE_CASE(c, change_case) \
|
||||
+/* Change the case of c based on change_case.
|
||||
+ * g_ascii_to*() will happily pass through non-ASCII bytes unchanged. */
|
||||
+#define UTF8_CHANGE_CASE(c, change_case) \
|
||||
(((change_case) & CHANGE_CASE_LOWER_MASK) ? \
|
||||
g_unichar_tolower (c) : \
|
||||
g_unichar_toupper (c))
|
||||
+#define RAW_CHANGE_CASE(c, change_case) \
|
||||
+ (((change_case) & CHANGE_CASE_LOWER_MASK) ? \
|
||||
+ g_ascii_tolower (c) : \
|
||||
+ g_ascii_toupper (c))
|
||||
|
||||
+/* If @text_is_raw is set, @text might not be valid UTF-8 (but will be
|
||||
+ * nul-terminated). */
|
||||
static void
|
||||
string_append (GString *string,
|
||||
const gchar *text,
|
||||
+ gboolean text_is_raw,
|
||||
ChangeCase *change_case)
|
||||
{
|
||||
- gunichar c;
|
||||
-
|
||||
if (text[0] == '\0')
|
||||
return;
|
||||
|
||||
@@ -2669,22 +2675,44 @@ string_append (GString *string,
|
||||
}
|
||||
else if (*change_case & CHANGE_CASE_SINGLE_MASK)
|
||||
{
|
||||
- c = g_utf8_get_char (text);
|
||||
- g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
|
||||
- g_string_append (string, g_utf8_next_char (text));
|
||||
+ if (!text_is_raw)
|
||||
+ {
|
||||
+ gunichar c = g_utf8_get_char (text);
|
||||
+ g_string_append_unichar (string, UTF8_CHANGE_CASE (c, *change_case));
|
||||
+ g_string_append (string, g_utf8_next_char (text));
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ g_string_append_c (string, RAW_CHANGE_CASE (text[0], *change_case));
|
||||
+ g_string_append (string, text + 1);
|
||||
+ }
|
||||
+
|
||||
*change_case = CHANGE_CASE_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
- while (*text != '\0')
|
||||
+ if (!text_is_raw)
|
||||
{
|
||||
- c = g_utf8_get_char (text);
|
||||
- g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
|
||||
- text = g_utf8_next_char (text);
|
||||
+ while (*text != '\0')
|
||||
+ {
|
||||
+ gunichar c = g_utf8_get_char (text);
|
||||
+ g_string_append_unichar (string, UTF8_CHANGE_CASE (c, *change_case));
|
||||
+ text = g_utf8_next_char (text);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ while (*text != '\0')
|
||||
+ {
|
||||
+ char c = *text;
|
||||
+ g_string_append_c (string, RAW_CHANGE_CASE (c, *change_case));
|
||||
+ text++;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+/* @match_info is (nullable) */
|
||||
static gboolean
|
||||
interpolate_replacement (const GMatchInfo *match_info,
|
||||
GString *result,
|
||||
@@ -2694,6 +2722,7 @@ interpolate_replacement (const GMatchInfo *match_info,
|
||||
InterpolationData *idata;
|
||||
gchar *match;
|
||||
ChangeCase change_case = CHANGE_CASE_NONE;
|
||||
+ gboolean is_raw = (match_info != NULL && (match_info->regex->compile_opts & G_REGEX_RAW));
|
||||
|
||||
for (list = data; list; list = list->next)
|
||||
{
|
||||
@@ -2701,10 +2730,10 @@ interpolate_replacement (const GMatchInfo *match_info,
|
||||
switch (idata->type)
|
||||
{
|
||||
case REPL_TYPE_STRING:
|
||||
- string_append (result, idata->text, &change_case);
|
||||
+ string_append (result, idata->text, is_raw, &change_case);
|
||||
break;
|
||||
case REPL_TYPE_CHARACTER:
|
||||
- g_string_append_c (result, CHANGE_CASE (idata->c, change_case));
|
||||
+ g_string_append_c (result, UTF8_CHANGE_CASE (idata->c, change_case));
|
||||
if (change_case & CHANGE_CASE_SINGLE_MASK)
|
||||
change_case = CHANGE_CASE_NONE;
|
||||
break;
|
||||
@@ -2712,7 +2741,7 @@ interpolate_replacement (const GMatchInfo *match_info,
|
||||
match = g_match_info_fetch (match_info, idata->num);
|
||||
if (match)
|
||||
{
|
||||
- string_append (result, match, &change_case);
|
||||
+ string_append (result, match, is_raw, &change_case);
|
||||
g_free (match);
|
||||
}
|
||||
break;
|
||||
@@ -2720,7 +2749,7 @@ interpolate_replacement (const GMatchInfo *match_info,
|
||||
match = g_match_info_fetch_named (match_info, idata->text);
|
||||
if (match)
|
||||
{
|
||||
- string_append (result, match, &change_case);
|
||||
+ string_append (result, match, is_raw, &change_case);
|
||||
g_free (match);
|
||||
}
|
||||
break;
|
||||
diff --git a/glib/tests/regex.c b/glib/tests/regex.c
|
||||
index c57bd8cdc..e31cf50ca 100644
|
||||
--- a/glib/tests/regex.c
|
||||
+++ b/glib/tests/regex.c
|
||||
@@ -2187,6 +2187,58 @@ pcre_ge (guint64 major, guint64 minor)
|
||||
return (pcre_major > major) || (pcre_major == major && pcre_minor >= minor);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_replace_raw_change_case (void)
|
||||
+{
|
||||
+ GError *local_error = NULL;
|
||||
+ GRegex *regex = NULL;
|
||||
+
|
||||
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3918");
|
||||
+ g_test_summary ("Test that case changes as part of a replacement are handled correctly in G_REGEX_RAW mode");
|
||||
+
|
||||
+ /*
|
||||
+ * Match a multi-byte sequence in RAW mode. The pattern matches
|
||||
+ * exactly 2 bytes. The subject contains a 4-byte UTF-8 lead (0xF4)
|
||||
+ * followed by only one continuation byte, then NUL.
|
||||
+ *
|
||||
+ * The matched substring will be "\xf4\x80" (2 bytes, heap-allocated
|
||||
+ * as 3-byte buffer with NUL). If the code regresses and tries to handle
|
||||
+ * the replacement as UTF-8 then g_utf8_get_char() would see 0xF4 and try
|
||||
+ * to read 4 bytes, going 1 byte past the NUL into OOB territory.
|
||||
+ */
|
||||
+ regex = g_regex_new ("..", G_REGEX_RAW, 0, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ /*
|
||||
+ * Build a subject string with truncated UTF-8.
|
||||
+ * \xF4 = 4-byte UTF-8 lead byte
|
||||
+ * \x80 = continuation byte
|
||||
+ * No 3rd/4th continuation bytes — the match is only 2 bytes.
|
||||
+ *
|
||||
+ * \U\0 = uppercase the entire match → triggers string_append()
|
||||
+ * with case change on the 2-byte non-UTF-8 match.
|
||||
+ */
|
||||
+ char subject[] = "\xf4\x80";
|
||||
+ char *result = g_regex_replace (regex, subject, -1, 0, "\\U\\0", 0, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ g_clear_pointer (&result, g_free);
|
||||
+ g_clear_pointer (®ex, g_regex_unref);
|
||||
+
|
||||
+ /*
|
||||
+ * Second variant: single-char case change \u with \0 backreference.
|
||||
+ */
|
||||
+ regex = g_regex_new (".", G_REGEX_RAW, 0, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ char subject2[] = "\xe6\xb0"; /* 3-byte UTF-8 lead, only 2 bytes */
|
||||
+ result = g_regex_replace (regex, subject2, -1, 0, "\\u\\0", 0, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ g_clear_pointer (&result, g_free);
|
||||
+ g_clear_pointer (®ex, g_regex_unref);
|
||||
+}
|
||||
+
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -2206,6 +2258,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/regex/multiline", test_multiline);
|
||||
g_test_add_func ("/regex/explicit-crlf", test_explicit_crlf);
|
||||
g_test_add_func ("/regex/max-lookbehind", test_max_lookbehind);
|
||||
+ g_test_add_func ("/regex/replace-raw-change-case", test_replace_raw_change_case);
|
||||
|
||||
/* TEST_NEW(pattern, compile_opts, match_opts) */
|
||||
TEST_NEW("[A-Z]+", G_REGEX_CASELESS | G_REGEX_EXTENDED | G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTBOL | G_REGEX_MATCH_PARTIAL);
|
||||
|
||||
From 92867c6639018e82af51faff3cd5de967bd93dab Mon Sep 17 00:00:00 2001
|
||||
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
|
||||
Date: Mon, 20 Jul 2026 07:48:43 +0000
|
||||
Subject: [PATCH 2/2] gdbusauthmechanismsha1: Add missing #include <stdint.h>
|
||||
for uint8_t
|
||||
|
||||
The validate_cookie_context() function uses uint8_t which requires
|
||||
stdint.h to be included. Without this include, the build fails with
|
||||
'uint8_t' undeclared error.
|
||||
|
||||
Also fix ISO C90 mixed declarations in regex test to comply with
|
||||
-Werror=declaration-after-statement.
|
||||
---
|
||||
gio/gdbusauthmechanismsha1.c | 1 +
|
||||
glib/tests/regex.c | 7 ++++---
|
||||
2 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
|
||||
index 095a6663e..f9ed66b6b 100644
|
||||
--- a/gio/gdbusauthmechanismsha1.c
|
||||
+++ b/gio/gdbusauthmechanismsha1.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
+#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
diff --git a/glib/tests/regex.c b/glib/tests/regex.c
|
||||
index e31cf50ca..1a8d30ab3 100644
|
||||
--- a/glib/tests/regex.c
|
||||
+++ b/glib/tests/regex.c
|
||||
@@ -2192,6 +2192,9 @@ test_replace_raw_change_case (void)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
GRegex *regex = NULL;
|
||||
+ char subject[] = "\xf4\x80";
|
||||
+ char subject2[] = "\xe6\xb0"; /* 3-byte UTF-8 lead, only 2 bytes */
|
||||
+ char *result = NULL;
|
||||
|
||||
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3918");
|
||||
g_test_summary ("Test that case changes as part of a replacement are handled correctly in G_REGEX_RAW mode");
|
||||
@@ -2218,8 +2221,7 @@ test_replace_raw_change_case (void)
|
||||
* \U\0 = uppercase the entire match → triggers string_append()
|
||||
* with case change on the 2-byte non-UTF-8 match.
|
||||
*/
|
||||
- char subject[] = "\xf4\x80";
|
||||
- char *result = g_regex_replace (regex, subject, -1, 0, "\\U\\0", 0, &local_error);
|
||||
+ result = g_regex_replace (regex, subject, -1, 0, "\\U\\0", 0, &local_error);
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
g_clear_pointer (&result, g_free);
|
||||
@@ -2231,7 +2233,6 @@ test_replace_raw_change_case (void)
|
||||
regex = g_regex_new (".", G_REGEX_RAW, 0, &local_error);
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
- char subject2[] = "\xe6\xb0"; /* 3-byte UTF-8 lead, only 2 bytes */
|
||||
result = g_regex_replace (regex, subject2, -1, 0, "\\u\\0", 0, &local_error);
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
170
SOURCES/CVE-2026-58013.patch
Normal file
170
SOURCES/CVE-2026-58013.patch
Normal file
@ -0,0 +1,170 @@
|
||||
From 6f410cf0d43f8b7a03f5c504ca9b53c75266a21d Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Tue, 28 Apr 2026 16:45:14 +0100
|
||||
Subject: [PATCH 1/2] 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 | 60 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 62 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/giochannel.c b/glib/giochannel.c
|
||||
index e93c4b458..66b68e645 100644
|
||||
--- a/glib/giochannel.c
|
||||
+++ b/glib/giochannel.c
|
||||
@@ -1830,7 +1830,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
|
||||
index 4a1b10876..c619fb00f 100644
|
||||
--- a/glib/tests/io-channel.c
|
||||
+++ b/glib/tests/io-channel.c
|
||||
@@ -69,6 +69,65 @@ test_read_line_embedded_nuls (void)
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_read_line_long_terminator (void)
|
||||
+{
|
||||
+ uint8_t *test_data = NULL;
|
||||
+ size_t test_data_len = 0;
|
||||
+ int fd;
|
||||
+ char *filename = NULL;
|
||||
+ GIOChannel *channel = NULL;
|
||||
+ GError *local_error = NULL;
|
||||
+ char *line = NULL;
|
||||
+ size_t line_length, terminator_pos;
|
||||
+ const char *line_term;
|
||||
+ int line_term_length;
|
||||
+ GIOStatus status;
|
||||
+
|
||||
+ g_test_summary ("Test that reading a line when using a long terminator doesn’t over-read the buffer.");
|
||||
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/work_items/3925");
|
||||
+
|
||||
+ /* 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 (g_steal_fd (&fd), NULL);
|
||||
+
|
||||
+ 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[])
|
||||
@@ -76,6 +135,7 @@ main (int argc,
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/io-channel/read-line/embedded-nuls", test_read_line_embedded_nuls);
|
||||
+ g_test_add_func ("/io-channel/read-line/long-terminator", test_read_line_long_terminator);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
From 9ddd99126dd21d53c874aa801bcee346ff09ca8d Mon Sep 17 00:00:00 2001
|
||||
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
|
||||
Date: Mon, 20 Jul 2026 07:12:52 +0000
|
||||
Subject: [PATCH 2/2] Adapt test to use GLib types instead of C standard types
|
||||
for compatibility with GLib 2.68.4
|
||||
|
||||
---
|
||||
glib/tests/io-channel.c | 19 ++++++++++---------
|
||||
1 file changed, 10 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/glib/tests/io-channel.c b/glib/tests/io-channel.c
|
||||
index c619fb00f..afcea93f0 100644
|
||||
--- a/glib/tests/io-channel.c
|
||||
+++ b/glib/tests/io-channel.c
|
||||
@@ -72,16 +72,16 @@ test_read_line_embedded_nuls (void)
|
||||
static void
|
||||
test_read_line_long_terminator (void)
|
||||
{
|
||||
- uint8_t *test_data = NULL;
|
||||
- size_t test_data_len = 0;
|
||||
- int fd;
|
||||
- char *filename = NULL;
|
||||
+ guint8 *test_data = NULL;
|
||||
+ gsize test_data_len = 0;
|
||||
+ gint fd;
|
||||
+ gchar *filename = NULL;
|
||||
GIOChannel *channel = NULL;
|
||||
GError *local_error = NULL;
|
||||
- char *line = NULL;
|
||||
- size_t line_length, terminator_pos;
|
||||
- const char *line_term;
|
||||
- int line_term_length;
|
||||
+ gchar *line = NULL;
|
||||
+ gsize line_length, terminator_pos;
|
||||
+ const gchar *line_term;
|
||||
+ gint line_term_length;
|
||||
GIOStatus status;
|
||||
|
||||
g_test_summary ("Test that reading a line when using a long terminator doesn’t over-read the buffer.");
|
||||
@@ -91,7 +91,8 @@ test_read_line_long_terminator (void)
|
||||
* 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 (g_steal_fd (&fd), NULL);
|
||||
+ g_close (fd, NULL);
|
||||
+ fd = -1;
|
||||
|
||||
test_data_len = 2047;
|
||||
test_data = g_malloc (test_data_len);
|
||||
101
SOURCES/CVE-2026-58014.patch
Normal file
101
SOURCES/CVE-2026-58014.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From 98ca9d79b8e51c820ad93aea2540a20e015db0ba Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@gnome.org>
|
||||
Date: Sat, 11 Apr 2026 14:42:57 +0100
|
||||
Subject: [PATCH] gkeyfile: Fix a one-byte heap under-read with
|
||||
g_key_file_get_locale_string_list()
|
||||
|
||||
If this method was called on a key file key which has an empty value,
|
||||
`len == 0` and this leads to a one-byte under-read off the start of the
|
||||
key file buffer.
|
||||
|
||||
Spotted by linhlhq as #YWH-PGM9867-200. The suggested fix is theirs, and
|
||||
the unit test is adapted from their report. I added the fuzzing test.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
|
||||
Fixes: #3930
|
||||
---
|
||||
fuzzing/fuzz_key.c | 9 +++++++++
|
||||
glib/gkeyfile.c | 2 +-
|
||||
glib/tests/keyfile.c | 23 +++++++++++++++++++++++
|
||||
3 files changed, 33 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/fuzzing/fuzz_key.c b/fuzzing/fuzz_key.c
|
||||
index 9f1f9187e..285bad26f 100644
|
||||
--- a/fuzzing/fuzz_key.c
|
||||
+++ b/fuzzing/fuzz_key.c
|
||||
@@ -6,11 +6,20 @@ test_parse (const gchar *data,
|
||||
GKeyFileFlags flags)
|
||||
{
|
||||
GKeyFile *key = NULL;
|
||||
+ char *comment = NULL;
|
||||
+ char **list = NULL;
|
||||
|
||||
key = g_key_file_new ();
|
||||
g_key_file_load_from_data (key, (const gchar*) data, size, G_KEY_FILE_NONE,
|
||||
NULL);
|
||||
|
||||
+ /* Also try some additional parsing and see if it crashes */
|
||||
+ comment = g_key_file_get_comment (key, "group", "key", NULL);
|
||||
+ g_free (comment);
|
||||
+
|
||||
+ list = g_key_file_get_locale_string_list (key, "group", "key", "de", NULL, NULL);
|
||||
+ g_strfreev (list);
|
||||
+
|
||||
g_key_file_free (key);
|
||||
}
|
||||
|
||||
diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c
|
||||
index 0b58edb3f..aae03afb0 100644
|
||||
--- a/glib/gkeyfile.c
|
||||
+++ b/glib/gkeyfile.c
|
||||
@@ -2409,7 +2409,7 @@ g_key_file_get_locale_string_list (GKeyFile *key_file,
|
||||
}
|
||||
|
||||
len = strlen (value);
|
||||
- if (value[len - 1] == key_file->list_separator)
|
||||
+ if (len > 0 && value[len - 1] == key_file->list_separator)
|
||||
value[len - 1] = '\0';
|
||||
|
||||
list_separator[0] = key_file->list_separator;
|
||||
diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c
|
||||
index 975ef8167..215c973a5 100644
|
||||
--- a/glib/tests/keyfile.c
|
||||
+++ b/glib/tests/keyfile.c
|
||||
@@ -800,6 +800,28 @@ test_locale_string_multiple_loads (void)
|
||||
g_free (old_locale);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_locale_string_empty (void)
|
||||
+{
|
||||
+ GKeyFile *keyfile = NULL;
|
||||
+ GError *local_error = NULL;
|
||||
+ const char *data =
|
||||
+ "[valid]\n"
|
||||
+ "key1=\n";
|
||||
+
|
||||
+ g_test_summary ("Check that loading an empty translatable string works");
|
||||
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3930");
|
||||
+
|
||||
+ keyfile = g_key_file_new ();
|
||||
+
|
||||
+ g_key_file_load_from_data (keyfile, data, -1, G_KEY_FILE_NONE, &local_error);
|
||||
+ g_assert_no_error (local_error);
|
||||
+
|
||||
+ check_locale_string_list_value (keyfile, "valid", "key1", NULL, NULL);
|
||||
+
|
||||
+ g_key_file_free (keyfile);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
test_lists (void)
|
||||
{
|
||||
@@ -1834,6 +1856,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/keyfile/number", test_number);
|
||||
g_test_add_func ("/keyfile/locale-string", test_locale_string);
|
||||
g_test_add_func ("/keyfile/locale-string/multiple-loads", test_locale_string_multiple_loads);
|
||||
+ g_test_add_func ("/keyfile/locale-string/empty", test_locale_string_empty);
|
||||
g_test_add_func ("/keyfile/lists", test_lists);
|
||||
g_test_add_func ("/keyfile/lists-set-get", test_lists_set_get);
|
||||
g_test_add_func ("/keyfile/group-remove", test_group_remove);
|
||||
105
SOURCES/CVE-2026-58015.patch
Normal file
105
SOURCES/CVE-2026-58015.patch
Normal file
@ -0,0 +1,105 @@
|
||||
From 80e5a24e239371a4d3e1d1a13273fd7a2e7df2d2 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/2] 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.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
||||
|
||||
Fixes: #3931
|
||||
---
|
||||
gio/gdbusauthmechanismsha1.c | 36 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 36 insertions(+)
|
||||
|
||||
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
|
||||
index 095a6663e..7f314daea 100644
|
||||
--- a/gio/gdbusauthmechanismsha1.c
|
||||
+++ b/gio/gdbusauthmechanismsha1.c
|
||||
@@ -1160,6 +1160,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,
|
||||
@@ -1194,6 +1222,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')
|
||||
{
|
||||
|
||||
From e0ccc69820c05ec3e7b54d2d7aa101674d54a9ec Mon Sep 17 00:00:00 2001
|
||||
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
|
||||
Date: Mon, 20 Jul 2026 06:18:14 +0000
|
||||
Subject: [PATCH 2/2] Fix compilation: use guint8 instead of uint8_t
|
||||
|
||||
The upstream commit used uint8_t which requires <stdint.h>, but in the
|
||||
older GLib 2.68 codebase this header is not included. Use guint8 instead
|
||||
which is GLib's own equivalent type and is already available through
|
||||
the included GLib headers.
|
||||
---
|
||||
gio/gdbusauthmechanismsha1.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
|
||||
index 7f314daea..60a5475bf 100644
|
||||
--- a/gio/gdbusauthmechanismsha1.c
|
||||
+++ b/gio/gdbusauthmechanismsha1.c
|
||||
@@ -1174,7 +1174,7 @@ validate_cookie_context (const char *cookie_context)
|
||||
|
||||
for (i = 0; cookie_context[i] != '\0'; i++)
|
||||
{
|
||||
- if ((uint8_t) cookie_context[i] >= 128 ||
|
||||
+ if ((guint8) cookie_context[i] >= 128 ||
|
||||
cookie_context[i] == '/' ||
|
||||
cookie_context[i] == '\\' ||
|
||||
cookie_context[i] == ' ' ||
|
||||
@ -1,6 +1,6 @@
|
||||
Name: glib2
|
||||
Version: 2.68.4
|
||||
Release: 19%{?dist}.2
|
||||
Release: 19%{?dist}.9
|
||||
Summary: A library of handy utility functions
|
||||
|
||||
License: LGPLv2+
|
||||
@ -95,6 +95,27 @@ Patch: CVE-2025-14512.patch
|
||||
# https://github.com/GNOME/glib/commit/c9da977c178fbfc0e4caf99f9fdf5dc433d6fcc2
|
||||
Patch: CVE-2026-58016.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/commit/8b72ad09c874ddff122b3e67b3470c5e2eab7690
|
||||
Patch: CVE-2026-58015.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/commit/5f6d86b50bebf5458ab1becf4de2c5e5f066122b
|
||||
Patch: CVE-2026-58014.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/commit/9f557746c52ae2a62fd5929f532b77024a18abe2
|
||||
Patch: CVE-2026-58013.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/5131
|
||||
Patch: CVE-2026-58011.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/5132
|
||||
Patch: CVE-2026-58012.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/commit/8338414f6560216efe67d3cbf549e32f8630252a
|
||||
Patch: CVE-2026-58010.patch
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/glib/-/commit/407349aa255a5c2b49caa52847aca1b8311c98b2
|
||||
Patch: CVE-2026-15588.patch
|
||||
|
||||
BuildRequires: chrpath
|
||||
BuildRequires: gcc
|
||||
BuildRequires: gcc-c++
|
||||
@ -310,6 +331,33 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
|
||||
%{_datadir}/installed-tests
|
||||
|
||||
%changelog
|
||||
* Thu Jul 30 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.9
|
||||
- Fix CVE-2026-15588: limit D-Bus auth line read length
|
||||
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.8
|
||||
- Fix CVE-2026-58010: off-by-one in GVariant tuple offset checking
|
||||
- Resolves: RHEL-212157
|
||||
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.7
|
||||
- Fix CVE-2026-58012: buffer overflow in gregex.c with G_REGEX_RAW
|
||||
- Resolves: RHEL-212217
|
||||
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.6
|
||||
- Fix CVE-2026-58011: range validation in g_date_time_add_full()
|
||||
- Resolves: RHEL-212194
|
||||
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.5
|
||||
- Fix CVE-2026-58013: buffer over-read in GIOChannel with long terminators
|
||||
- Resolves: RHEL-212236
|
||||
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.4
|
||||
- Fix CVE-2026-58014: heap under-read in g_key_file_get_locale_string_list
|
||||
- Resolves: RHEL-190589
|
||||
|
||||
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.3
|
||||
- Fix CVE-2026-58015: validate D-Bus DBUS_COOKIE_SHA1 cookie context
|
||||
- Resolves: RHEL-212261
|
||||
|
||||
* Thu Jul 09 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.68.4-19.2
|
||||
- Fix CVE-2026-58016: broken node element nesting validation in
|
||||
D-Bus introspection XML parsing
|
||||
|
||||
Loading…
Reference in New Issue
Block a user