public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Michael Catanzaro <mcatanzaro@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/glib2] cve-2026-58016-f44: Enable GnuTLS-based GHmac in Fedora and reenable glib2-static in RHEL
Date: Tue, 11 Aug 2026 10:37:24 GMT [thread overview]
Message-ID: <178644464440.1.11313599040704646782.rpms-glib2-1f79f0520372@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/glib2
Branch : cve-2026-58016-f44
Commit : 1f79f0520372d7802c298defcde49252386ce119
Author : Michael Catanzaro <mcatanzaro@redhat.com>
Date : 2021-06-17T10:45:30-05:00
Stats : +1325/-912 in 7 file(s)
URL : https://src.fedoraproject.org/rpms/glib2/c/1f79f0520372d7802c298defcde49252386ce119?branch=cve-2026-58016-f44
Log:
Enable GnuTLS-based GHmac in Fedora and reenable glib2-static in RHEL
Consolidate GDesktopAppInfo changes into gdesktopappinfo.patch
Disable check-rpath since it seems to be broken
---
diff --git a/0001-tests-Iterate-mainloop-during-launch-test.patch b/0001-tests-Iterate-mainloop-during-launch-test.patch
deleted file mode 100644
index 5290431..0000000
--- a/0001-tests-Iterate-mainloop-during-launch-test.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 5e42384cc4499293259a8a37a737014a56de34df Mon Sep 17 00:00:00 2001
-From: Benjamin Berg <bberg@redhat.com>
-Date: Fri, 23 Oct 2020 18:20:01 +0200
-Subject: [PATCH 1/4] tests: Iterate mainloop during launch test
-
-When launching an application, we wait for the DBus response from
-systemd before executing the binary. Because of this the main loop needs
-to be iterated for spawning to completed and the file to be created.
-
-Without this the test will time out if GLib was able to connect to the
-session bus.
----
- gio/tests/desktop-app-info.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c
-index fcc29c579..743230cbb 100644
---- a/gio/tests/desktop-app-info.c
-+++ b/gio/tests/desktop-app-info.c
-@@ -334,6 +334,7 @@ wait_for_file (const gchar *want_this,
- */
- while (access (want_this, F_OK) != 0)
- {
-+ g_main_context_iteration (NULL, FALSE);
- g_usleep (100000); /* 100ms */
- g_assert_cmpuint (retries, >, 0);
- retries--;
---
-2.31.1
-
diff --git a/0002-gdesktopappinfo-Move-launched-applications-into-tran.patch b/0002-gdesktopappinfo-Move-launched-applications-into-tran.patch
deleted file mode 100644
index a4e6290..0000000
--- a/0002-gdesktopappinfo-Move-launched-applications-into-tran.patch
+++ /dev/null
@@ -1,388 +0,0 @@
-From ba3b85a8fea0151e74de50e841a7f16f9b077a56 Mon Sep 17 00:00:00 2001
-From: Benjamin Berg <bberg@redhat.com>
-Date: Mon, 27 Jul 2020 22:22:32 +0200
-Subject: [PATCH 2/4] gdesktopappinfo: Move launched applications into
- transient scope
-
-Try to move the spawned executable into its own systemd scope. To avoid
-possible race conditions and ensure proper accounting, we delay the
-execution of the real command until after the DBus call to systemd has
-finished.
-
-From the two approaches we can take here, this is better in the sense
-that we have a child that the API consumer can watch. API consumers
-should not be doing this, however, gnome-session needs to watch children
-during session startup. Until gnome-session is fixed, we will not be
-able to change this.
-
-The alternative approach is to delegate launching itself to systemd by
-creating a transient .service unit instead. This is cleaner and has e.g.
-the advantage that systemd will take care of log redirection and similar
-issues.
-
-Note that this patch is incomplete. The DBus call is done in a "fire and
-forget" manner, which is fine in most cases, but means that "gio open"
-will fail to move the child into the new scope as gio quits before the
-DBus call finishes.
----
- gio/gdesktopappinfo.c | 264 ++++++++++++++++++++++++++++++++++++------
- 1 file changed, 227 insertions(+), 37 deletions(-)
-
-diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
-index 1a4b97918..afdcd42ac 100644
---- a/gio/gdesktopappinfo.c
-+++ b/gio/gdesktopappinfo.c
-@@ -2730,6 +2730,148 @@ notify_desktop_launch (GDBusConnection *session_bus,
-
- #define _SPAWN_FLAGS_DEFAULT (G_SPAWN_SEARCH_PATH)
-
-+#if defined(__linux__) && !defined(__BIONIC__)
-+typedef struct {
-+ int pipe[2];
-+ GSpawnChildSetupFunc user_setup;
-+ gpointer user_setup_data;
-+} SpawnWrapperData;
-+
-+static void
-+launch_uris_with_spawn_delay_exec (gpointer user_data)
-+{
-+ SpawnWrapperData *data = user_data;
-+
-+ /* Clear CLOEXEC again, as that was set due to
-+ * G_SPAWN_LEAVE_DESCRIPTORS_OPEN not being set. */
-+ fcntl (data->pipe[0], F_SETFD, 0);
-+
-+ /* No need to close read side, we have CLOEXEC set. */
-+
-+ if (data->user_setup)
-+ data->user_setup (data->user_setup_data);
-+}
-+
-+static gchar *
-+systemd_unit_name_escape (const gchar *in)
-+{
-+ /* Adapted from systemd source */
-+ GString * const str = g_string_sized_new (strlen (in));
-+
-+ for (; *in; in++)
-+ {
-+ if (g_ascii_isalnum (*in) || *in == ':' || *in == '_' || *in == '.')
-+ g_string_append_c (str, *in);
-+ else
-+ g_string_append_printf (str, "\\x%02x", *in);
-+ }
-+ return g_string_free (str, FALSE);
-+}
-+
-+static void
-+create_systemd_scope (GDBusConnection *session_bus,
-+ GDesktopAppInfo *info,
-+ gint pid,
-+ GAsyncReadyCallback callback,
-+ gpointer user_data)
-+{
-+ GVariantBuilder builder;
-+ const char *app_name = g_get_application_name ();
-+ char *appid = NULL;
-+ char *appid_escaped = NULL;
-+ char *snid_escaped = NULL;
-+ char *unit_name = NULL;
-+
-+ /* In this order:
-+ * 1. Actual application ID from file
-+ * 2. Stripping the .desktop from the desktop ID
-+ * 3. Fall back to using the binary name
-+ */
-+ if (info->app_id)
-+ appid = g_strdup (info->app_id);
-+ else if (info->desktop_id && g_str_has_suffix (info->desktop_id, ".desktop"))
-+ appid = g_strndup (info->desktop_id, strlen (info->desktop_id) - 8);
-+ else
-+ appid = g_path_get_basename (info->binary);
-+
-+ appid_escaped = systemd_unit_name_escape (appid);
-+
-+ /* Generate a name conforming to
-+ * https://systemd.io/DESKTOP_ENVIRONMENTS/
-+ * We use the PID to disambiguate, as that should be unique enough.
-+ */
-+ unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, pid);
-+
-+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))"));
-+ g_variant_builder_add (&builder, "s", unit_name);
-+ g_variant_builder_add (&builder, "s", "fail");
-+
-+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sv)"));
-+
-+ /* Add a generic human readable description, can be changed at will. */
-+ if (app_name)
-+ g_variant_builder_add (&builder,
-+ "(sv)",
-+ "Description",
-+ g_variant_new_take_string (g_strdup_printf ("Application launched by %s",
-+ app_name)));
-+ g_variant_builder_add (&builder,
-+ "(sv)",
-+ "PIDs",
-+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, &pid, 1, 4));
-+ /* Default to let systemd garbage collect failed applications we launched. */
-+ g_variant_builder_add (&builder,
-+ "(sv)",
-+ "CollectMode",
-+ g_variant_new_string ("inactive-or-failed"));
-+
-+ g_variant_builder_close (&builder);
-+
-+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sa(sv))"));
-+ g_variant_builder_close (&builder);
-+
-+ g_dbus_connection_call (session_bus,
-+ "org.freedesktop.systemd1",
-+ "/org/freedesktop/systemd1",
-+ "org.freedesktop.systemd1.Manager",
-+ "StartTransientUnit",
-+ g_variant_builder_end (&builder),
-+ G_VARIANT_TYPE ("(o)"),
-+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
-+ 1000,
-+ NULL,
-+ callback,
-+ user_data);
-+
-+ g_free (appid);
-+ g_free (appid_escaped);
-+ g_free (snid_escaped);
-+ g_free (unit_name);
-+}
-+
-+static void
-+systemd_scope_created_cb (GObject *object,
-+ GAsyncResult *result,
-+ gpointer user_data)
-+{
-+ GVariant *res = NULL;
-+ GError *error = NULL;
-+
-+ res = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error);
-+ if (error != NULL)
-+ {
-+ g_debug ("Failed to move new child into scope: %s", error->message);
-+ g_error_free (error);
-+ }
-+
-+ /* Unblock the waiting wrapper binary. */
-+ close (GPOINTER_TO_INT (user_data));
-+
-+ if (res)
-+ g_variant_unref (res);
-+}
-+#endif
-+
- static gboolean
- g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- GDBusConnection *session_bus,
-@@ -2750,13 +2892,14 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- GList *old_uris;
- GList *dup_uris;
-
-- char **argv, **envp;
-+ GStrv argv = NULL, envp = NULL;
-+ GStrv wrapped_argv = NULL;
-+ GList *launched_uris = NULL;
-+ char *sn_id = NULL;
- int argc;
-
- g_return_val_if_fail (info != NULL, FALSE);
-
-- argv = NULL;
--
- if (launch_context)
- envp = g_app_launch_context_get_environment (launch_context);
- else
-@@ -2770,27 +2913,19 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- do
- {
- GPid pid;
-- GList *launched_uris;
- GList *iter;
-- char *sn_id = NULL;
-- char **wrapped_argv;
- int i;
-- gsize j;
-- const gchar * const wrapper_argv[] =
-- {
-- "/bin/sh",
-- "-e",
-- "-u",
-- "-c", "export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"",
-- "sh", /* argv[0] for sh */
-- };
-+#if defined(__linux__) && !defined(__BIONIC__)
-+ SpawnWrapperData wrapper_data;
-+#endif
-+ GSpawnChildSetupFunc setup = user_setup;
-+ gpointer setup_data = user_setup_data;
-
- old_uris = dup_uris;
- if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error))
-- goto out;
-+ return FALSE;
-
- /* Get the subset of URIs we're launching with this process */
-- launched_uris = NULL;
- for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next)
- launched_uris = g_list_prepend (launched_uris, iter->data);
- launched_uris = g_list_reverse (launched_uris);
-@@ -2799,7 +2934,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Unable to find terminal required for application"));
-- goto out;
-+ return FALSE;
- }
-
- if (info->filename)
-@@ -2808,7 +2943,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- info->filename,
- TRUE);
-
-- sn_id = NULL;
- if (launch_context)
- {
- GList *launched_files = create_files_for_uris (launched_uris);
-@@ -2837,38 +2971,93 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- * with a wrapper program (grep the GLib git history for
- * `gio-launch-desktop` for an example of this which could be
- * resurrected). */
-- wrapped_argv = g_new (char *, argc + G_N_ELEMENTS (wrapper_argv) + 1);
-+ wrapped_argv = g_new (char *, argc + 6 + 1);
-+
-+ wrapped_argv[0] = g_strdup ("/bin/sh");
-+ wrapped_argv[1] = g_strdup ("-e");
-+ wrapped_argv[2] = g_strdup ("-u");
-+ wrapped_argv[3] = g_strdup ("-c");
-+ /* argument 4 is filled in below */
-+ wrapped_argv[5] = g_strdup ("sh");
-
-- for (j = 0; j < G_N_ELEMENTS (wrapper_argv); j++)
-- wrapped_argv[j] = g_strdup (wrapper_argv[j]);
- for (i = 0; i < argc; i++)
-- wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = g_steal_pointer (&argv[i]);
-+ wrapped_argv[i + 6] = g_steal_pointer (&argv[i]);
-+
-+ wrapped_argv[i + 6] = NULL;
-+ g_clear_pointer (&argv, g_free);
-+
-+#if defined(__linux__) && !defined(__BIONIC__)
-+ /* Create pipes, if we use a setup func, then set cloexec,
-+ * otherwise our wrapper script will close both sides. */
-+ if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL))
-+ {
-+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-+ _("Unable to create pipe for systemd synchronization"));
-+ return FALSE;
-+ }
-+
-+ /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */
-+ fcntl (wrapper_data.pipe[1], F_SETFD, FD_CLOEXEC);
-
-- wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = NULL;
-- g_free (argv);
-- argv = NULL;
-+ if (!(spawn_flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
-+ {
-+ /* In this case, we use a setup function (which could probably also
-+ * overwrite envp to set GIO_LAUNCHED_DESKTOP_FILE_PID).
-+ *
-+ * Note that this does not incur an additional cost because
-+ * G_SPAWN_LEAVE_DESCRIPTOR_OPEN must be set in order to use
-+ * posix_spawn. */
-+ wrapper_data.user_setup = setup;
-+ wrapper_data.user_setup_data = setup_data;
-+
-+ setup = launch_uris_with_spawn_delay_exec;
-+ setup_data = &wrapper_data;
-+ }
-+
-+ wrapped_argv[4] = g_strdup_printf ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; cat <&%1$d; exec \"$@\" %1$d<&-",
-+ wrapper_data.pipe[0]);
-+#else
-+ wrapped_argv[4] = g_strdup ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"");
-+#endif
-
- if (!g_spawn_async_with_fds (info->path,
- wrapped_argv,
- envp,
- spawn_flags,
-- user_setup,
-- user_setup_data,
-+ setup,
-+ setup_data,
- &pid,
- stdin_fd,
- stdout_fd,
- stderr_fd,
- error))
- {
-+#if defined(__linux__) && !defined(__BIONIC__)
-+ close (wrapper_data.pipe[0]);
-+ close (wrapper_data.pipe[1]);
-+#endif
-+
- if (sn_id)
- g_app_launch_context_launch_failed (launch_context, sn_id);
-
-- g_free (sn_id);
-- g_list_free (launched_uris);
--
- goto out;
- }
-
-+#if defined(__linux__) && !defined(__BIONIC__)
-+ /* We close write side asynchronously later on when the dbus call
-+ * to systemd finishes. */
-+ close (wrapper_data.pipe[0]);
-+
-+ if (session_bus)
-+ create_systemd_scope (session_bus,
-+ info,
-+ pid,
-+ systemd_scope_created_cb,
-+ GINT_TO_POINTER (wrapper_data.pipe[1]));
-+ else
-+ close (wrapper_data.pipe[1]);
-+#endif
-+
- if (pid_callback != NULL)
- pid_callback (info, pid, pid_callback_data);
-
-@@ -2893,19 +3082,20 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- sn_id,
- launched_uris);
-
-- g_free (sn_id);
-- g_list_free (launched_uris);
--
-- g_strfreev (wrapped_argv);
-- wrapped_argv = NULL;
-+ g_clear_pointer (&sn_id, g_free);
-+ g_clear_pointer (&launched_uris, g_list_free);
-+ g_clear_pointer (&wrapped_argv, g_strfreev);
- }
- while (dup_uris != NULL);
-
- completed = TRUE;
-
-- out:
-+out:
- g_strfreev (argv);
- g_strfreev (envp);
-+ g_clear_pointer (&wrapped_argv, g_strfreev);
-+ g_list_free (launched_uris);
-+ g_free (sn_id);
-
- return completed;
- }
---
-2.31.1
-
diff --git a/0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch b/0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch
deleted file mode 100644
index 84a8d7a..0000000
--- a/0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch
+++ /dev/null
@@ -1,382 +0,0 @@
-From cd67a1b0256d2397dac0836e154f3449b63a6b19 Mon Sep 17 00:00:00 2001
-From: Benjamin Berg <bberg@redhat.com>
-Date: Tue, 28 Jul 2020 12:11:13 +0200
-Subject: [PATCH 3/4] gdesktopappinfo: Handle task completion from spawn
- function
-
-This allows delaying the return of the task until all dbus calls (in
-particular the ones to setup the scope) have finished.
-
-This fixes the behaviour of the previous commit which would not
-correctly move the process into the scope if the application exited
-right after the task returned.
----
- gio/gdesktopappinfo.c | 212 +++++++++++++++++++++++++++++-------------
- 1 file changed, 146 insertions(+), 66 deletions(-)
-
-diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
-index afdcd42ac..8d0f1688e 100644
---- a/gio/gdesktopappinfo.c
-+++ b/gio/gdesktopappinfo.c
-@@ -2849,11 +2849,17 @@ create_systemd_scope (GDBusConnection *session_bus,
- g_free (unit_name);
- }
-
-+typedef struct {
-+ GTask *task;
-+ int fd;
-+} ScopeCreatedData;
-+
- static void
- systemd_scope_created_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
- {
-+ ScopeCreatedData *data = user_data;
- GVariant *res = NULL;
- GError *error = NULL;
-
-@@ -2865,13 +2871,47 @@ systemd_scope_created_cb (GObject *object,
- }
-
- /* Unblock the waiting wrapper binary. */
-- close (GPOINTER_TO_INT (user_data));
-+
-+ close (data->fd);
-+
-+ if (data->task)
-+ {
-+ gint pending;
-+ pending = GPOINTER_TO_INT (g_task_get_task_data (data->task));
-+ pending -= 1;
-+ g_task_set_task_data (data->task, GINT_TO_POINTER (pending), NULL);
-+
-+ if (pending == 0 && !g_task_get_completed (data->task))
-+ g_task_return_boolean (data->task, TRUE);
-+ }
-
- if (res)
- g_variant_unref (res);
-+ g_clear_object (&data->task);
-+ g_free (data);
- }
- #endif
-
-+static void
-+launch_uris_with_spawn_flush_cb (GObject *object,
-+ GAsyncResult *result,
-+ gpointer user_data)
-+{
-+ GTask *task = G_TASK (user_data);
-+ gint pending;
-+
-+ g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL);
-+
-+ pending = GPOINTER_TO_INT (g_task_get_task_data (task));
-+ pending -= 1;
-+ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
-+
-+ if (pending == 0 && !g_task_get_completed (task))
-+ g_task_return_boolean (task, TRUE);
-+
-+ g_object_unref (task);
-+}
-+
- static gboolean
- g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- GDBusConnection *session_bus,
-@@ -2886,9 +2926,10 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- gint stdin_fd,
- gint stdout_fd,
- gint stderr_fd,
-- GError **error)
-+ GTask *task,
-+ GError **error_out)
- {
-- gboolean completed = FALSE;
-+ GError *error = NULL;
- GList *old_uris;
- GList *dup_uris;
-
-@@ -2898,8 +2939,15 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- char *sn_id = NULL;
- int argc;
-
-+ /* We may get a task to report back on or an error. But never both. */
-+ g_assert (!(task && error_out));
- g_return_val_if_fail (info != NULL, FALSE);
-
-+ /* Surrounding code must not have set any data on the task
-+ * (it is cleared before calling this function). */
-+ if (session_bus && task)
-+ g_assert (g_task_get_task_data (task) == NULL);
-+
- if (launch_context)
- envp = g_app_launch_context_get_environment (launch_context);
- else
-@@ -2922,8 +2970,8 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- gpointer setup_data = user_setup_data;
-
- old_uris = dup_uris;
-- if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error))
-- return FALSE;
-+ if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, &error))
-+ goto out;
-
- /* Get the subset of URIs we're launching with this process */
- for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next)
-@@ -2932,9 +2980,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
-
- if (info->terminal && !prepend_terminal_to_vector (&argc, &argv))
- {
-- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-- _("Unable to find terminal required for application"));
-- return FALSE;
-+ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
-+ _("Unable to find terminal required for application"));
-+ goto out;
- }
-
- if (info->filename)
-@@ -2991,9 +3039,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- * otherwise our wrapper script will close both sides. */
- if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL))
- {
-- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-- _("Unable to create pipe for systemd synchronization"));
-- return FALSE;
-+ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
-+ _("Unable to create pipe for systemd synchronization"));
-+ goto out;
- }
-
- /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */
-@@ -3030,7 +3078,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- stdin_fd,
- stdout_fd,
- stderr_fd,
-- error))
-+ &error))
- {
- #if defined(__linux__) && !defined(__BIONIC__)
- close (wrapper_data.pipe[0]);
-@@ -3049,11 +3097,29 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- close (wrapper_data.pipe[0]);
-
- if (session_bus)
-- create_systemd_scope (session_bus,
-- info,
-- pid,
-- systemd_scope_created_cb,
-- GINT_TO_POINTER (wrapper_data.pipe[1]));
-+ {
-+ ScopeCreatedData *data;
-+
-+ data = g_new0 (ScopeCreatedData, 1);
-+
-+ if (task)
-+ {
-+ gint pending;
-+ pending = GPOINTER_TO_INT (g_task_get_task_data (task));
-+ pending += 1;
-+ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
-+
-+ data->task = g_object_ref (task);
-+ }
-+
-+ data->fd = wrapper_data.pipe[1];
-+
-+ create_systemd_scope (session_bus,
-+ info,
-+ pid,
-+ systemd_scope_created_cb,
-+ data);
-+ }
- else
- close (wrapper_data.pipe[1]);
- #endif
-@@ -3088,8 +3154,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
- }
- while (dup_uris != NULL);
-
-- completed = TRUE;
--
- out:
- g_strfreev (argv);
- g_strfreev (envp);
-@@ -3097,7 +3161,52 @@ out:
- g_list_free (launched_uris);
- g_free (sn_id);
-
-- return completed;
-+ if (!error)
-+ {
-+ if (session_bus && task)
-+ {
-+ GCancellable *cancellable = g_task_get_cancellable (task);
-+ gint pending;
-+ pending = GPOINTER_TO_INT (g_task_get_task_data (task));
-+ pending += 1;
-+ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
-+
-+ /* FIXME: The D-Bus message from the notify_desktop_launch() function
-+ * can be still lost even if flush is called later. See:
-+ * https://gitlab.freedesktop.org/dbus/dbus/issues/72
-+ */
-+ g_dbus_connection_flush (session_bus,
-+ cancellable,
-+ launch_uris_with_spawn_flush_cb,
-+ g_steal_pointer (&task));
-+ }
-+ else if (session_bus)
-+ {
-+ /* No task available. */
-+ g_dbus_connection_flush (session_bus,
-+ NULL,
-+ NULL,
-+ NULL);
-+ }
-+ else if (task)
-+ {
-+ /* Return the given task. */
-+ g_task_return_boolean (task, TRUE);
-+ g_object_unref (task);
-+ }
-+ }
-+ else
-+ {
-+ if (task)
-+ {
-+ g_task_return_error (task, error);
-+ g_object_unref (task);
-+ }
-+ else
-+ g_propagate_error (error_out, error);
-+ }
-+
-+ return !error;
- }
-
- static gchar *
-@@ -3246,17 +3355,9 @@ g_desktop_app_info_launch_uris_internal (GAppInfo *appinfo,
- success = g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec, uris, launch_context,
- spawn_flags, user_setup, user_setup_data,
- pid_callback, pid_callback_data,
-- stdin_fd, stdout_fd, stderr_fd, error);
-+ stdin_fd, stdout_fd, stderr_fd, NULL, error);
-
-- if (session_bus != NULL)
-- {
-- /* This asynchronous flush holds a reference until it completes,
-- * which ensures that the following unref won't immediately kill
-- * the connection if we were the initial owner.
-- */
-- g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
-- g_object_unref (session_bus);
-- }
-+ g_clear_object (&session_bus);
-
- return success;
- }
-@@ -3310,18 +3411,6 @@ launch_uris_with_dbus_cb (GObject *object,
- g_object_unref (task);
- }
-
--static void
--launch_uris_flush_cb (GObject *object,
-- GAsyncResult *result,
-- gpointer user_data)
--{
-- GTask *task = G_TASK (user_data);
--
-- g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL);
-- g_task_return_boolean (task, TRUE);
-- g_object_unref (task);
--}
--
- static void
- launch_uris_bus_get_cb (GObject *object,
- GAsyncResult *result,
-@@ -3330,12 +3419,20 @@ launch_uris_bus_get_cb (GObject *object,
- GTask *task = G_TASK (user_data);
- GDesktopAppInfo *info = G_DESKTOP_APP_INFO (g_task_get_source_object (task));
- LaunchUrisData *data = g_task_get_task_data (task);
-+ LaunchUrisData *data_copy = NULL;
- GCancellable *cancellable = g_task_get_cancellable (task);
- GDBusConnection *session_bus;
-- GError *error = NULL;
-
- session_bus = g_bus_get_finish (result, NULL);
-
-+ data_copy = g_new0 (LaunchUrisData, 1);
-+ data_copy->appinfo = g_steal_pointer (&data->appinfo);
-+ data_copy->uris = g_steal_pointer (&data->uris);
-+ data_copy->context = g_steal_pointer (&data->context);
-+
-+ /* Allow other data to be attached to the task. */
-+ g_task_set_task_data (task, NULL, NULL);
-+
- if (session_bus && info->app_id)
- {
- /* FIXME: The g_document_portal_add_documents() function, which is called
-@@ -3343,34 +3440,21 @@ launch_uris_bus_get_cb (GObject *object,
- * uses blocking calls.
- */
- g_desktop_app_info_launch_uris_with_dbus (info, session_bus,
-- data->uris, data->context,
-+ data_copy->uris, data_copy->context,
- cancellable,
- launch_uris_with_dbus_cb,
- g_steal_pointer (&task));
- }
- else
- {
-- /* FIXME: The D-Bus message from the notify_desktop_launch() function
-- * can be still lost even if flush is called later. See:
-- * https://gitlab.freedesktop.org/dbus/dbus/issues/72
-- */
- g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec,
-- data->uris, data->context,
-+ data_copy->uris, data_copy->context,
- _SPAWN_FLAGS_DEFAULT, NULL,
- NULL, NULL, NULL, -1, -1, -1,
-- &error);
-- if (error != NULL)
-- {
-- g_task_return_error (task, g_steal_pointer (&error));
-- g_object_unref (task);
-- }
-- else
-- g_dbus_connection_flush (session_bus,
-- cancellable,
-- launch_uris_flush_cb,
-- g_steal_pointer (&task));
-+ g_steal_pointer (&task), NULL);
- }
-
-+ launch_uris_data_free (data_copy);
- g_clear_object (&session_bus);
- }
-
-@@ -5186,16 +5270,12 @@ g_desktop_app_info_launch_action (GDesktopAppInfo *info,
- if (exec_line)
- g_desktop_app_info_launch_uris_with_spawn (info, session_bus, exec_line, NULL, launch_context,
- _SPAWN_FLAGS_DEFAULT, NULL, NULL, NULL, NULL,
-- -1, -1, -1, NULL);
-+ -1, -1, -1, NULL, NULL);
-
- g_free (exec_line);
- }
-
-- if (session_bus != NULL)
-- {
-- g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
-- g_object_unref (session_bus);
-- }
-+ g_clear_object (&session_bus);
- }
- /* Epilogue {{{1 */
-
---
-2.31.1
-
diff --git a/0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch b/0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch
deleted file mode 100644
index ae8a719..0000000
--- a/0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-From 8da8a3ef6df8af6de8bd388192bebe8b51b3e782 Mon Sep 17 00:00:00 2001
-From: Benjamin Berg <bberg@redhat.com>
-Date: Thu, 17 Sep 2020 17:35:58 +0200
-Subject: [PATCH 4/4] gdesktopappinfo: Add SourcePath= to transient systemd
- units
-
-systemd allows setting a SourcePath= which shows the file that the unit
-has been generated from. KDE is starting to set this and it seems like a
-good idea, so do the same here.
-
-See https://invent.kde.org/frameworks/kio/-/merge_requests/124
----
- gio/gdesktopappinfo.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
-diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
-index 8d0f1688e..a833de4e6 100644
---- a/gio/gdesktopappinfo.c
-+++ b/gio/gdesktopappinfo.c
-@@ -2777,6 +2777,7 @@ create_systemd_scope (GDBusConnection *session_bus,
- {
- GVariantBuilder builder;
- const char *app_name = g_get_application_name ();
-+ const char *source_path = NULL;
- char *appid = NULL;
- char *appid_escaped = NULL;
- char *snid_escaped = NULL;
-@@ -2802,6 +2803,8 @@ create_systemd_scope (GDBusConnection *session_bus,
- */
- unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, pid);
-
-+ source_path = g_desktop_app_info_get_filename (info);
-+
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))"));
- g_variant_builder_add (&builder, "s", unit_name);
- g_variant_builder_add (&builder, "s", "fail");
-@@ -2815,6 +2818,16 @@ create_systemd_scope (GDBusConnection *session_bus,
- "Description",
- g_variant_new_take_string (g_strdup_printf ("Application launched by %s",
- app_name)));
-+
-+ /* If we have a .desktop file, document that the scope has been "generated"
-+ * from it.
-+ */
-+ if (source_path && g_utf8_validate (source_path, -1, NULL))
-+ g_variant_builder_add (&builder,
-+ "(sv)",
-+ "SourcePath",
-+ g_variant_new_string (source_path));
-+
- g_variant_builder_add (&builder,
- "(sv)",
- "PIDs",
---
-2.31.1
-
diff --git a/gdesktopappinfo.patch b/gdesktopappinfo.patch
new file mode 100644
index 0000000..786ac7c
--- /dev/null
+++ b/gdesktopappinfo.patch
@@ -0,0 +1,855 @@
+From 5e42384cc4499293259a8a37a737014a56de34df Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Fri, 23 Oct 2020 18:20:01 +0200
+Subject: [PATCH 1/4] tests: Iterate mainloop during launch test
+
+When launching an application, we wait for the DBus response from
+systemd before executing the binary. Because of this the main loop needs
+to be iterated for spawning to completed and the file to be created.
+
+Without this the test will time out if GLib was able to connect to the
+session bus.
+---
+ gio/tests/desktop-app-info.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c
+index fcc29c579..743230cbb 100644
+--- a/gio/tests/desktop-app-info.c
++++ b/gio/tests/desktop-app-info.c
+@@ -334,6 +334,7 @@ wait_for_file (const gchar *want_this,
+ */
+ while (access (want_this, F_OK) != 0)
+ {
++ g_main_context_iteration (NULL, FALSE);
+ g_usleep (100000); /* 100ms */
+ g_assert_cmpuint (retries, >, 0);
+ retries--;
+--
+2.31.1
+
+From ba3b85a8fea0151e74de50e841a7f16f9b077a56 Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Mon, 27 Jul 2020 22:22:32 +0200
+Subject: [PATCH 2/4] gdesktopappinfo: Move launched applications into
+ transient scope
+
+Try to move the spawned executable into its own systemd scope. To avoid
+possible race conditions and ensure proper accounting, we delay the
+execution of the real command until after the DBus call to systemd has
+finished.
+
+From the two approaches we can take here, this is better in the sense
+that we have a child that the API consumer can watch. API consumers
+should not be doing this, however, gnome-session needs to watch children
+during session startup. Until gnome-session is fixed, we will not be
+able to change this.
+
+The alternative approach is to delegate launching itself to systemd by
+creating a transient .service unit instead. This is cleaner and has e.g.
+the advantage that systemd will take care of log redirection and similar
+issues.
+
+Note that this patch is incomplete. The DBus call is done in a "fire and
+forget" manner, which is fine in most cases, but means that "gio open"
+will fail to move the child into the new scope as gio quits before the
+DBus call finishes.
+---
+ gio/gdesktopappinfo.c | 264 ++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 227 insertions(+), 37 deletions(-)
+
+diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
+index 1a4b97918..afdcd42ac 100644
+--- a/gio/gdesktopappinfo.c
++++ b/gio/gdesktopappinfo.c
+@@ -2730,6 +2730,148 @@ notify_desktop_launch (GDBusConnection *session_bus,
+
+ #define _SPAWN_FLAGS_DEFAULT (G_SPAWN_SEARCH_PATH)
+
++#if defined(__linux__) && !defined(__BIONIC__)
++typedef struct {
++ int pipe[2];
++ GSpawnChildSetupFunc user_setup;
++ gpointer user_setup_data;
++} SpawnWrapperData;
++
++static void
++launch_uris_with_spawn_delay_exec (gpointer user_data)
++{
++ SpawnWrapperData *data = user_data;
++
++ /* Clear CLOEXEC again, as that was set due to
++ * G_SPAWN_LEAVE_DESCRIPTORS_OPEN not being set. */
++ fcntl (data->pipe[0], F_SETFD, 0);
++
++ /* No need to close read side, we have CLOEXEC set. */
++
++ if (data->user_setup)
++ data->user_setup (data->user_setup_data);
++}
++
++static gchar *
++systemd_unit_name_escape (const gchar *in)
++{
++ /* Adapted from systemd source */
++ GString * const str = g_string_sized_new (strlen (in));
++
++ for (; *in; in++)
++ {
++ if (g_ascii_isalnum (*in) || *in == ':' || *in == '_' || *in == '.')
++ g_string_append_c (str, *in);
++ else
++ g_string_append_printf (str, "\\x%02x", *in);
++ }
++ return g_string_free (str, FALSE);
++}
++
++static void
++create_systemd_scope (GDBusConnection *session_bus,
++ GDesktopAppInfo *info,
++ gint pid,
++ GAsyncReadyCallback callback,
++ gpointer user_data)
++{
++ GVariantBuilder builder;
++ const char *app_name = g_get_application_name ();
++ char *appid = NULL;
++ char *appid_escaped = NULL;
++ char *snid_escaped = NULL;
++ char *unit_name = NULL;
++
++ /* In this order:
++ * 1. Actual application ID from file
++ * 2. Stripping the .desktop from the desktop ID
++ * 3. Fall back to using the binary name
++ */
++ if (info->app_id)
++ appid = g_strdup (info->app_id);
++ else if (info->desktop_id && g_str_has_suffix (info->desktop_id, ".desktop"))
++ appid = g_strndup (info->desktop_id, strlen (info->desktop_id) - 8);
++ else
++ appid = g_path_get_basename (info->binary);
++
++ appid_escaped = systemd_unit_name_escape (appid);
++
++ /* Generate a name conforming to
++ * https://systemd.io/DESKTOP_ENVIRONMENTS/
++ * We use the PID to disambiguate, as that should be unique enough.
++ */
++ unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, pid);
++
++ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))"));
++ g_variant_builder_add (&builder, "s", unit_name);
++ g_variant_builder_add (&builder, "s", "fail");
++
++ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sv)"));
++
++ /* Add a generic human readable description, can be changed at will. */
++ if (app_name)
++ g_variant_builder_add (&builder,
++ "(sv)",
++ "Description",
++ g_variant_new_take_string (g_strdup_printf ("Application launched by %s",
++ app_name)));
++ g_variant_builder_add (&builder,
++ "(sv)",
++ "PIDs",
++ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, &pid, 1, 4));
++ /* Default to let systemd garbage collect failed applications we launched. */
++ g_variant_builder_add (&builder,
++ "(sv)",
++ "CollectMode",
++ g_variant_new_string ("inactive-or-failed"));
++
++ g_variant_builder_close (&builder);
++
++ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(sa(sv))"));
++ g_variant_builder_close (&builder);
++
++ g_dbus_connection_call (session_bus,
++ "org.freedesktop.systemd1",
++ "/org/freedesktop/systemd1",
++ "org.freedesktop.systemd1.Manager",
++ "StartTransientUnit",
++ g_variant_builder_end (&builder),
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NO_AUTO_START,
++ 1000,
++ NULL,
++ callback,
++ user_data);
++
++ g_free (appid);
++ g_free (appid_escaped);
++ g_free (snid_escaped);
++ g_free (unit_name);
++}
++
++static void
++systemd_scope_created_cb (GObject *object,
++ GAsyncResult *result,
++ gpointer user_data)
++{
++ GVariant *res = NULL;
++ GError *error = NULL;
++
++ res = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error);
++ if (error != NULL)
++ {
++ g_debug ("Failed to move new child into scope: %s", error->message);
++ g_error_free (error);
++ }
++
++ /* Unblock the waiting wrapper binary. */
++ close (GPOINTER_TO_INT (user_data));
++
++ if (res)
++ g_variant_unref (res);
++}
++#endif
++
+ static gboolean
+ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ GDBusConnection *session_bus,
+@@ -2750,13 +2892,14 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ GList *old_uris;
+ GList *dup_uris;
+
+- char **argv, **envp;
++ GStrv argv = NULL, envp = NULL;
++ GStrv wrapped_argv = NULL;
++ GList *launched_uris = NULL;
++ char *sn_id = NULL;
+ int argc;
+
+ g_return_val_if_fail (info != NULL, FALSE);
+
+- argv = NULL;
+-
+ if (launch_context)
+ envp = g_app_launch_context_get_environment (launch_context);
+ else
+@@ -2770,27 +2913,19 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ do
+ {
+ GPid pid;
+- GList *launched_uris;
+ GList *iter;
+- char *sn_id = NULL;
+- char **wrapped_argv;
+ int i;
+- gsize j;
+- const gchar * const wrapper_argv[] =
+- {
+- "/bin/sh",
+- "-e",
+- "-u",
+- "-c", "export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"",
+- "sh", /* argv[0] for sh */
+- };
++#if defined(__linux__) && !defined(__BIONIC__)
++ SpawnWrapperData wrapper_data;
++#endif
++ GSpawnChildSetupFunc setup = user_setup;
++ gpointer setup_data = user_setup_data;
+
+ old_uris = dup_uris;
+ if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error))
+- goto out;
++ return FALSE;
+
+ /* Get the subset of URIs we're launching with this process */
+- launched_uris = NULL;
+ for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next)
+ launched_uris = g_list_prepend (launched_uris, iter->data);
+ launched_uris = g_list_reverse (launched_uris);
+@@ -2799,7 +2934,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Unable to find terminal required for application"));
+- goto out;
++ return FALSE;
+ }
+
+ if (info->filename)
+@@ -2808,7 +2943,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ info->filename,
+ TRUE);
+
+- sn_id = NULL;
+ if (launch_context)
+ {
+ GList *launched_files = create_files_for_uris (launched_uris);
+@@ -2837,38 +2971,93 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ * with a wrapper program (grep the GLib git history for
+ * `gio-launch-desktop` for an example of this which could be
+ * resurrected). */
+- wrapped_argv = g_new (char *, argc + G_N_ELEMENTS (wrapper_argv) + 1);
++ wrapped_argv = g_new (char *, argc + 6 + 1);
++
++ wrapped_argv[0] = g_strdup ("/bin/sh");
++ wrapped_argv[1] = g_strdup ("-e");
++ wrapped_argv[2] = g_strdup ("-u");
++ wrapped_argv[3] = g_strdup ("-c");
++ /* argument 4 is filled in below */
++ wrapped_argv[5] = g_strdup ("sh");
+
+- for (j = 0; j < G_N_ELEMENTS (wrapper_argv); j++)
+- wrapped_argv[j] = g_strdup (wrapper_argv[j]);
+ for (i = 0; i < argc; i++)
+- wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = g_steal_pointer (&argv[i]);
++ wrapped_argv[i + 6] = g_steal_pointer (&argv[i]);
++
++ wrapped_argv[i + 6] = NULL;
++ g_clear_pointer (&argv, g_free);
++
++#if defined(__linux__) && !defined(__BIONIC__)
++ /* Create pipes, if we use a setup func, then set cloexec,
++ * otherwise our wrapper script will close both sides. */
++ if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL))
++ {
++ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ _("Unable to create pipe for systemd synchronization"));
++ return FALSE;
++ }
++
++ /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */
++ fcntl (wrapper_data.pipe[1], F_SETFD, FD_CLOEXEC);
+
+- wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = NULL;
+- g_free (argv);
+- argv = NULL;
++ if (!(spawn_flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
++ {
++ /* In this case, we use a setup function (which could probably also
++ * overwrite envp to set GIO_LAUNCHED_DESKTOP_FILE_PID).
++ *
++ * Note that this does not incur an additional cost because
++ * G_SPAWN_LEAVE_DESCRIPTOR_OPEN must be set in order to use
++ * posix_spawn. */
++ wrapper_data.user_setup = setup;
++ wrapper_data.user_setup_data = setup_data;
++
++ setup = launch_uris_with_spawn_delay_exec;
++ setup_data = &wrapper_data;
++ }
++
++ wrapped_argv[4] = g_strdup_printf ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; cat <&%1$d; exec \"$@\" %1$d<&-",
++ wrapper_data.pipe[0]);
++#else
++ wrapped_argv[4] = g_strdup ("export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"");
++#endif
+
+ if (!g_spawn_async_with_fds (info->path,
+ wrapped_argv,
+ envp,
+ spawn_flags,
+- user_setup,
+- user_setup_data,
++ setup,
++ setup_data,
+ &pid,
+ stdin_fd,
+ stdout_fd,
+ stderr_fd,
+ error))
+ {
++#if defined(__linux__) && !defined(__BIONIC__)
++ close (wrapper_data.pipe[0]);
++ close (wrapper_data.pipe[1]);
++#endif
++
+ if (sn_id)
+ g_app_launch_context_launch_failed (launch_context, sn_id);
+
+- g_free (sn_id);
+- g_list_free (launched_uris);
+-
+ goto out;
+ }
+
++#if defined(__linux__) && !defined(__BIONIC__)
++ /* We close write side asynchronously later on when the dbus call
++ * to systemd finishes. */
++ close (wrapper_data.pipe[0]);
++
++ if (session_bus)
++ create_systemd_scope (session_bus,
++ info,
++ pid,
++ systemd_scope_created_cb,
++ GINT_TO_POINTER (wrapper_data.pipe[1]));
++ else
++ close (wrapper_data.pipe[1]);
++#endif
++
+ if (pid_callback != NULL)
+ pid_callback (info, pid, pid_callback_data);
+
+@@ -2893,19 +3082,20 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ sn_id,
+ launched_uris);
+
+- g_free (sn_id);
+- g_list_free (launched_uris);
+-
+- g_strfreev (wrapped_argv);
+- wrapped_argv = NULL;
++ g_clear_pointer (&sn_id, g_free);
++ g_clear_pointer (&launched_uris, g_list_free);
++ g_clear_pointer (&wrapped_argv, g_strfreev);
+ }
+ while (dup_uris != NULL);
+
+ completed = TRUE;
+
+- out:
++out:
+ g_strfreev (argv);
+ g_strfreev (envp);
++ g_clear_pointer (&wrapped_argv, g_strfreev);
++ g_list_free (launched_uris);
++ g_free (sn_id);
+
+ return completed;
+ }
+--
+2.31.1
+
+From cd67a1b0256d2397dac0836e154f3449b63a6b19 Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Tue, 28 Jul 2020 12:11:13 +0200
+Subject: [PATCH 3/4] gdesktopappinfo: Handle task completion from spawn
+ function
+
+This allows delaying the return of the task until all dbus calls (in
+particular the ones to setup the scope) have finished.
+
+This fixes the behaviour of the previous commit which would not
+correctly move the process into the scope if the application exited
+right after the task returned.
+---
+ gio/gdesktopappinfo.c | 212 +++++++++++++++++++++++++++++-------------
+ 1 file changed, 146 insertions(+), 66 deletions(-)
+
+diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
+index afdcd42ac..8d0f1688e 100644
+--- a/gio/gdesktopappinfo.c
++++ b/gio/gdesktopappinfo.c
+@@ -2849,11 +2849,17 @@ create_systemd_scope (GDBusConnection *session_bus,
+ g_free (unit_name);
+ }
+
++typedef struct {
++ GTask *task;
++ int fd;
++} ScopeCreatedData;
++
+ static void
+ systemd_scope_created_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+ {
++ ScopeCreatedData *data = user_data;
+ GVariant *res = NULL;
+ GError *error = NULL;
+
+@@ -2865,13 +2871,47 @@ systemd_scope_created_cb (GObject *object,
+ }
+
+ /* Unblock the waiting wrapper binary. */
+- close (GPOINTER_TO_INT (user_data));
++
++ close (data->fd);
++
++ if (data->task)
++ {
++ gint pending;
++ pending = GPOINTER_TO_INT (g_task_get_task_data (data->task));
++ pending -= 1;
++ g_task_set_task_data (data->task, GINT_TO_POINTER (pending), NULL);
++
++ if (pending == 0 && !g_task_get_completed (data->task))
++ g_task_return_boolean (data->task, TRUE);
++ }
+
+ if (res)
+ g_variant_unref (res);
++ g_clear_object (&data->task);
++ g_free (data);
+ }
+ #endif
+
++static void
++launch_uris_with_spawn_flush_cb (GObject *object,
++ GAsyncResult *result,
++ gpointer user_data)
++{
++ GTask *task = G_TASK (user_data);
++ gint pending;
++
++ g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL);
++
++ pending = GPOINTER_TO_INT (g_task_get_task_data (task));
++ pending -= 1;
++ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
++
++ if (pending == 0 && !g_task_get_completed (task))
++ g_task_return_boolean (task, TRUE);
++
++ g_object_unref (task);
++}
++
+ static gboolean
+ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ GDBusConnection *session_bus,
+@@ -2886,9 +2926,10 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ gint stdin_fd,
+ gint stdout_fd,
+ gint stderr_fd,
+- GError **error)
++ GTask *task,
++ GError **error_out)
+ {
+- gboolean completed = FALSE;
++ GError *error = NULL;
+ GList *old_uris;
+ GList *dup_uris;
+
+@@ -2898,8 +2939,15 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ char *sn_id = NULL;
+ int argc;
+
++ /* We may get a task to report back on or an error. But never both. */
++ g_assert (!(task && error_out));
+ g_return_val_if_fail (info != NULL, FALSE);
+
++ /* Surrounding code must not have set any data on the task
++ * (it is cleared before calling this function). */
++ if (session_bus && task)
++ g_assert (g_task_get_task_data (task) == NULL);
++
+ if (launch_context)
+ envp = g_app_launch_context_get_environment (launch_context);
+ else
+@@ -2922,8 +2970,8 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ gpointer setup_data = user_setup_data;
+
+ old_uris = dup_uris;
+- if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error))
+- return FALSE;
++ if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, &error))
++ goto out;
+
+ /* Get the subset of URIs we're launching with this process */
+ for (iter = old_uris; iter != NULL && iter != dup_uris; iter = iter->next)
+@@ -2932,9 +2980,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+
+ if (info->terminal && !prepend_terminal_to_vector (&argc, &argv))
+ {
+- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+- _("Unable to find terminal required for application"));
+- return FALSE;
++ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
++ _("Unable to find terminal required for application"));
++ goto out;
+ }
+
+ if (info->filename)
+@@ -2991,9 +3039,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ * otherwise our wrapper script will close both sides. */
+ if (!g_unix_open_pipe (wrapper_data.pipe, 0, NULL))
+ {
+- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+- _("Unable to create pipe for systemd synchronization"));
+- return FALSE;
++ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
++ _("Unable to create pipe for systemd synchronization"));
++ goto out;
+ }
+
+ /* Set CLOEXEC on the write pipe, so we don't need to deal with it in the child. */
+@@ -3030,7 +3078,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ stdin_fd,
+ stdout_fd,
+ stderr_fd,
+- error))
++ &error))
+ {
+ #if defined(__linux__) && !defined(__BIONIC__)
+ close (wrapper_data.pipe[0]);
+@@ -3049,11 +3097,29 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ close (wrapper_data.pipe[0]);
+
+ if (session_bus)
+- create_systemd_scope (session_bus,
+- info,
+- pid,
+- systemd_scope_created_cb,
+- GINT_TO_POINTER (wrapper_data.pipe[1]));
++ {
++ ScopeCreatedData *data;
++
++ data = g_new0 (ScopeCreatedData, 1);
++
++ if (task)
++ {
++ gint pending;
++ pending = GPOINTER_TO_INT (g_task_get_task_data (task));
++ pending += 1;
++ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
++
++ data->task = g_object_ref (task);
++ }
++
++ data->fd = wrapper_data.pipe[1];
++
++ create_systemd_scope (session_bus,
++ info,
++ pid,
++ systemd_scope_created_cb,
++ data);
++ }
+ else
+ close (wrapper_data.pipe[1]);
+ #endif
+@@ -3088,8 +3154,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
+ }
+ while (dup_uris != NULL);
+
+- completed = TRUE;
+-
+ out:
+ g_strfreev (argv);
+ g_strfreev (envp);
+@@ -3097,7 +3161,52 @@ out:
+ g_list_free (launched_uris);
+ g_free (sn_id);
+
+- return completed;
++ if (!error)
++ {
++ if (session_bus && task)
++ {
++ GCancellable *cancellable = g_task_get_cancellable (task);
++ gint pending;
++ pending = GPOINTER_TO_INT (g_task_get_task_data (task));
++ pending += 1;
++ g_task_set_task_data (task, GINT_TO_POINTER (pending), NULL);
++
++ /* FIXME: The D-Bus message from the notify_desktop_launch() function
++ * can be still lost even if flush is called later. See:
++ * https://gitlab.freedesktop.org/dbus/dbus/issues/72
++ */
++ g_dbus_connection_flush (session_bus,
++ cancellable,
++ launch_uris_with_spawn_flush_cb,
++ g_steal_pointer (&task));
++ }
++ else if (session_bus)
++ {
++ /* No task available. */
++ g_dbus_connection_flush (session_bus,
++ NULL,
++ NULL,
++ NULL);
++ }
++ else if (task)
++ {
++ /* Return the given task. */
++ g_task_return_boolean (task, TRUE);
++ g_object_unref (task);
++ }
++ }
++ else
++ {
++ if (task)
++ {
++ g_task_return_error (task, error);
++ g_object_unref (task);
++ }
++ else
++ g_propagate_error (error_out, error);
++ }
++
++ return !error;
+ }
+
+ static gchar *
+@@ -3246,17 +3355,9 @@ g_desktop_app_info_launch_uris_internal (GAppInfo *appinfo,
+ success = g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec, uris, launch_context,
+ spawn_flags, user_setup, user_setup_data,
+ pid_callback, pid_callback_data,
+- stdin_fd, stdout_fd, stderr_fd, error);
++ stdin_fd, stdout_fd, stderr_fd, NULL, error);
+
+- if (session_bus != NULL)
+- {
+- /* This asynchronous flush holds a reference until it completes,
+- * which ensures that the following unref won't immediately kill
+- * the connection if we were the initial owner.
+- */
+- g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
+- g_object_unref (session_bus);
+- }
++ g_clear_object (&session_bus);
+
+ return success;
+ }
+@@ -3310,18 +3411,6 @@ launch_uris_with_dbus_cb (GObject *object,
+ g_object_unref (task);
+ }
+
+-static void
+-launch_uris_flush_cb (GObject *object,
+- GAsyncResult *result,
+- gpointer user_data)
+-{
+- GTask *task = G_TASK (user_data);
+-
+- g_dbus_connection_flush_finish (G_DBUS_CONNECTION (object), result, NULL);
+- g_task_return_boolean (task, TRUE);
+- g_object_unref (task);
+-}
+-
+ static void
+ launch_uris_bus_get_cb (GObject *object,
+ GAsyncResult *result,
+@@ -3330,12 +3419,20 @@ launch_uris_bus_get_cb (GObject *object,
+ GTask *task = G_TASK (user_data);
+ GDesktopAppInfo *info = G_DESKTOP_APP_INFO (g_task_get_source_object (task));
+ LaunchUrisData *data = g_task_get_task_data (task);
++ LaunchUrisData *data_copy = NULL;
+ GCancellable *cancellable = g_task_get_cancellable (task);
+ GDBusConnection *session_bus;
+- GError *error = NULL;
+
+ session_bus = g_bus_get_finish (result, NULL);
+
++ data_copy = g_new0 (LaunchUrisData, 1);
++ data_copy->appinfo = g_steal_pointer (&data->appinfo);
++ data_copy->uris = g_steal_pointer (&data->uris);
++ data_copy->context = g_steal_pointer (&data->context);
++
++ /* Allow other data to be attached to the task. */
++ g_task_set_task_data (task, NULL, NULL);
++
+ if (session_bus && info->app_id)
+ {
+ /* FIXME: The g_document_portal_add_documents() function, which is called
+@@ -3343,34 +3440,21 @@ launch_uris_bus_get_cb (GObject *object,
+ * uses blocking calls.
+ */
+ g_desktop_app_info_launch_uris_with_dbus (info, session_bus,
+- data->uris, data->context,
++ data_copy->uris, data_copy->context,
+ cancellable,
+ launch_uris_with_dbus_cb,
+ g_steal_pointer (&task));
+ }
+ else
+ {
+- /* FIXME: The D-Bus message from the notify_desktop_launch() function
+- * can be still lost even if flush is called later. See:
+- * https://gitlab.freedesktop.org/dbus/dbus/issues/72
+- */
+ g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec,
+- data->uris, data->context,
++ data_copy->uris, data_copy->context,
+ _SPAWN_FLAGS_DEFAULT, NULL,
+ NULL, NULL, NULL, -1, -1, -1,
+- &error);
+- if (error != NULL)
+- {
+- g_task_return_error (task, g_steal_pointer (&error));
+- g_object_unref (task);
+- }
+- else
+- g_dbus_connection_flush (session_bus,
+- cancellable,
+- launch_uris_flush_cb,
+- g_steal_pointer (&task));
++ g_steal_pointer (&task), NULL);
+ }
+
++ launch_uris_data_free (data_copy);
+ g_clear_object (&session_bus);
+ }
+
+@@ -5186,16 +5270,12 @@ g_desktop_app_info_launch_action (GDesktopAppInfo *info,
+ if (exec_line)
+ g_desktop_app_info_launch_uris_with_spawn (info, session_bus, exec_line, NULL, launch_context,
+ _SPAWN_FLAGS_DEFAULT, NULL, NULL, NULL, NULL,
+- -1, -1, -1, NULL);
++ -1, -1, -1, NULL, NULL);
+
+ g_free (exec_line);
+ }
+
+- if (session_bus != NULL)
+- {
+- g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
+- g_object_unref (session_bus);
+- }
++ g_clear_object (&session_bus);
+ }
+ /* Epilogue {{{1 */
+
+--
+2.31.1
+
+From 8da8a3ef6df8af6de8bd388192bebe8b51b3e782 Mon Sep 17 00:00:00 2001
+From: Benjamin Berg <bberg@redhat.com>
+Date: Thu, 17 Sep 2020 17:35:58 +0200
+Subject: [PATCH 4/4] gdesktopappinfo: Add SourcePath= to transient systemd
+ units
+
+systemd allows setting a SourcePath= which shows the file that the unit
+has been generated from. KDE is starting to set this and it seems like a
+good idea, so do the same here.
+
+See https://invent.kde.org/frameworks/kio/-/merge_requests/124
+---
+ gio/gdesktopappinfo.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
+index 8d0f1688e..a833de4e6 100644
+--- a/gio/gdesktopappinfo.c
++++ b/gio/gdesktopappinfo.c
+@@ -2777,6 +2777,7 @@ create_systemd_scope (GDBusConnection *session_bus,
+ {
+ GVariantBuilder builder;
+ const char *app_name = g_get_application_name ();
++ const char *source_path = NULL;
+ char *appid = NULL;
+ char *appid_escaped = NULL;
+ char *snid_escaped = NULL;
+@@ -2802,6 +2803,8 @@ create_systemd_scope (GDBusConnection *session_bus,
+ */
+ unit_name = g_strdup_printf ("app-glib-%s-%d.scope", appid_escaped, pid);
+
++ source_path = g_desktop_app_info_get_filename (info);
++
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssa(sv)a(sa(sv)))"));
+ g_variant_builder_add (&builder, "s", unit_name);
+ g_variant_builder_add (&builder, "s", "fail");
+@@ -2815,6 +2818,16 @@ create_systemd_scope (GDBusConnection *session_bus,
+ "Description",
+ g_variant_new_take_string (g_strdup_printf ("Application launched by %s",
+ app_name)));
++
++ /* If we have a .desktop file, document that the scope has been "generated"
++ * from it.
++ */
++ if (source_path && g_utf8_validate (source_path, -1, NULL))
++ g_variant_builder_add (&builder,
++ "(sv)",
++ "SourcePath",
++ g_variant_new_string (source_path));
++
+ g_variant_builder_add (&builder,
+ "(sv)",
+ "PIDs",
+--
+2.31.1
diff --git a/glib2.spec b/glib2.spec
index 91e031e..a45ca6e 100644
--- a/glib2.spec
+++ b/glib2.spec
@@ -1,25 +1,24 @@
+# https://bugzilla.redhat.com/show_bug.cgi?id=1973304
+%global __brp_check_rpaths %{nil}
+
Name: glib2
Version: 2.68.2
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: A library of handy utility functions
License: LGPLv2+
URL: http://www.gtk.org
Source0: http://download.gnome.org/sources/glib/2.68/glib-%{version}.tar.xz
-%if 0%{?rhel}
-# Required for RHEL core crypto components policy.
+# Required for RHEL core crypto components policy. Good for Fedora too.
+# https://bugzilla.redhat.com/show_bug.cgi?id=1630260
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/903
Patch0: gnutls-hmac.patch
-%endif
# Add patches to move applications into systemd scopes in compliance with
# https://systemd.io/DESKTOP_ENVIRONMENTS/
# Proposed upstream at https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1596
-Patch001: 0001-tests-Iterate-mainloop-during-launch-test.patch
-Patch002: 0002-gdesktopappinfo-Move-launched-applications-into-tran.patch
-Patch003: 0003-gdesktopappinfo-Handle-task-completion-from-spawn-fu.patch
-Patch004: 0004-gdesktopappinfo-Add-SourcePath-to-transient-systemd-.patch
+Patch1: gdesktopappinfo.patch
BuildRequires: chrpath
BuildRequires: gcc
@@ -34,10 +33,6 @@ BuildRequires: libselinux-devel
BuildRequires: meson
# for sys/sdt.h
BuildRequires: systemtap-sdt-devel
-%if 0%{?rhel}
-# For gnutls-hmac.patch
-BuildRequires: pkgconfig(gnutls)
-%endif
BuildRequires: pkgconfig(libelf)
BuildRequires: pkgconfig(libffi)
BuildRequires: pkgconfig(libpcre)
@@ -46,6 +41,15 @@ BuildRequires: pkgconfig(sysprof-capture-4)
BuildRequires: pkgconfig(zlib)
BuildRequires: python3-devel
+# For gnutls-hmac.patch. We now dlopen libgnutls.so.30 so that we can build a
+# static glib2 without depending on a static build of GnuTLS as well. This will
+# ensure we notice if the GnuTLS soname bumps, so that we can update our patch.
+%if 0%{__isa_bits} == 64
+Requires: libgnutls.so.30()(64bit)
+%else
+Requires: libgnutls.so.30()
+%endif
+
# for GIO content-type support
Recommends: shared-mime-info
@@ -82,14 +86,12 @@ BuildArch: noarch
%description doc
The glib2-doc package includes documentation for the GLib library.
-%if !0%{?rhel}
%package static
Summary: glib static
Requires: %{name}-devel = %{version}-%{release}
%description static
The %{name}-static subpackage contains static libraries for %{name}.
-%endif
%package tests
Summary: Tests for the glib2 package
@@ -107,9 +109,6 @@ the functionality of the installed glib2 package.
rm -rf glib/pcre
rm -rf subprojects
-# We cannot build with GnuTLS in Fedora since there is no gnutls-static
-# subpackage. (glib2-static is needed by qemu in Fedora, but not in RHEL.)
-# Accordingly, we can't build a usable glib2-static in RHEL.
%meson \
-Dman=true \
-Ddtrace=true \
@@ -118,12 +117,8 @@ rm -rf subprojects
-Dglib_debug=disabled \
-Dgtk_doc=true \
-Dinstalled_tests=true \
-%if 0%{?rhel}
-Dgnutls=true \
-%endif
-%if !0%{?rhel}
--default-library=both \
-%endif
%{nil}
%meson_build
@@ -233,20 +228,23 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
%files doc
%{_datadir}/gtk-doc/
-%if !0%{?rhel}
%files static
%{_libdir}/libgio-2.0.a
%{_libdir}/libglib-2.0.a
%{_libdir}/libgmodule-2.0.a
%{_libdir}/libgobject-2.0.a
%{_libdir}/libgthread-2.0.a
-%endif
%files tests
%{_libexecdir}/installed-tests
%{_datadir}/installed-tests
%changelog
+* Thu Jun 17 2021 Michael Catanzaro <mcatanzaro@redhat.com> - 2.68.2-2
+- Enable GnuTLS-based GHmac in Fedora and reenable glib2-static in RHEL
+- Consolidate GDesktopAppInfo changes into gdesktopappinfo.patch
+- Disable check-rpath since it seems to be broken
+
* Tue May 11 2021 Kalev Lember <klember@redhat.com> - 2.68.2-1
- Update to 2.68.2
diff --git a/gnutls-hmac.patch b/gnutls-hmac.patch
index 5d193f4..90ee2ee 100644
--- a/gnutls-hmac.patch
+++ b/gnutls-hmac.patch
@@ -1,7 +1,7 @@
-From 12e9cd51eb0ef07c3554cd035f92d8b7b5b82304 Mon Sep 17 00:00:00 2001
+From 86412ea2265ae018ba6146d525cafce78782c0fc Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Fri, 7 Jun 2019 18:44:43 +0000
-Subject: [PATCH 1/2] ghmac: Split off wrapper functions into ghmac-utils.c
+Subject: [PATCH 1/4] ghmac: Split off wrapper functions into ghmac-utils.c
Prep for adding a GnuTLS HMAC implementation; these are just
utility functions that call the "core" API.
@@ -284,10 +284,10 @@ index 49fd272f0..4f181f21f 100644
- (const guchar *) str, length);
-}
diff --git a/glib/meson.build b/glib/meson.build
-index 8c18e6de4..329b8d197 100644
+index 28bfae200..0a37d19ea 100644
--- a/glib/meson.build
+++ b/glib/meson.build
-@@ -253,6 +253,7 @@ glib_sources = files(
+@@ -254,6 +254,7 @@ glib_sources = files(
'ggettext.c',
'ghash.c',
'ghmac.c',
@@ -296,13 +296,12 @@ index 8c18e6de4..329b8d197 100644
'ghostutils.c',
'giochannel.c',
--
-2.29.2
+2.31.1
-
-From 231ed985074af4a354405cf1961fabf9c60bce43 Mon Sep 17 00:00:00 2001
+From a5ee9970772e182de1c249ee514e87ef38e08360 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Fri, 7 Jun 2019 19:36:54 +0000
-Subject: [PATCH 2/2] Add a gnutls backend for GHmac
+Subject: [PATCH 2/4] Add a gnutls backend for GHmac
For RHEL we want apps to use FIPS-certified crypto libraries,
and HMAC apparently counts as "keyed" and hence needs to
@@ -316,18 +315,47 @@ Most distributors ship glib-networking built with GnuTLS, and
most apps use glib-networking, so this isn't a net-new library
in most cases.
-mcatanzaro note: I've updated Colin's original patch to implement
-g_hmac_copy() using gnutls_hmac_copy(), which didn't exist when Colin
-developed this patch.
+=======================================================================
+
+mcatanzaro note:
+
+I've updated Colin's original patch with several enhancements:
+
+Implement g_hmac_copy() using gnutls_hmac_copy(), which didn't exist
+when Colin developed this patch.
+
+Removed use of GSlice
+
+Better error checking in g_hmac_new(). It is possible for
+gnutls_hmac_init() to fail if running in FIPS mode and an MD5 digest is
+requested. In this case, we should return NULL rather than returning a
+broken GHmac with a NULL gnutls_hmac_hd_t. This was leading to a later
+null pointer dereference inside gnutls_hmac_update(). Applications are
+responsible for checking to ensure the return value of g_hmac_new() is
+not NULL since it is annotated as nullable. Added documentation to
+indicate this possibility.
+
+Properly handle length -1 in g_hmac_update(). This means we've been
+given a NUL-terminated string and should use strlen(). GnuTLS doesn't
+accept -1, so let's call strlen() ourselves.
+
+Crash the application with g_error() if gnutls_hmac() fails for any
+reason. This is necessary because g_hmac_update() is not fallible, so we
+have no way to indicate error. Crashing seems better than returning the
+wrong result later when g_hmac_get_string() or g_hmac_get_digest() is
+later called. (Those functions are also not fallible.) Fortunately, I
+don't think this error should actually be hit in practice.
+
+https://gitlab.gnome.org/GNOME/glib/-/merge_requests/903
---
- glib/gchecksum.c | 9 ++-
- glib/gchecksumprivate.h | 32 ++++++++
- glib/ghmac-gnutls.c | 164 ++++++++++++++++++++++++++++++++++++++++
- glib/ghmac.c | 3 +
+ glib/gchecksum.c | 9 +-
+ glib/gchecksumprivate.h | 32 +++++++
+ glib/ghmac-gnutls.c | 187 ++++++++++++++++++++++++++++++++++++++++
+ glib/ghmac.c | 15 ++++
glib/meson.build | 10 ++-
meson.build | 7 ++
meson_options.txt | 5 ++
- 7 files changed, 224 insertions(+), 6 deletions(-)
+ 7 files changed, 259 insertions(+), 6 deletions(-)
create mode 100644 glib/gchecksumprivate.h
create mode 100644 glib/ghmac-gnutls.c
@@ -406,10 +434,10 @@ index 000000000..86c7a3b61
\ No newline at end of file
diff --git a/glib/ghmac-gnutls.c b/glib/ghmac-gnutls.c
new file mode 100644
-index 000000000..f1a74a849
+index 000000000..a55375060
--- /dev/null
+++ b/glib/ghmac-gnutls.c
-@@ -0,0 +1,164 @@
+@@ -0,0 +1,187 @@
+/* ghmac.h - data hashing functions
+ *
+ * Copyright (C) 2011 Collabora Ltd.
@@ -464,9 +492,11 @@ index 000000000..f1a74a849
+ gsize key_len)
+{
+ gnutls_mac_algorithm_t algo;
-+ GHmac *hmac = g_slice_new0 (GHmac);
++ GHmac *hmac = g_new0 (GHmac, 1);
++ int ret;
++
+ hmac->ref_count = 1;
-+ hmac->digest_type = digest_type;
++ hmac->digest_type = digest_type;
+
+ switch (digest_type)
+ {
@@ -489,7 +519,16 @@ index 000000000..f1a74a849
+ g_return_val_if_reached (NULL);
+ }
+
-+ gnutls_hmac_init (&hmac->hmac, algo, key, key_len);
++ ret = gnutls_hmac_init (&hmac->hmac, algo, key, key_len);
++ if (ret != 0)
++ {
++ /* There is no way to report an error here, but one possible cause of
++ * failure is that the requested digest may be disabled by Fedora or RHEL
++ * system crypto policy. As of 2021, MD5 and SHA-1 are likely disabled.
++ */
++ g_free (hmac->hmac);
++ return NULL;
++ }
+
+ return hmac;
+}
@@ -501,11 +540,15 @@ index 000000000..f1a74a849
+
+ g_return_val_if_fail (hmac != NULL, NULL);
+
-+ copy = g_slice_new0 (GHmac);
++ copy = g_new0 (GHmac, 1);
+ copy->ref_count = 1;
+ copy->digest_type = hmac->digest_type;
+ copy->hmac = gnutls_hmac_copy (hmac->hmac);
+
++ /* g_hmac_copy is not allowed to fail, so we'll have to crash on error. */
++ if (!copy->hmac)
++ g_error ("gnutls_hmac_copy failed");
++
+ return copy;
+}
+
@@ -528,7 +571,7 @@ index 000000000..f1a74a849
+ {
+ gnutls_hmac_deinit (hmac->hmac, NULL);
+ g_free (hmac->digest_str);
-+ g_slice_free (GHmac, hmac);
++ g_free (hmac);
+ }
+}
+
@@ -538,10 +581,18 @@ index 000000000..f1a74a849
+ const guchar *data,
+ gssize length)
+{
++ int ret;
++
+ g_return_if_fail (hmac != NULL);
+ g_return_if_fail (length == 0 || data != NULL);
+
-+ gnutls_hmac (hmac->hmac, data, length);
++ if (length == -1)
++ length = strlen ((const char *)data);
++
++ /* g_hmac_update is not allowed to fail, so we'll have to crash on error. */
++ ret = gnutls_hmac (hmac->hmac, data, length);
++ if (ret != 0)
++ g_error ("gnutls_hmac failed: %s", gnutls_strerror (ret));
+}
+
+const gchar *
@@ -575,7 +626,7 @@ index 000000000..f1a74a849
+ *digest_len = g_checksum_type_get_length (hmac->digest_type);
+}
diff --git a/glib/ghmac.c b/glib/ghmac.c
-index 4f181f21f..c62d9ce4e 100644
+index 4f181f21f..0e39ea40a 100644
--- a/glib/ghmac.c
+++ b/glib/ghmac.c
@@ -33,6 +33,9 @@
@@ -588,11 +639,30 @@ index 4f181f21f..c62d9ce4e 100644
/**
* SECTION:hmac
+@@ -84,6 +87,18 @@ struct _GHmac
+ * Support for digests of type %G_CHECKSUM_SHA512 has been added in GLib 2.42.
+ * Support for %G_CHECKSUM_SHA384 was added in GLib 2.52.
+ *
++ * Note that #GHmac creation may fail, in which case this function will
++ * return %NULL. Since there is no error parameter, it is not possible
++ * to indicate why.
++ *
++ * In Fedora, CentOS Stream, and Red Hat Enterprise Linux, GLib is
++ * configured to use GnuTLS to implement #GHmac in order to support FIPS
++ * compliance. This introduces additional failure possibilities that are
++ * not present in upstream GLib. For example, the creation of a #GHmac
++ * will fail if @digest_type is %G_CHECKSUM_MD5 and the system is
++ * running in FIPS mode. #GHmac creation may also fail if GLib is unable
++ * to load GnuTLS.
++ *
+ * Returns: the newly created #GHmac, or %NULL.
+ * Use g_hmac_unref() to free the memory allocated by it.
+ *
diff --git a/glib/meson.build b/glib/meson.build
-index 329b8d197..2942a7e9b 100644
+index 0a37d19ea..b17c89dd9 100644
--- a/glib/meson.build
+++ b/glib/meson.build
-@@ -252,7 +252,6 @@ glib_sources = files(
+@@ -253,7 +253,6 @@ glib_sources = files(
'gfileutils.c',
'ggettext.c',
'ghash.c',
@@ -600,7 +670,7 @@ index 329b8d197..2942a7e9b 100644
'ghmac-utils.c',
'ghook.c',
'ghostutils.c',
-@@ -308,6 +307,7 @@ glib_sources = files(
+@@ -309,6 +308,7 @@ glib_sources = files(
'guriprivate.h',
'gutils.c',
'gutilsprivate.h',
@@ -608,7 +678,7 @@ index 329b8d197..2942a7e9b 100644
'guuid.c',
'gvariant.c',
'gvariant-core.c',
-@@ -352,6 +352,12 @@ else
+@@ -353,6 +353,12 @@ else
glib_dtrace_hdr = []
endif
@@ -621,7 +691,7 @@ index 329b8d197..2942a7e9b 100644
pcre_static_args = []
if use_pcre_static_flag
-@@ -378,7 +384,7 @@ libglib = library('glib-2.0',
+@@ -379,7 +385,7 @@ libglib = library('glib-2.0',
# intl.lib is not compatible with SAFESEH
link_args : [noseh_link_args, glib_link_flags, win32_ldflags],
include_directories : configinc,
@@ -631,10 +701,10 @@ index 329b8d197..2942a7e9b 100644
objc_args : glib_c_args,
)
diff --git a/meson.build b/meson.build
-index 0d892fb2d..091029fea 100644
+index a0ee8b774..064dba800 100644
--- a/meson.build
+++ b/meson.build
-@@ -2078,6 +2078,13 @@ if host_system == 'linux'
+@@ -2104,6 +2104,13 @@ if host_system == 'linux'
glib_conf.set('HAVE_LIBMOUNT', libmount_dep.found())
endif
@@ -665,5 +735,351 @@ index 072765361..d2370042f 100644
type : 'boolean',
value : false,
--
-2.29.2
+2.31.1
+
+From cde56a63aa12ae7c30f85af7d058fa5e666aa2e9 Mon Sep 17 00:00:00 2001
+From: Michael Catanzaro <mcatanzaro@redhat.com>
+Date: Wed, 16 Jun 2021 20:35:00 -0500
+Subject: [PATCH 3/4] dlopen GnuTLS instead of linking directly
+
+I'd like to enable our GnuTLS GHmac patchset in Fedora in order to
+ensure it is receiving sufficient real-world testing, since we've
+discovered several bugs thus far. Problem is Fedora has one requirement
+that RHEL does not: it needs to build glib as a static lib. This is
+needed by QEMU in Fedora for complicated technical reasons that I don't
+understand. However, nothing in RHEL needs it. This means we failed to
+notice that glib2-static is broken in RHEL, because there is no
+gnutls-static! We could fix this by adding a gnutls-static package, but
+that seems like overkill, and adding more static libraries where they're
+not truly necessary is not the direction we want to move in anyway. So
+instead, let's just dlopen GnuTLS to sidestep this problem entirely.
+This would not be a good solution for upstream, but upstream has made
+clear that this patchset is already non-upstreamable, so it will be fine
+for our purposes.
+---
+ glib/ghmac-gnutls.c | 101 ++++++++++++++++++++++++++++++++++++++++++--
+ glib/ghmac.c | 2 +-
+ glib/meson.build | 2 +-
+ meson.build | 6 +--
+ 4 files changed, 102 insertions(+), 9 deletions(-)
+
+diff --git a/glib/ghmac-gnutls.c b/glib/ghmac-gnutls.c
+index a55375060..0469d2bd0 100644
+--- a/glib/ghmac-gnutls.c
++++ b/glib/ghmac-gnutls.c
+@@ -19,8 +19,8 @@
+
+ #include "config.h"
+
++#include <dlfcn.h>
+ #include <string.h>
+-#include <gnutls/crypto.h>
+
+ #include "ghmac.h"
+
+@@ -31,13 +31,16 @@
+ #include "gstrfuncs.h"
+ #include "gchecksumprivate.h"
+ #include "gtestutils.h"
++#include "gthread.h"
+ #include "gtypes.h"
+ #include "glibintl.h"
+
+-#ifndef HAVE_GNUTLS
++#ifndef USE_GNUTLS
+ #error "build configuration error"
+ #endif
+
++typedef gpointer gnutls_hmac_hd_t;
++
+ struct _GHmac
+ {
+ int ref_count;
+@@ -46,15 +49,107 @@ struct _GHmac
+ gchar *digest_str;
+ };
+
++typedef enum
++{
++ GNUTLS_MAC_MD5 = 2,
++ GNUTLS_MAC_SHA1 = 3,
++ GNUTLS_MAC_SHA256 = 6,
++ GNUTLS_MAC_SHA384 = 7,
++ GNUTLS_MAC_SHA512 = 8,
++} gnutls_mac_algorithm_t;
++
++/* Why are we dlopening GnuTLS instead of linking to it directly? Because we
++ * want to be able to build GLib as a static library without depending on a
++ * static build of GnuTLS. QEMU depends on static linking with GLib, but Fedora
++ * does not ship a static build of GnuTLS, and this allows us to avoid changing
++ * that.
++ */
++static int (*gnutls_hmac_init) (gnutls_hmac_hd_t *dig, gnutls_mac_algorithm_t algorithm, const void *key, size_t keylen);
++static gnutls_hmac_hd_t (*gnutls_hmac_copy) (gnutls_hmac_hd_t handle);
++static void (*gnutls_hmac_deinit) (gnutls_hmac_hd_t handle, void *digest);
++static int (*gnutls_hmac) (gnutls_hmac_hd_t handle, const void *ptext, size_t ptext_len);
++static void (*gnutls_hmac_output) (gnutls_hmac_hd_t handle, void *digest);
++static const char * (*gnutls_strerror) (int error);
++
++static gsize gnutls_initialize_attempted = 0;
++static gboolean gnutls_initialize_successful = FALSE;
++
++static void
++initialize_gnutls (void)
++{
++ gpointer libgnutls;
++
++ libgnutls = dlopen ("libgnutls.so.30", RTLD_LAZY | RTLD_GLOBAL);
++ if (!libgnutls)
++ {
++ g_warning ("Cannot use GHmac: failed to load libgnutls.so.30: %s", dlerror ());
++ return;
++ }
++
++ gnutls_hmac_init = dlsym (libgnutls, "gnutls_hmac_init");
++ if (!gnutls_hmac_init)
++ {
++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_init: %s", dlerror ());
++ return;
++ }
++
++ gnutls_hmac_copy = dlsym (libgnutls, "gnutls_hmac_copy");
++ if (!gnutls_hmac_copy)
++ {
++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_copy: %s", dlerror ());
++ return;
++ }
++
++ gnutls_hmac_deinit = dlsym (libgnutls, "gnutls_hmac_deinit");
++ if (!gnutls_hmac_deinit)
++ {
++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_deinit: %s", dlerror ());
++ return;
++ }
++
++ gnutls_hmac = dlsym (libgnutls, "gnutls_hmac");
++ if (!gnutls_hmac)
++ {
++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac: %s", dlerror ());
++ return;
++ }
++
++ gnutls_hmac_output = dlsym (libgnutls, "gnutls_hmac_output");
++ if (!gnutls_hmac_output)
++ {
++ g_warning ("Cannot use GHmac: failed to load gnutls_hmac_output: %s", dlerror ());
++ return;
++ }
++
++ gnutls_strerror = dlsym (libgnutls, "gnutls_strerror");
++ if (!gnutls_strerror)
++ {
++ g_warning ("Cannot use GHmac: failed to load gnutls_strerror: %s", dlerror ());
++ return;
++ }
++
++ gnutls_initialize_successful = TRUE;
++}
++
+ GHmac *
+ g_hmac_new (GChecksumType digest_type,
+ const guchar *key,
+ gsize key_len)
+ {
+ gnutls_mac_algorithm_t algo;
+- GHmac *hmac = g_new0 (GHmac, 1);
++ GHmac *hmac;
+ int ret;
+
++ if (g_once_init_enter (&gnutls_initialize_attempted))
++ {
++ initialize_gnutls ();
++ g_once_init_leave (&gnutls_initialize_attempted, 1);
++ }
++
++ if (!gnutls_initialize_successful)
++ return NULL;
++
++ hmac = g_new0 (GHmac, 1);
+ hmac->ref_count = 1;
+ hmac->digest_type = digest_type;
+
+diff --git a/glib/ghmac.c b/glib/ghmac.c
+index 0e39ea40a..2d9be91b8 100644
+--- a/glib/ghmac.c
++++ b/glib/ghmac.c
+@@ -33,7 +33,7 @@
+ #include "gtypes.h"
+ #include "glibintl.h"
+
+-#ifdef HAVE_GNUTLS
++#ifdef USE_GNUTLS
+ #error "build configuration error"
+ #endif
+
+diff --git a/glib/meson.build b/glib/meson.build
+index b17c89dd9..a015f7755 100644
+--- a/glib/meson.build
++++ b/glib/meson.build
+@@ -385,7 +385,7 @@ libglib = library('glib-2.0',
+ # intl.lib is not compatible with SAFESEH
+ link_args : [noseh_link_args, glib_link_flags, win32_ldflags],
+ include_directories : configinc,
+- dependencies : pcre_deps + libgnutls_dep + [thread_dep, librt] + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep],
++ dependencies : pcre_deps + [thread_dep, librt] + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep] + [libdl_dep],
+ c_args : glib_c_args,
+ objc_args : glib_c_args,
+ )
+diff --git a/meson.build b/meson.build
+index 064dba800..7aae7dfea 100644
+--- a/meson.build
++++ b/meson.build
+@@ -2104,11 +2104,9 @@ if host_system == 'linux'
+ glib_conf.set('HAVE_LIBMOUNT', libmount_dep.found())
+ endif
+
+-# gnutls is used optionally by ghmac
+-libgnutls_dep = []
++# gnutls is used optionally by GHmac
+ if get_option('gnutls')
+- libgnutls_dep = [dependency('gnutls', version : '>=3.6.9', required : true)]
+- glib_conf.set('HAVE_GNUTLS', 1)
++ glib_conf.set('USE_GNUTLS', 1)
+ endif
+
+ if host_system == 'windows'
+--
+2.31.1
+
+From b61ea19037287cae2e6152e9616767a691bf4af0 Mon Sep 17 00:00:00 2001
+From: Michael Catanzaro <mcatanzaro@redhat.com>
+Date: Wed, 16 Jun 2021 20:46:24 -0500
+Subject: [PATCH 4/4] Add test for GHmac in FIPS mode
+
+This will test a few problems that we hit recently:
+
+g_hmac_copy() is broken, https://bugzilla.redhat.com/show_bug.cgi?id=1786538
+
+Crash in g_hmac_update() in FIPS mode, https://bugzilla.redhat.com/show_bug.cgi?id=1971533
+
+Crash when passing -1 length to g_hmac_update() (discovered in #1971533)
+
+We'll also test to ensure MD5 fails, and stop compiling the other MD5
+tests.
+---
+ glib/tests/hmac.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 45 insertions(+)
+
+diff --git a/glib/tests/hmac.c b/glib/tests/hmac.c
+index 3ac3206df..6698c4d19 100644
+--- a/glib/tests/hmac.c
++++ b/glib/tests/hmac.c
+@@ -1,7 +1,10 @@
++#include "config.h"
++
+ #include <glib.h>
+ #include <string.h>
+ #include <stdlib.h>
+
++#ifndef USE_GNUTLS
+ /* HMAC-MD5 test vectors as per RFC 2202 */
+
+ /* Test 1 */
+@@ -81,6 +84,7 @@ guint8 key_md5_test7[] = {
+ guint8 result_md5_test7[] = {
+ 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, 0x1f, 0xb1,
+ 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e };
++#endif
+
+ /* HMAC-SHA1, HMAC-SHA256, HMAC-SHA384 and HMAC-SHA512 test vectors
+ * as per RFCs 2202 and 4868.
+@@ -299,6 +303,7 @@ typedef struct {
+ gconstpointer result;
+ } HmacCase;
+
++#ifndef USE_GNUTLS
+ HmacCase hmac_md5_tests[] = {
+ { G_CHECKSUM_MD5, key_md5_test1, 16, "Hi There", 8, result_md5_test1 },
+ { G_CHECKSUM_MD5, "Jefe", 4, "what do ya want for nothing?", 28,
+@@ -317,6 +322,7 @@ HmacCase hmac_md5_tests[] = {
+ 73, result_md5_test7 },
+ { -1, NULL, 0, NULL, 0, NULL },
+ };
++#endif
+
+ HmacCase hmac_sha1_tests[] = {
+ { G_CHECKSUM_SHA1, key_sha_test1, 20, "Hi There", 8, result_sha1_test1 },
+@@ -493,11 +499,44 @@ test_hmac_for_bytes (void)
+ g_bytes_unref (data);
+ }
+
++#ifdef USE_GNUTLS
++static void
++test_gnutls_fips_mode (void)
++{
++ GHmac *hmac;
++ GHmac *copy;
++
++ /* No MD5 in FIPS mode. */
++ hmac = g_hmac_new (G_CHECKSUM_MD5, "abc123", sizeof ("abc123"));
++ g_assert_null (hmac);
++
++ /* SHA-256 should be good. */
++ hmac = g_hmac_new (G_CHECKSUM_SHA256, "abc123", sizeof ("abc123"));
++ g_assert_nonnull (hmac);
++
++ /* Ensure g_hmac_update() does not crash when called with -1. */
++ g_hmac_update (hmac, "You win again, gravity!", -1);
++
++ /* Ensure g_hmac_copy() does not crash. */
++ copy = g_hmac_copy (hmac);
++ g_assert_nonnull (hmac);
++ g_hmac_unref (hmac);
++
++ g_assert_cmpstr (g_hmac_get_string (copy), ==, "795ba6900bcb22e8ce65c2ec02db4e85697da921deb960ee3143bf88a4a60f83");
++ g_hmac_unref (copy);
++}
++#endif
++
+ int
+ main (int argc,
+ char **argv)
+ {
+ int i;
++
++#ifdef USE_GNUTLS
++ g_setenv ("GNUTLS_FORCE_FIPS_MODE", "1", FALSE);
++#endif
++
+ g_test_init (&argc, &argv, NULL);
+
+ for (i = 0 ; hmac_sha1_tests[i].key_len > 0 ; i++)
+@@ -532,6 +571,7 @@ main (int argc,
+ g_free (name);
+ }
+
++#ifndef USE_GNUTLS
+ for (i = 0 ; hmac_md5_tests[i].key_len > 0 ; i++)
+ {
+ gchar *name = g_strdup_printf ("/hmac/md5-%d", i + 1);
+@@ -539,6 +579,7 @@ main (int argc,
+ (void (*)(const void *)) test_hmac);
+ g_free (name);
+ }
++#endif
+
+ g_test_add_func ("/hmac/ref-unref", test_hmac_ref_unref);
+ g_test_add_func ("/hmac/copy", test_hmac_copy);
+@@ -546,5 +587,9 @@ main (int argc,
+ g_test_add_func ("/hmac/for-string", test_hmac_for_string);
+ g_test_add_func ("/hmac/for-bytes", test_hmac_for_bytes);
+
++#ifdef USE_GNUTLS
++ g_test_add_func ("/hmac/gnutls-fips-mode", test_gnutls_fips_mode);
++#endif
++
+ return g_test_run ();
+ }
+--
+2.31.1
reply other threads:[~2026-08-11 10:37 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178644464440.1.11313599040704646782.rpms-glib2-1f79f0520372@fedoraproject.org \
--to=mcatanzaro@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox