chantra / rpms / librepo

Forked from rpms/librepo 2 years ago
Clone

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

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