Skip to content

Commit

Permalink
PGP: Set a default creation SELinux labels on GnuPG directories
Browse files Browse the repository at this point in the history
This is another way how to fix mismatching SELinux context on
/run/user directories without moving the directories to
/run/gnupg/user.

librepo used to precreate the directory in /run/user to make sure
a GnuPG agent executed by GPGME library places its socket there.

The 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 different from a DNF
program. Then the directory was created with a SELinux label different
from the one expected by systemd and when logging out a corresponding
user, the mismatching label clashed with systemd.

This patch fixes the issue by choosing a SELinux label of those
directories to the label defined in a default SELinux file context
database.

This patch adds a new -DENABLE_SELINUX=OFF CMake option to disable the
new dependency on libselinux. A default behavior is to support SELinux
only if GPGME backend is selected with -DUSE_GPGME=ON.

https://issues.redhat.com/browse/RHEL-10720
  • Loading branch information
ppisar committed Oct 18, 2023
1 parent e206603 commit 81602bb
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 7 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ OPTION (WITH_ZCHUNK "Build with zchunk support" ON)
OPTION (ENABLE_PYTHON "Build Python bindings" ON)
OPTION (USE_GPGME "Use GpgMe (instead of rpm library) for OpenPGP key support" ON)
OPTION (USE_RUN_GNUPG_USER_SOCKET "Create a directory for gpg-agent socket in /run/gnugp/user (instead of /run/user)" OFF)
OPTION (ENABLE_SELINUX "Restore SELinux labels on GnuPG directories" ON)

INCLUDE (${CMAKE_SOURCE_DIR}/VERSION.cmake)
SET (VERSION "${LIBREPO_MAJOR}.${LIBREPO_MINOR}.${LIBREPO_PATCH}")
Expand Down Expand Up @@ -37,6 +38,9 @@ FIND_PACKAGE(CURL 7.52.0 REQUIRED)

IF (USE_GPGME)
FIND_PACKAGE(Gpgme REQUIRED)
IF (ENABLE_SELINUX)
PKG_CHECK_MODULES(SELINUX REQUIRED libselinux)
ENDIF(ENABLE_SELINUX)
ELSE (USE_GPGME)
PKG_CHECK_MODULES(RPM REQUIRED rpm>=4.18.0)

Expand Down Expand Up @@ -93,6 +97,10 @@ ENDIF (NOT CURL_FOUND)
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
#INCLUDE_DIRECTORIES(${CHECK_INCLUDE_DIR})
IF (USE_GPGME AND ENABLE_SELINUX)
INCLUDE_DIRECTORIES(${SELINUX_INCLUDE_DIRS})
ADD_DEFINITIONS(-DENABLE_SELINUX=1)
ENDIF (USE_GPGME AND ENABLE_SELINUX)

include (GNUInstallDirs)
# Python stuff
Expand Down
14 changes: 13 additions & 1 deletion librepo.spec
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@

%if 0%{?fedora} >= 39
%bcond_with use_gpgme
%bcond_with use_selinux
%else
%bcond_without use_gpgme
%bcond_without use_selinux
%endif

# Needs to match how gnupg2 is compiled
%bcond_with run_gnupg_user_socket

%if %{with use_gpgme} && %{with use_selinux}
%global need_selinux 1
%else
%global need_selinux 0
%endif

%global dnf_conflict 2.8.8

Name: librepo
Expand All @@ -42,6 +50,9 @@ BuildRequires: libattr-devel
BuildRequires: libcurl-devel >= %{libcurl_version}
BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(libcrypto)
%if %{need_selinux}
BuildRequires: pkgconfig(libselinux)
%endif
BuildRequires: pkgconfig(openssl)
%if %{with zchunk}
BuildRequires: pkgconfig(zck) >= 0.9.11
Expand Down Expand Up @@ -82,7 +93,8 @@ Python 3 bindings for the librepo library.
%cmake \
-DWITH_ZCHUNK=%{?with_zchunk:ON}%{!?with_zchunk:OFF} \
-DUSE_GPGME=%{?with_use_gpgme:ON}%{!?with_use_gpgme:OFF} \
-DUSE_RUN_GNUPG_USER_SOCKET=%{?with_run_gnupg_user_socket:ON}%{!?with_run_gnupg_user_socket:OFF}
-DUSE_RUN_GNUPG_USER_SOCKET=%{?with_run_gnupg_user_socket:ON}%{!?with_run_gnupg_user_socket:OFF} \
-DENABLE_SELINUX=%{?need_selinux:ON}%{!?need_selinux:OFF}
%cmake_build

%check
Expand Down
3 changes: 3 additions & 0 deletions librepo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ TARGET_LINK_LIBRARIES(librepo
)
IF (USE_GPGME)
TARGET_LINK_LIBRARIES(librepo ${GPGME_VANILLA_LIBRARIES})
IF (ENABLE_SELINUX)
TARGET_LINK_LIBRARIES(librepo ${SELINUX_LIBRARIES})
ENDIF(ENABLE_SELINUX)
ELSE(USE_GPGME)
TARGET_LINK_LIBRARIES(librepo ${RPM_LIBRARIES})
ENDIF (USE_GPGME)
Expand Down
71 changes: 65 additions & 6 deletions librepo/gpg_gpgme.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#include <stdint.h>
#include <unistd.h>

#if ENABLE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#endif

#include "gpg.h"
#include "gpg_internal.h"
#include "rcodes.h"
Expand All @@ -45,10 +50,14 @@
* Previous solution was to send the agent a "KILLAGENT" message, but that
* would cause a race condition with calling gpgme_release(), see [2], [3].
*
* Another previous solution used /run/user/$UID which showed problematic when
* this library was used out of an systemd-logind session. Then /run/user/$UID,
* normally maintained by systemd, was assigned a SELinux label unexpected by
* systemd causing errors on a user logout [4].
* Current solution with precreating /run/user/$UID showed problematic when
* this library was used out of an systemd-logind session. Then
* /run/user/$UID, normally maintained by systemd, was assigned a SELinux
* label unexpected by systemd causing errors on a user logout [4].
*
* We remedy it by choosing the label according to a default file context
* policy (ENABLE_SELINUX macro) or by using a different path supported by
* some GnuPG configurations (DUSE_RUN_GNUPG_USER_SOCKET macro).
*
* Since the agent doesn't clean up its sockets properly, by creating this
* directory we make sure they are in a place that is not causing trouble with
Expand All @@ -72,19 +81,69 @@ lr_gpg_ensure_socket_dir_exists()
const uid_t uid = getuid();
char dirname[32];
int res;
#if ENABLE_SELINUX
char *old_default_context = NULL;
int old_default_context_was_retrieved = 0;
struct selabel_handle *labeling_handle = NULL;

/* A purpose of this piece of code is to deal with applications whose
* security policy overrides a file context for temporary files but don't
* know that librepo executes GnuPG which expects a default file context. */
if (0 == getfscreatecon(&old_default_context)) {
old_default_context_was_retrieved = 1;
} else {
g_debug("Failed to retrieve a default SELinux context");
}
labeling_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (labeling_handle == NULL) {
g_debug("Failed to open a SELinux labeling handle: %s", strerror(errno));
}
#endif

for (int i = 0; templates[i] != NULL; i++) {
res = snprintf(dirname, sizeof(dirname), templates[i], (uintmax_t)uid);
if (res >= sizeof(dirname)) {
g_debug("Failed to format a GnuPG agent socket path because of a small buffer");
return;
goto exit;
}

#if ENABLE_SELINUX
if (labeling_handle != NULL) {
char *new_default_context = NULL;
if (selabel_lookup(labeling_handle, &new_default_context, dirname, modes[i])) {
/* Here we could hard-code "system_u:object_r:user_tmp_t:s0", but
* that value should be really defined in default file context
* SELinux policy. Only log that the policy is incomplete. */
g_debug("Failed to look up a default SELinux label for \"%s\"", dirname);
} else {
if (setfscreatecon(new_default_context)) {
g_debug("Failed to set default SELinux context to \"%s\"",
new_default_context);
}
freecon(new_default_context);
}
}
#endif

res = mkdir(dirname, modes[i]);
if (res != 0 && errno != EEXIST) {
g_debug("Failed to create \"%s\": %d - %s\n", dirname, errno, strerror(errno));
return;
goto exit;
}
}

exit:
#if ENABLE_SELINUX
if (labeling_handle != NULL) {
selabel_close(labeling_handle);
}
if (old_default_context_was_retrieved) {
if (setfscreatecon(old_default_context)) {
g_debug("Failed to restore a default SELinux context");
}
}
freecon(old_default_context);
#endif
}

static gpgme_ctx_t
Expand Down

0 comments on commit 81602bb

Please sign in to comment.