diff --git a/CVE-2025-13601.patch b/CVE-2025-13601.patch new file mode 100644 index 0000000..e94ffea --- /dev/null +++ b/CVE-2025-13601.patch @@ -0,0 +1,124 @@ +From 115b2b74d93ba1c61d842baba3612938a5bfb759 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Thu, 13 Nov 2025 18:27:22 +0000 +Subject: [PATCH] gconvert: Error out if g_escape_uri_string() would overflow + +If the string to escape contains a very large number of unacceptable +characters (which would need escaping), the calculation of the length of +the escaped string could overflow, leading to a potential write off the +end of the newly allocated string. + +In addition to that, the number of unacceptable characters was counted +in a signed integer, which would overflow to become negative, making it +easier for an attacker to craft an input string which would cause an +out-of-bounds write. + +Fix that by validating the allocation length, and using an unsigned +integer to count the number of unacceptable characters. + +Spotted by treeplus. Thanks to the Sovereign Tech Resilience programme +from the Sovereign Tech Agency. ID: #YWH-PGM9867-134 + +Signed-off-by: Philip Withnall + +Fixes: #3827 +--- + glib/gconvert.c | 36 +++++++++++++++++++++++++----------- + 1 file changed, 25 insertions(+), 11 deletions(-) + +diff --git a/glib/gconvert.c b/glib/gconvert.c +index 50286478c..066c391d6 100644 +--- a/glib/gconvert.c ++++ b/glib/gconvert.c +@@ -1386,8 +1386,9 @@ static const gchar hex[16] = "0123456789ABCDEF"; + /* Note: This escape function works on file: URIs, but if you want to + * escape something else, please read RFC-2396 */ + static gchar * +-g_escape_uri_string (const gchar *string, +- UnsafeCharacterSet mask) ++g_escape_uri_string (const gchar *string, ++ UnsafeCharacterSet mask, ++ GError **error) + { + #define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask)) + +@@ -1395,7 +1396,7 @@ g_escape_uri_string (const gchar *string, + gchar *q; + gchar *result; + int c; +- gint unacceptable; ++ size_t unacceptable; + UnsafeCharacterSet use_mask; + + g_return_val_if_fail (mask == UNSAFE_ALL +@@ -1412,7 +1413,14 @@ g_escape_uri_string (const gchar *string, + if (!ACCEPTABLE (c)) + unacceptable++; + } +- ++ ++ if (unacceptable >= (G_MAXSIZE - (p - string)) / 2) ++ { ++ g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI, ++ _("The URI is too long")); ++ return NULL; ++ } ++ + result = g_malloc (p - string + unacceptable * 2 + 1); + + use_mask = mask; +@@ -1437,12 +1445,13 @@ g_escape_uri_string (const gchar *string, + + + static gchar * +-g_escape_file_uri (const gchar *hostname, +- const gchar *pathname) ++g_escape_file_uri (const gchar *hostname, ++ const gchar *pathname, ++ GError **error) + { + char *escaped_hostname = NULL; +- char *escaped_path; +- char *res; ++ char *escaped_path = NULL; ++ char *res = NULL; + + #ifdef G_OS_WIN32 + char *p, *backslash; +@@ -1463,10 +1472,14 @@ g_escape_file_uri (const gchar *hostname, + + if (hostname && *hostname != '\0') + { +- escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST); ++ escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST, error); ++ if (escaped_hostname == NULL) ++ goto out; + } + +- escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH); ++ escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH, error); ++ if (escaped_path == NULL) ++ goto out; + + res = g_strconcat ("file://", + (escaped_hostname) ? escaped_hostname : "", +@@ -1474,6 +1487,7 @@ g_escape_file_uri (const gchar *hostname, + escaped_path, + NULL); + ++out: + #ifdef G_OS_WIN32 + g_free ((char *) pathname); + #endif +@@ -1793,7 +1807,7 @@ g_filename_to_uri (const gchar *filename, + hostname = NULL; + #endif + +- escaped_uri = g_escape_file_uri (hostname, filename); ++ escaped_uri = g_escape_file_uri (hostname, filename, error); + + return escaped_uri; + } +-- +2.52.0 + diff --git a/RHEL-114086.patch b/gdbusconnection-serial-number-overflow.patch similarity index 100% rename from RHEL-114086.patch rename to gdbusconnection-serial-number-overflow.patch diff --git a/glib2.spec b/glib2.spec index c0646c2..8d576df 100644 --- a/glib2.spec +++ b/glib2.spec @@ -5,7 +5,7 @@ Name: glib2 Version: 2.56.4 -Release: 167%{?dist} +Release: 168%{?dist} Summary: A library of handy utility functions License: LGPLv2+ @@ -33,6 +33,9 @@ BuildRequires: pkgconfig(zlib) BuildRequires: automake autoconf libtool BuildRequires: gtk-doc BuildRequires: python3-devel +# For testsuite +BuildRequires: desktop-file-utils +BuildRequires: shared-mime-info # for GIO content-type support Recommends: shared-mime-info @@ -148,7 +151,16 @@ Patch29: CVE-2024-34397.patch Patch30: gdatetime-test.patch # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4470 -Patch31: RHEL-114086.patch +Patch31: gdbusconnection-serial-number-overflow.patch + +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4914 +Patch32: CVE-2025-13601.patch + +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4916 +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4918 +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4930 +# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4931 +Patch33: gunixmount-improvements.patch %description GLib is the low-level core library that forms the basis for projects @@ -264,6 +276,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %transfiletriggerpostun -- %{_datadir}/glib-2.0/schemas glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : +%check +make %{?_smp_mflags} check + %files -f glib20.lang %license COPYING %doc AUTHORS NEWS README @@ -347,6 +362,11 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_datadir}/installed-tests %changelog +* Tue Jan 20 2026 Michael Catanzaro - 2.56.4-168 +- Add patch for CVE-2025-13601 +- Fix GUnixMount issues +- Enable testsuite during RPM check phase + * Wed Sep 17 2025 RHEL Packaging Agent - 2.56.4-167 - gdbusconnection: Prevent sending a serial of zero on overflow - Resolves: RHEL-114086 diff --git a/gunixmount-improvements.patch b/gunixmount-improvements.patch new file mode 100644 index 0000000..b6c2f7e --- /dev/null +++ b/gunixmount-improvements.patch @@ -0,0 +1,510 @@ +From 21ca525a8729c6b64133b00b3e382a2ce5478a9a Mon Sep 17 00:00:00 2001 +From: Christian Hergert +Date: Fri, 21 Nov 2025 12:31:13 -0800 +Subject: [PATCH 1/5] gio/gunixmounts: mark some file-system types as system + +Since this list was originally created, more file system types have +become commonly used and would benefit from being marked as a system +file-system type. + +This was found while tracking down some performance issues in +gnome-settings-daemon trash handling. +--- + gio/gunixmounts.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c +index 3514e2e8e..7d7b82980 100644 +--- a/gio/gunixmounts.c ++++ b/gio/gunixmounts.c +@@ -306,6 +306,8 @@ g_unix_is_system_fs_type (const char *fs_type) + "auto", + "autofs", + "autofs4", ++ "binfmt_misc", ++ "bpf", + "cgroup", + "configfs", + "cxfs", +@@ -314,6 +316,7 @@ g_unix_is_system_fs_type (const char *fs_type) + "devpts", + "devtmpfs", + "ecryptfs", ++ "efivarfs", + "fdescfs", + "fusectl", + "gfs", +@@ -342,6 +345,7 @@ g_unix_is_system_fs_type (const char *fs_type) + "selinuxfs", + "sysfs", + "tmpfs", ++ "tracefs", + "usbfs", + "zfs", + NULL +-- +2.52.0 + + +From b5525b89de94b2a84f4f77603f4cd5eae7c27b1b Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Mon, 1 Dec 2025 15:36:02 +0100 +Subject: [PATCH 2/5] gio/gunixmounts: Mark more file systems as system + internal + +The commit f1a90a67 updated list of system internal file systems. +I think we can add a few more file systems (i.e. `cgroups2`, +`fuse.gvfsd-fuse`, `fuse.portal`) and `/bin/efi` path. This is to +improve performance of `gvfsd-trash`, `gsd-houskeeping` and similar. + +Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/814 +--- + gio/gunixmounts.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c +index 7d7b82980..f9c3f9fec 100644 +--- a/gio/gunixmounts.c ++++ b/gio/gunixmounts.c +@@ -227,6 +227,7 @@ g_unix_is_mount_path_system_internal (const char *mount_path) + */ + "/", /* we already have "Filesystem root" in Nautilus */ + "/bin", ++ "/bin/efi", + "/boot", + "/compat/linux/proc", + "/compat/linux/sys", +@@ -309,6 +310,7 @@ g_unix_is_system_fs_type (const char *fs_type) + "binfmt_misc", + "bpf", + "cgroup", ++ "cgroup2", + "configfs", + "cxfs", + "debugfs", +@@ -318,6 +320,8 @@ g_unix_is_system_fs_type (const char *fs_type) + "ecryptfs", + "efivarfs", + "fdescfs", ++ "fuse.gvfsd-fuse", ++ "fuse.portal", + "fusectl", + "gfs", + "gfs2", +-- +2.52.0 + + +From e8e7229a72b92844c9928dde48cfa8c660cfe658 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Wed, 3 Dec 2025 10:02:15 +0100 +Subject: [PATCH 3/5] gio/gunixmounts: Replace /bin/efi with /boot/efi + +The commit 06e9f2c0 added `/bin/efi` instead of `/boot/efi` to the +list of system internal mount paths by mistake. Let's fix it. +--- + gio/gunixmounts.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c +index f9c3f9fec..a35e9fc43 100644 +--- a/gio/gunixmounts.c ++++ b/gio/gunixmounts.c +@@ -227,8 +227,8 @@ g_unix_is_mount_path_system_internal (const char *mount_path) + */ + "/", /* we already have "Filesystem root" in Nautilus */ + "/bin", +- "/bin/efi", + "/boot", ++ "/boot/efi", + "/compat/linux/proc", + "/compat/linux/sys", + "/dev", +-- +2.52.0 + + +From b761e2b3917a6cef5814717c06c19b9bd835096e Mon Sep 17 00:00:00 2001 +From: Christian Hergert +Date: Fri, 21 Nov 2025 18:54:33 -0800 +Subject: [PATCH 4/5] gio/unixmounts: use bsearch() to check for set inclusion + +This turns out to be about 17% faster than the previous set comparisons +on large (in the thousands) /proc/mounts configurations. It does require +that we keep the lists sorted but ended up faster than gperf hashing. +--- + gio/gunixmounts.c | 61 +++++++++++++++++++++++++---------------------- + 1 file changed, 32 insertions(+), 29 deletions(-) + +diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c +index a35e9fc43..ae4174d4f 100644 +--- a/gio/gunixmounts.c ++++ b/gio/gunixmounts.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -194,16 +195,17 @@ static guint64 mount_poller_time = 0; + #define endmntent(f) fclose(f) + #endif + ++static int ++compare_str (const char * key, ++ const char * const *element) ++{ ++ return strcmp (key, *element); ++} ++ + static gboolean +-is_in (const char *value, const char *set[]) ++is_in (const char *value, const char *set[], gsize set_size) + { +- int i; +- for (i = 0; set[i] != NULL; i++) +- { +- if (strcmp (set[i], value) == 0) +- return TRUE; +- } +- return FALSE; ++ return bsearch (value, set, set_size, sizeof (char *), (GCompareFunc)compare_str) != NULL; + } + + /** +@@ -221,11 +223,12 @@ is_in (const char *value, const char *set[]) + gboolean + g_unix_is_mount_path_system_internal (const char *mount_path) + { ++ /* keep sorted for bsearch */ + const char *ignore_mountpoints[] = { + /* Includes all FHS 2.3 toplevel dirs and other specialized + * directories that we want to hide from the user. + */ +- "/", /* we already have "Filesystem root" in Nautilus */ ++ "/", /* we already have "Filesystem root" in Nautilus */ + "/bin", + "/boot", + "/boot/efi", +@@ -241,11 +244,15 @@ g_unix_is_mount_path_system_internal (const char *mount_path) + "/live/image", + "/media", + "/mnt", ++ "/net", + "/opt", ++ "/proc", + "/rescue", + "/root", + "/sbin", ++ "/sbin", + "/srv", ++ "/sys", + "/tmp", + "/usr", + "/usr/X11R6", +@@ -262,16 +269,16 @@ g_unix_is_mount_path_system_internal (const char *mount_path) + "/var/mail", + "/var/run", + "/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */ +- "/proc", +- "/sbin", +- "/net", +- "/sys", +- NULL + }; + +- if (is_in (mount_path, ignore_mountpoints)) ++ if (is_in (mount_path, ignore_mountpoints, G_N_ELEMENTS (ignore_mountpoints))) + return TRUE; +- ++ ++ /* Kept separate from sorted list as they may vary */ ++ if (g_str_equal ("/var", mount_path) || ++ g_str_equal ("/run", mount_path)) ++ return TRUE; ++ + if (g_str_has_prefix (mount_path, "/dev/") || + g_str_has_prefix (mount_path, "/proc/") || + g_str_has_prefix (mount_path, "/sys/")) +@@ -301,14 +308,13 @@ g_unix_is_mount_path_system_internal (const char *mount_path) + gboolean + g_unix_is_system_fs_type (const char *fs_type) + { ++ /* keep sorted for bsearch */ + const char *ignore_fs[] = { + "adfs", + "afs", + "auto", + "autofs", + "autofs4", +- "binfmt_misc", +- "bpf", + "cgroup", + "cgroup2", + "configfs", +@@ -318,7 +324,6 @@ g_unix_is_system_fs_type (const char *fs_type) + "devpts", + "devtmpfs", + "ecryptfs", +- "efivarfs", + "fdescfs", + "fuse.gvfsd-fuse", + "fuse.portal", +@@ -349,15 +354,13 @@ g_unix_is_system_fs_type (const char *fs_type) + "selinuxfs", + "sysfs", + "tmpfs", +- "tracefs", + "usbfs", +- "zfs", +- NULL ++ "zfs" + }; + + g_return_val_if_fail (fs_type != NULL && *fs_type != '\0', FALSE); + +- return is_in (fs_type, ignore_fs); ++ return is_in (fs_type, ignore_fs, G_N_ELEMENTS (ignore_fs)); + } + + /** +@@ -379,19 +382,19 @@ g_unix_is_system_fs_type (const char *fs_type) + gboolean + g_unix_is_system_device_path (const char *device_path) + { ++ /* keep sorted for bsearch */ + const char *ignore_devices[] = { +- "none", +- "sunrpc", +- "devpts", +- "nfsd", + "/dev/loop", + "/dev/vn", +- NULL ++ "devpts", ++ "nfsd", ++ "none", ++ "sunrpc", + }; + + g_return_val_if_fail (device_path != NULL && *device_path != '\0', FALSE); + +- return is_in (device_path, ignore_devices); ++ return is_in (device_path, ignore_devices, G_N_ELEMENTS (ignore_devices)); + } + + static gboolean +-- +2.52.0 + + +From b9914374503531d5e9773716b865863fa04f6dca Mon Sep 17 00:00:00 2001 +From: Christian Hergert +Date: Tue, 6 Jan 2026 10:56:59 -0800 +Subject: [PATCH 5/5] gio/unixmounts: test that mounts are in sorted order + +--- + gio/gunixmounts-private.h | 69 +++++++++++++++++++++++++++++++++++++++ + gio/gunixmounts.c | 51 ++--------------------------- + gio/tests/unix-mounts.c | 24 ++++++++++++++ + 3 files changed, 95 insertions(+), 49 deletions(-) + create mode 100644 gio/gunixmounts-private.h + +diff --git a/gio/gunixmounts-private.h b/gio/gunixmounts-private.h +new file mode 100644 +index 000000000..196e81aca +--- /dev/null ++++ b/gio/gunixmounts-private.h +@@ -0,0 +1,69 @@ ++/* GIO - GLib Input, Output and Streaming Library ++ * ++ * Copyright 2006-2007 Red Hat, Inc. ++ * Copyright 2026 Christian Hergert ++ * ++ * 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 . ++ */ ++ ++#pragma once ++ ++/* keep sorted for bsearch */ ++static const char *system_mount_paths[] = { ++ /* Includes all FHS 2.3 toplevel dirs and other specialized ++ * directories that we want to hide from the user. ++ */ ++ "/", /* we already have "Filesystem root" in Nautilus */ ++ "/bin", ++ "/boot", ++ "/compat/linux/proc", ++ "/compat/linux/sys", ++ "/dev", ++ "/etc", ++ "/home", ++ "/lib", ++ "/lib64", ++ "/libexec", ++ "/live/cow", ++ "/live/image", ++ "/media", ++ "/mnt", ++ "/net", ++ "/opt", ++ "/proc", ++ "/rescue", ++ "/root", ++ "/sbin", ++ "/sbin", ++ "/srv", ++ "/sys", ++ "/tmp", ++ "/usr", ++ "/usr/X11R6", ++ "/usr/local", ++ "/usr/obj", ++ "/usr/ports", ++ "/usr/src", ++ "/usr/xobj", ++ "/var", ++ "/var/crash", ++ "/var/local", ++ "/var/log", ++ "/var/log/audit", /* https://bugzilla.redhat.com/show_bug.cgi?id=333041 */ ++ "/var/mail", ++ "/var/run", ++ "/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */ ++}; +diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c +index ae4174d4f..ca806abaf 100644 +--- a/gio/gunixmounts.c ++++ b/gio/gunixmounts.c +@@ -65,6 +65,7 @@ + #endif + + #include "gunixmounts.h" ++#include "gunixmounts-private.h" + #include "glocalfileprivate.h" + #include "gfile.h" + #include "gfilemonitor.h" +@@ -223,55 +224,7 @@ is_in (const char *value, const char *set[], gsize set_size) + gboolean + g_unix_is_mount_path_system_internal (const char *mount_path) + { +- /* keep sorted for bsearch */ +- const char *ignore_mountpoints[] = { +- /* Includes all FHS 2.3 toplevel dirs and other specialized +- * directories that we want to hide from the user. +- */ +- "/", /* we already have "Filesystem root" in Nautilus */ +- "/bin", +- "/boot", +- "/boot/efi", +- "/compat/linux/proc", +- "/compat/linux/sys", +- "/dev", +- "/etc", +- "/home", +- "/lib", +- "/lib64", +- "/libexec", +- "/live/cow", +- "/live/image", +- "/media", +- "/mnt", +- "/net", +- "/opt", +- "/proc", +- "/rescue", +- "/root", +- "/sbin", +- "/sbin", +- "/srv", +- "/sys", +- "/tmp", +- "/usr", +- "/usr/X11R6", +- "/usr/local", +- "/usr/obj", +- "/usr/ports", +- "/usr/src", +- "/usr/xobj", +- "/var", +- "/var/crash", +- "/var/local", +- "/var/log", +- "/var/log/audit", /* https://bugzilla.redhat.com/show_bug.cgi?id=333041 */ +- "/var/mail", +- "/var/run", +- "/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */ +- }; +- +- if (is_in (mount_path, ignore_mountpoints, G_N_ELEMENTS (ignore_mountpoints))) ++ if (is_in (mount_path, system_mount_paths, G_N_ELEMENTS (system_mount_paths))) + return TRUE; + + /* Kept separate from sorted list as they may vary */ +diff --git a/gio/tests/unix-mounts.c b/gio/tests/unix-mounts.c +index 67b8c8d98..4c1f69a01 100644 +--- a/gio/tests/unix-mounts.c ++++ b/gio/tests/unix-mounts.c +@@ -28,6 +28,8 @@ + #include + #include + ++#include "../gunixmounts-private.h" ++ + static void + test_is_system_fs_type (void) + { +@@ -48,6 +50,27 @@ test_is_system_device_path (void) + g_assert_false (g_unix_is_system_device_path ("/")); + } + ++static void ++test_system_mount_paths_sorted (void) ++{ ++ size_t i; ++ size_t n_paths = G_N_ELEMENTS (system_mount_paths); ++ ++ for (i = 1; i < n_paths; i++) ++ { ++ int cmp = strcmp (system_mount_paths[i - 1], system_mount_paths[i]); ++ if (cmp > 0) ++ { ++ g_fprintf (stderr, "system_mount_paths array is not sorted: " ++ "\"%s\" should come before \"%s\"", ++ system_mount_paths[i - 1], ++ system_mount_paths[i]); ++ g_test_fail (); ++ return; ++ } ++ } ++} ++ + int + main (int argc, + char *argv[]) +@@ -58,6 +81,7 @@ main (int argc, + + g_test_add_func ("/unix-mounts/is-system-fs-type", test_is_system_fs_type); + g_test_add_func ("/unix-mounts/is-system-device-path", test_is_system_device_path); ++ g_test_add_func ("/unix-mounts/system-mount-paths-sorted", test_system_mount_paths_sorted); + + return g_test_run (); + } +-- +2.52.0 +