Blame SOURCES/0001-Create-a-directory-for-gpg-sockets-in-run-user-RhBug.patch

37b9c9
From d474bcad3fdca0e009f24e11d927a3cdc7fd6a55 Mon Sep 17 00:00:00 2001
37b9c9
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
37b9c9
Date: Wed, 27 Nov 2019 16:15:20 +0100
37b9c9
Subject: [PATCH] Create a directory for gpg sockets in /run/user/
37b9c9
 (RhBug:1769831,1771012)
37b9c9
37b9c9
The solution of sending the "KILLAGENT" message to gpgagent to make it
37b9c9
clean up its sockets in gpg home dir is causing a race condition with
37b9c9
the gpgme_release() function.
37b9c9
37b9c9
Instead of trying to make the agent clean up its sockets (which doesn't
37b9c9
seem to be reliably possible), take advantage of its feature to create
37b9c9
the sockets under '/run/user/$UID' if this directory is present. The
37b9c9
sockets shouldn't be causing any trouble in this directory.
37b9c9
37b9c9
The commit creates the '/run/user/$UID' directory if it's not present on
37b9c9
the system. The sockets are then created there.
37b9c9
37b9c9
https://bugzilla.redhat.com/show_bug.cgi?id=1769831
37b9c9
https://bugzilla.redhat.com/show_bug.cgi?id=1771012
37b9c9
---
37b9c9
 librepo/gpg.c | 56 +++++++++++++++++++++++++--------------------------
37b9c9
 1 file changed, 28 insertions(+), 28 deletions(-)
37b9c9
37b9c9
diff --git a/librepo/gpg.c b/librepo/gpg.c
37b9c9
index a019015..a134d44 100644
37b9c9
--- a/librepo/gpg.c
37b9c9
+++ b/librepo/gpg.c
37b9c9
@@ -32,28 +32,33 @@
37b9c9
 #include "util.h"
37b9c9
 #include "gpg.h"
37b9c9
 
37b9c9
-static void
37b9c9
-kill_gpg_agent(gpgme_ctx_t context, const char *home_dir)
37b9c9
-{
37b9c9
-    gpgme_error_t gpgerr;
37b9c9
-
37b9c9
-    gpgerr = gpgme_set_protocol(context, GPGME_PROTOCOL_ASSUAN);
37b9c9
-    if (gpgerr != GPG_ERR_NO_ERROR) {
37b9c9
-        g_warning("%s: gpgme_set_protocol: %s", __func__, gpgme_strerror(gpgerr));
37b9c9
-        return;
37b9c9
-    }
37b9c9
-    if (home_dir) {
37b9c9
-        gchar * gpg_agent_sock = g_build_filename(home_dir, "S.gpg-agent", NULL);
37b9c9
-        gpgerr = gpgme_ctx_set_engine_info(context, GPGME_PROTOCOL_ASSUAN, gpg_agent_sock, home_dir);
37b9c9
-        g_free(gpg_agent_sock);
37b9c9
-        if (gpgerr != GPG_ERR_NO_ERROR) {
37b9c9
-            g_warning("%s: gpgme_ctx_set_engine_info: %s", __func__, gpgme_strerror(gpgerr));
37b9c9
-            return;
37b9c9
-        }
37b9c9
+/*
37b9c9
+ * Creates the '/run/user/$UID' directory if it doesn't exist. If this
37b9c9
+ * directory exists, gpgagent will create its sockets under
37b9c9
+ * '/run/user/$UID/gnupg'.
37b9c9
+ *
37b9c9
+ * If this directory doesn't exist, gpgagent will create its sockets in gpg
37b9c9
+ * home directory, which is under '/var/cache/yum/metadata/' and this was
37b9c9
+ * causing trouble with container images, see [1].
37b9c9
+ *
37b9c9
+ * Previous solution was to send the agent a "KILLAGENT" message, but that
37b9c9
+ * would cause a race condition with calling gpgme_release(), see [2], [3].
37b9c9
+ *
37b9c9
+ * Since the agent doesn't clean up its sockets properly, by creating this
37b9c9
+ * directory we make sure they are in a place that is not causing trouble with
37b9c9
+ * container images.
37b9c9
+ *
37b9c9
+ * [1] https://bugzilla.redhat.com/show_bug.cgi?id=1650266
37b9c9
+ * [2] https://bugzilla.redhat.com/show_bug.cgi?id=1769831
37b9c9
+ * [3] https://github.com/rpm-software-management/microdnf/issues/50
37b9c9
+ */
37b9c9
+void ensure_socket_dir_exists() {
37b9c9
+    char dirname[32];
37b9c9
+    snprintf(dirname, sizeof(dirname), "/run/user/%u", getuid());
37b9c9
+    int res = mkdir(dirname, 0700);
37b9c9
+    if (res != 0 && errno != EEXIST) {
37b9c9
+        g_debug("Failed to create \"%s\": %d - %s\n", dirname, errno, strerror(errno));
37b9c9
     }
37b9c9
-    gpgerr = gpgme_op_assuan_transact_ext(context, "KILLAGENT", NULL, NULL, NULL, NULL, NULL, NULL, NULL);
37b9c9
-    if (gpgerr != GPG_ERR_NO_ERROR)
37b9c9
-        g_debug("%s: gpgme_op_assuan_transact_ext: %s", __func__, gpgme_strerror(gpgerr));
37b9c9
 }
37b9c9
 
37b9c9
 gboolean
37b9c9
@@ -239,6 +244,8 @@ lr_gpg_import_key(const char *key_fn, const char *home_dir, GError **err)
37b9c9
 
37b9c9
     assert(!err || *err == NULL);
37b9c9
 
37b9c9
+    ensure_socket_dir_exists();
37b9c9
+
37b9c9
     // Initialization
37b9c9
     gpgme_check_version(NULL);
37b9c9
     gpgerr = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
37b9c9
@@ -320,13 +327,6 @@ lr_gpg_import_key(const char *key_fn, const char *home_dir, GError **err)
37b9c9
 
37b9c9
     close(key_fd);
37b9c9
 
37b9c9
-    // Running gpg-agent kept opened sockets on the system.
37b9c9
-    // It tries to exit gpg-agent. Path to the communication socket is derived from homedir.
37b9c9
-    // The gpg-agent automaticaly removes all its socket before exit.
37b9c9
-    // Newer gpg-agent creates sockets under [/var]/run/user/{pid}/... if directory exists.
37b9c9
-    // In this case gpg-agent will not be exited.
37b9c9
-    kill_gpg_agent(context, home_dir);
37b9c9
-
37b9c9
     gpgme_release(context);
37b9c9
 
37b9c9
     return TRUE;
37b9c9
-- 
37b9c9
2.24.0
37b9c9