Skip to content

Commit e206603

Browse files
ppisarjrohel
authored andcommitted
PGP: Enable creating a UID directory for GnuGP agent socket in /run/gnupg/user
librepo used to precreate the directory in /run/user to make sure a GnuPG agent executed by GPGME library, one of librepo's PGP backends, places its socket there. The UID directories there are normally created and removed by systemd (logind PAM session). librepo created them for a case when a package manager is invoked out of systemd session, before the super user logs in. E.g. by a timer job to cache repository metadata. A problem was when this out-of-session process was a SELinux-confined process creating files with its own SELinux label. Then the UID directory was created with a SELinux label different from the one expected by systemd. Later, the mismatching label interfered with systemd when logging out a corresponding user. This patch fixes it by creating the UID directories in a different path which is not managed by systemd. That path is /run/gnupg/user. GnuPG recognizes the path if it is compiled with --enable-run-gnupg-user-socket option. Unfortunatelly, this patch cannot keep precreating directories in the old /run/user path for compatibility with GnuPG built without that option because that would still break systemd. Also GPGME does not provide a way for checking how GnuPG was configured. Therefore users who rely on precreating the directories by librepo need to keep their librepo and GnuPG in synchronization. So this patch adds a new -DUSE_RUN_GNUPG_USER_SOCKET=ON CMake option to use /run/gnupg/user. A default behavior is using the old /run/user. https://issues.redhat.com/browse/RHEL-10720
1 parent f097eef commit e206603

3 files changed

Lines changed: 41 additions & 7 deletions

File tree

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ OPTION (ENABLE_DOCS "Build docs?" ON)
66
OPTION (WITH_ZCHUNK "Build with zchunk support" ON)
77
OPTION (ENABLE_PYTHON "Build Python bindings" ON)
88
OPTION (USE_GPGME "Use GpgMe (instead of rpm library) for OpenPGP key support" ON)
9+
OPTION (USE_RUN_GNUPG_USER_SOCKET "Create a directory for gpg-agent socket in /run/gnugp/user (instead of /run/user)" OFF)
910

1011
INCLUDE (${CMAKE_SOURCE_DIR}/VERSION.cmake)
1112
SET (VERSION "${LIBREPO_MAJOR}.${LIBREPO_MINOR}.${LIBREPO_PATCH}")
@@ -59,6 +60,11 @@ ELSE (USE_GPGME)
5960
UNSET(CMAKE_REQUIRED_LIBRARIES)
6061
ENDIF (USE_GPGME)
6162

63+
IF (USE_RUN_GNUPG_USER_SOCKET)
64+
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_RUN_GNUPG_USER_SOCKET")
65+
SET (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DUSE_RUN_GNUPG_USER_SOCKET")
66+
ENDIF (USE_RUN_GNUPG_USER_SOCKET)
67+
6268
IF (WITH_ZCHUNK)
6369
PKG_CHECK_MODULES(ZCHUNKLIB zck>=0.9.11 REQUIRED)
6470
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWITH_ZCHUNK")

librepo.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
%bcond_without use_gpgme
1515
%endif
1616

17+
# Needs to match how gnupg2 is compiled
18+
%bcond_with run_gnupg_user_socket
19+
1720
%global dnf_conflict 2.8.8
1821

1922
Name: librepo
@@ -78,7 +81,8 @@ Python 3 bindings for the librepo library.
7881
%build
7982
%cmake \
8083
-DWITH_ZCHUNK=%{?with_zchunk:ON}%{!?with_zchunk:OFF} \
81-
-DUSE_GPGME=%{?with_use_gpgme:ON}%{!?with_use_gpgme:OFF}
84+
-DUSE_GPGME=%{?with_use_gpgme:ON}%{!?with_use_gpgme:OFF} \
85+
-DUSE_RUN_GNUPG_USER_SOCKET=%{?with_run_gnupg_user_socket:ON}%{!?with_run_gnupg_user_socket:OFF}
8286
%cmake_build
8387

8488
%check

librepo/gpg_gpgme.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <fcntl.h>
2626
#include <errno.h>
2727
#include <gpgme.h>
28+
#include <stdint.h>
2829
#include <unistd.h>
2930

3031
#include "gpg.h"
@@ -33,9 +34,9 @@
3334
#include "util.h"
3435

3536
/*
36-
* Creates the '/run/user/$UID' directory if it doesn't exist. If this
37+
* Creates the '/run/gnupg/user/$UID' directory if it doesn't exist. If this
3738
* directory exists, gpgagent will create its sockets under
38-
* '/run/user/$UID/gnupg'.
39+
* '/run/gnupg/user/$UID/gnupg'.
3940
*
4041
* If this directory doesn't exist, gpgagent will create its sockets in gpg
4142
* home directory, which is under '/var/cache/yum/metadata/' and this was
@@ -44,22 +45,45 @@
4445
* Previous solution was to send the agent a "KILLAGENT" message, but that
4546
* would cause a race condition with calling gpgme_release(), see [2], [3].
4647
*
48+
* Another previous solution used /run/user/$UID which showed problematic when
49+
* this library was used out of an systemd-logind session. Then /run/user/$UID,
50+
* normally maintained by systemd, was assigned a SELinux label unexpected by
51+
* systemd causing errors on a user logout [4].
52+
*
4753
* Since the agent doesn't clean up its sockets properly, by creating this
4854
* directory we make sure they are in a place that is not causing trouble with
4955
* container images.
5056
*
5157
* [1] https://bugzilla.redhat.com/show_bug.cgi?id=1650266
5258
* [2] https://bugzilla.redhat.com/show_bug.cgi?id=1769831
5359
* [3] https://github.com/rpm-software-management/microdnf/issues/50
60+
* [4] https://issues.redhat.com/browse/RHEL-6421
5461
*/
5562
static void
5663
lr_gpg_ensure_socket_dir_exists()
5764
{
65+
#ifdef DUSE_RUN_GNUPG_USER_SOCKET
66+
const char *templates[] = { "/run/gnupg", "/run/gnupg/user", "/run/gnupg/user/%ju", NULL };
67+
const mode_t modes[] = { 0755, 0755, 0700, 0 };
68+
#else
69+
const char *templates[] = { "/run/user/%ju", NULL };
70+
const mode_t modes[] = { 0700, 0 };
71+
#endif
72+
const uid_t uid = getuid();
5873
char dirname[32];
59-
snprintf(dirname, sizeof(dirname), "/run/user/%u", getuid());
60-
int res = mkdir(dirname, 0700);
61-
if (res != 0 && errno != EEXIST) {
62-
g_debug("Failed to create \"%s\": %d - %s\n", dirname, errno, strerror(errno));
74+
int res;
75+
76+
for (int i = 0; templates[i] != NULL; i++) {
77+
res = snprintf(dirname, sizeof(dirname), templates[i], (uintmax_t)uid);
78+
if (res >= sizeof(dirname)) {
79+
g_debug("Failed to format a GnuPG agent socket path because of a small buffer");
80+
return;
81+
}
82+
res = mkdir(dirname, modes[i]);
83+
if (res != 0 && errno != EEXIST) {
84+
g_debug("Failed to create \"%s\": %d - %s\n", dirname, errno, strerror(errno));
85+
return;
86+
}
6387
}
6488
}
6589

0 commit comments

Comments
 (0)