import libdnf-0.69.0-8.el9_4.1

i9c changed/i9c/libdnf-0.69.0-8.el9_4.1
MSVSphere Packaging Team 4 months ago
parent f15eb58137
commit a5a0b4ba0d

@ -0,0 +1,37 @@
From ccd66a3cb4ddb7a0f0d914ee06eed58121dbe7ce Mon Sep 17 00:00:00 2001
From: Aleš Matěj <amatej@redhat.com>
Date: Tue, 27 Jun 2023 07:24:28 +0200
Subject: [PATCH] filterAdvisory: match installed_solvables sort with lower_bound (RhBug:2212838)
`std::lower_bound` expects that the range it operates on is sorted by
the provided comparator.
`lower_bound()` is used on `installed_solvables` twice, first with
comparator `NameSolvableComparator` and later with
`SolvableCompareAdvisoryPkgNameArch` to cover both we need to sort
`installed_solvables` by name and arch.
Otherwise this can lead to problems if multiple architectures of a pkg
are installed.
For: https://bugzilla.redhat.com/show_bug.cgi?id=2212838
---
libdnf/sack/query.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index b7b1560..7937770 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -1903,7 +1903,7 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
while ((installed_id = installed.pImpl->result->next(installed_id)) != -1) {
installed_solvables.push_back(pool_id2solvable(pool, installed_id));
}
- std::sort(installed_solvables.begin(), installed_solvables.end(), NameSolvableComparator);
+ std::sort(installed_solvables.begin(), installed_solvables.end(), NameArchSolvableComparator);
Query obsoletes(sack, ExcludeFlags::IGNORE_EXCLUDES);
obsoletes.addFilter(HY_PKG, HY_EQ, resultPset);
--
libgit2 1.6.4

@ -0,0 +1,84 @@
From dadfe65ce753ba8a8bdb5e38d7929135526edbd5 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Thu, 31 Aug 2023 13:18:03 +0200
Subject: [PATCH] hawkey.subject: get_best_selectors only obsoleters of latest
In situation where a package exists in multiple versions and some older
version is being obsoleted, any of obsoleters was considered a valid
solution.
The result could be really misleading. For example let's have this package set:
systemd-udev-1.0
systemd-udev-2.0
Obsoletes: systemd-udev < 2
systemd-boot-unsigned-2.0
Obsoletes: systemd-udev < 2
In this case `dnf install systemd-udev` may lead to installation of
systemd-boot-unsigned which is probably not what the user expected. The
reason is the split in the upgrade-path created by obsolete and both
branches - systemd-udev-2.0 and systemd-boot-unsigned-2.0 are considered
valid.
With this patch install command takes into account only obsoleters of
the best version of the package so the `dnf install systemd-udev`
results in correct installation of systemd-udev-2.0 package.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2183279
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2176263
---
python/hawkey/__init__.py | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/python/hawkey/__init__.py b/python/hawkey/__init__.py
index 45bdc3a..1ec1ef4 100644
--- a/python/hawkey/__init__.py
+++ b/python/hawkey/__init__.py
@@ -291,13 +291,13 @@ class Subject(_hawkey.Subject):
# after movement of base.install() or base.distro_sync()
return []
+ installed_query = q.installed()
if not self._filename_pattern and is_glob_pattern(self.pattern) \
or solution['nevra'] and solution['nevra'].name is None:
with_obsoletes = False
if obsoletes and solution['nevra'] and solution['nevra'].has_just_name():
with_obsoletes = True
- installed_query = q.installed()
if reponame:
q = q.filter(reponame=reponame)
available_query = q.available()
@@ -309,13 +309,24 @@ class Subject(_hawkey.Subject):
sltrs = []
for name, pkgs_list in q._name_dict().items():
if with_obsoletes:
+ # If there is no installed package in the pkgs_list, add only
+ # obsoleters of the latest versions. Otherwise behave consistently
+ # with upgrade and add all obsoleters.
+ # See https://bugzilla.redhat.com/show_bug.cgi?id=2176263
+ # for details of the problem.
+ obsoletes_query = base.sack.query().filterm(pkg=pkgs_list)
+ if not obsoletes_query.installed():
+ obsoletes_query.filterm(latest_per_arch_by_priority=True)
pkgs_list = pkgs_list + base.sack.query().filter(
- obsoletes=pkgs_list).run()
+ obsoletes=obsoletes_query).run()
sltrs.append(self._list_or_query_to_selector(base.sack, pkgs_list))
return sltrs
else:
if obsoletes and solution['nevra'] and solution['nevra'].has_just_name():
- q = q.union(base.sack.query().filter(obsoletes=q))
+ if installed_query:
+ q = q.union(base.sack.query().filter(obsoletes=q))
+ else:
+ q = q.union(base.sack.query().filter(obsoletes=q.filter(latest_per_arch_by_priority=True)))
installed_query = q.installed()
if reports:
--
libgit2 1.6.4

@ -0,0 +1,99 @@
From 2ffe58595baa2a51700a1210b1d3a2124f805756 Mon Sep 17 00:00:00 2001
From: Aleš Matěj <amatej@redhat.com>
Date: Mon, 25 Sep 2023 08:24:40 +0200
Subject: [PATCH] Avoid reinstalling installonly packages marked for ERASE
Without this patch reinstalling installonly pkg marked for ERASE might
be a valid smallest solution to our job.
For example when user wants to install through a provide we select all
packages that provide it and put them inside a `job install oneof ...`
if one of the providers is also marked for ERASE due to installonly
limit libsolv might decide to reinstall it.
To make sure it doesn't happen mark the available package also as ERASE.
https://github.com/openSUSE/libsolv/issues/540
https://issues.redhat.com/browse/RHEL-1253
(https://bugzilla.redhat.com/show_bug.cgi?id=2163474)
---
libdnf/goal/Goal.cpp | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index 7def837..ba938e1 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -643,6 +643,12 @@ erase_flags2libsolv(int flags)
return ret;
}
+static bool
+NameSolvableComparator(const Solvable * first, const Solvable * second)
+{
+ return first->name < second->name;
+}
+
Goal::Goal(const Goal & goal_src) : pImpl(new Impl(*goal_src.pImpl)) {}
Goal::Impl::Impl(const Goal::Impl & goal_src)
@@ -1436,10 +1442,24 @@ Goal::Impl::limitInstallonlyPackages(Solver *solv, Queue *job)
for (int i = 0; i < onlies->count; ++i) {
Id p, pp;
IdQueue q, installing;
+ std::vector<Solvable *> available_unused_providers;
+ // Add all providers of installonly provides that are marked for install
+ // to `q` IdQueue those that are not marked for install and are not already
+ // installed are added to available_unused_providers.
FOR_PKG_PROVIDES(p, pp, onlies->elements[i])
- if (solver_get_decisionlevel(solv, p) > 0)
+ // According to libsolv-bindings the decision level is positive for installs
+ // and negative for conflicts (conflicts with another package or dependency
+ // conflicts = dependencies cannot be met).
+ if (solver_get_decisionlevel(solv, p) > 0) {
q.pushBack(p);
+ } else {
+ Solvable *s = pool_id2solvable(pool, p);
+ if (s->repo != pool->installed) {
+ available_unused_providers.push_back(s);
+ }
+ }
+
if (q.size() <= (int) dnf_sack_get_installonly_limit(sack)) {
continue;
}
@@ -1457,17 +1477,28 @@ Goal::Impl::limitInstallonlyPackages(Solver *solv, Queue *job)
struct InstallonliesSortCallback s_cb = {pool, dnf_sack_running_kernel(sack)};
solv_sort(q.data(), q.size(), sizeof(q[0]), sort_packages, &s_cb);
+ std::sort(available_unused_providers.begin(), available_unused_providers.end(), NameSolvableComparator);
IdQueue same_names;
while (q.size() > 0) {
same_name_subqueue(pool, q.getQueue(), same_names.getQueue());
if (same_names.size() <= (int) dnf_sack_get_installonly_limit(sack))
continue;
reresolve = 1;
for (int j = 0; j < same_names.size(); ++j) {
Id id = same_names[j];
Id action = SOLVER_ERASE;
- if (j < (int) dnf_sack_get_installonly_limit(sack))
+ if (j < (int) dnf_sack_get_installonly_limit(sack)) {
action = SOLVER_INSTALL;
+ } else {
+ // We want to avoid reinstalling packages marked for ERASE, therefore
+ // if some unused provider is also available we need to mark it ERASE as well.
+ Solvable *s = pool_id2solvable(pool, id);
+ auto low = std::lower_bound(available_unused_providers.begin(), available_unused_providers.end(), s, NameSolvableComparator);
+ while (low != available_unused_providers.end() && (*low)->name == s->name) {
+ queue_push2(job, SOLVER_ERASE | SOLVER_SOLVABLE, pool_solvable2id(pool, *low));
+ ++low;
+ }
+ }
queue_push2(job, action | SOLVER_SOLVABLE, id);
}
}
--
libgit2 1.6.4

@ -0,0 +1,338 @@
From 7529d06dbe7ac4c1cb41a4fb8e32e3b96be72075 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Wed, 4 Oct 2023 16:38:12 +0200
Subject: [PATCH] PGP: Set a default creation SELinux labels on GnuPG
directories
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
libdnf 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). libdnf 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.
The same issue was with temporary GnuPG home directories created by
libdnf under /tmp.
This patch fixes both the isseus by restoring a SELinux label of those
directories to the label defined in a default SELinux file context
database.
Obviously the database cannot have a record for a nonspecific
/tmp/tmpdir.XXXXXX (a mkdtemp() template) directory names. Therefore
I changed their names to more specific /tmp/libdnf.XXXXXX. Once
a SELinux policy updates the database, directories under /tmp will get
a correct label.
There is yet another problem with accessing /var/cache/dnf/*/pubring,
but that seems to be pure SELinux policy problem.
This patch adds a new -DENABLE_SELINUX=OFF CMake option to disable the
new dependency on libselinux. A default behavior is to support SELinux.
Implementation details:
I used selabel_lookup() + setfscreatecon() + mkdtemp()
+ setfscreatecon() sequence instead of mkdtemp()
+ selinux_restorecon() sequence because the later polutes stderr if
a SELinux policy does not define the default context. One could
supress stderr messages with selinux_set_callback(), but its effect
cannot be restored.
I also kept the sequence in one function and reused it for creating
/run/user/$PID directories because the code is simpler than spliting
the function into three parts.
https://issues.redhat.com/browse/RHEL-6421
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
CMakeLists.txt | 7 +++
libdnf.spec | 11 +++-
libdnf/CMakeLists.txt | 4 ++
libdnf/repo/Repo.cpp | 124 ++++++++++++++++++++++++++++++++++++++----
4 files changed, 132 insertions(+), 14 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 405dc4e8..cc550ddb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,7 @@ option(WITH_ZCHUNK "Build with zchunk support" ON)
option(ENABLE_RHSM_SUPPORT "Build with Red Hat Subscription Manager support?" OFF)
option(ENABLE_SOLV_URPMREORDER "Build with support for URPM-like solution reordering?" OFF)
option(WITH_TESTS "Enables unit tests" ON)
+option(ENABLE_SELINUX "Restore SELinux labels on GnuPG directories" ON)
# build options - debugging
@@ -83,6 +84,12 @@ if(ENABLE_RHSM_SUPPORT)
include_directories(${RHSM_INCLUDE_DIRS})
endif()
+if(ENABLE_SELINUX)
+ pkg_check_modules(SELINUX REQUIRED libselinux)
+ include_directories(${SELINUX_INCLUDE_DIRS})
+ add_definitions(-DENABLE_SELINUX=1)
+endif()
+
# glibc: check if fnmatch.h has FNM_CASEFOLD symbol
include(CheckSymbolExists)
diff --git a/libdnf.spec b/libdnf.spec
index 41df982c..09b5a89d 100644
--- a/libdnf.spec
+++ b/libdnf.spec
@@ -42,6 +42,8 @@
%bcond_with rhsm
%endif
+%bcond_without selinux
+
%if 0%{?rhel}
%bcond_with zchunk
%else
@@ -83,6 +85,9 @@ BuildRequires: pkgconfig(zck) >= 0.9.11
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
+%if %{with selinux}
+BuildRequires: pkgconfig(libselinux)
+%endif
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
@@ -204,7 +209,8 @@ pushd build-py2
%define __builddir build-py2
%endif
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python2} -DWITH_MAN=OFF ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts} -DLIBDNF_MAJOR_VERSION=%{libdnf_major_version} -DLIBDNF_MINOR_VERSION=%{libdnf_minor_version} -DLIBDNF_MICRO_VERSION=%{libdnf_micro_version} \
- -DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
+ -DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF} \
+ -DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
%make_build
popd
%endif
@@ -218,7 +224,8 @@ pushd build-py3
%define __builddir build-py3
%endif
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python3} -DWITH_GIR=0 -DWITH_MAN=0 -Dgtkdoc=0 ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts} -DLIBDNF_MAJOR_VERSION=%{libdnf_major_version} -DLIBDNF_MINOR_VERSION=%{libdnf_minor_version} -DLIBDNF_MICRO_VERSION=%{libdnf_micro_version} \
- -DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
+ -DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF} \
+ -DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
%make_build
popd
%endif
diff --git a/libdnf/CMakeLists.txt b/libdnf/CMakeLists.txt
index 9e71d139..3c82ec3a 100644
--- a/libdnf/CMakeLists.txt
+++ b/libdnf/CMakeLists.txt
@@ -88,6 +88,10 @@ if(ENABLE_RHSM_SUPPORT)
target_link_libraries(libdnf ${RHSM_LIBRARIES})
endif()
+if(ENABLE_SELINUX)
+ target_link_libraries(libdnf ${SELINUX_LIBRARIES})
+endif()
+
set(DNF_SO_VERSION 2)
set_target_properties(libdnf PROPERTIES OUTPUT_NAME "dnf")
set_target_properties(libdnf PROPERTIES SOVERSION ${DNF_SO_VERSION})
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 9959a73a..16f15195 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -51,6 +51,11 @@
#include <gpgme.h>
+#if ENABLE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#endif
+
#include <solv/chksum.h>
#include <solv/repo.h>
#include <solv/util.h>
@@ -651,6 +656,81 @@ std::unique_ptr<LrHandle> Repo::Impl::lrHandleInitRemote(const char *destdir)
return h;
}
+/*
+ * @brief Create a temporary directory.
+ *
+ * Creates a temporary directory with 0700 mode attempting to set a proper
+ * SELinux file context. Encountered errors are logged at debug level to
+ * a global logger.
+ *
+ * @param name_template As an input value it is a template according to
+ * mkdtemp(3). As an output value it will contain the created directory name.
+ *
+ * @return 0 if the directory was created, -1 if it wasn't. SELinux failures
+ * are not considered an error.
+ */
+static int create_temporary_directory(char *name_template) {
+ auto logger(Log::getLogger());
+ int saved_errno = errno;
+ int retval = 0;
+#if ENABLE_SELINUX
+ char *old_default_context = NULL;
+ char *new_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 libdnf executes GnuPG which expects a default file context. */
+ if (0 == getfscreatecon(&old_default_context)) {
+ old_default_context_was_retrieved = 1;
+ } else {
+ logger->debug(tfm::format("Failed to retrieve a default SELinux context"));
+ }
+
+ labeling_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+ if (NULL == labeling_handle) {
+ logger->debug(tfm::format("Failed to open a SELinux labeling handle: %s",
+ strerror(errno)));
+ } else {
+ if (selabel_lookup(labeling_handle, &new_default_context, name_template, 0700)) {
+ /* 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 incpomplete. */
+ logger->debug(tfm::format("Failed to look up a default SELinux label for \"%s\"",
+ name_template));
+ } else {
+ if (setfscreatecon(new_default_context)) {
+ logger->debug(tfm::format("Failed to set default SELinux context to \"%s\"",
+ new_default_context));
+ }
+ freecon(new_default_context);
+ }
+ selabel_close(labeling_handle);
+ }
+#endif
+
+ /* mkdtemp() assures 0700 mode. */
+ if (NULL == mkdtemp(name_template)) {
+ saved_errno = errno;
+ logger->debug(tfm::format("Failed to create a directory \"%s\": %s",
+ name_template, strerror(errno)));
+ retval = -1;
+ }
+
+#if ENABLE_SELINUX
+ if (old_default_context_was_retrieved) {
+ if (setfscreatecon(old_default_context)) {
+ logger->debug(tfm::format("Failed to restore a default SELinux context"));
+ }
+ }
+ freecon(old_default_context);
+#endif
+
+ errno = saved_errno;
+ return retval;
+}
+
static void gpgImportKey(gpgme_ctx_t context, int keyFd)
{
auto logger(Log::getLogger());
@@ -705,8 +785,8 @@ static std::vector<Key> rawkey2infos(int fd) {
std::unique_ptr<std::remove_pointer<gpgme_ctx_t>::type> context(ctx);
// set GPG home dir
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- if (!mkdtemp(tmpdir)) {
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ if (create_temporary_directory(tmpdir)) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir, errTxt));
@@ -859,6 +939,13 @@ std::vector<Key> Repo::Impl::retrieve(const std::string & url)
* would cause a race condition with calling gpgme_release(), see [2], [3],
* [4].
*
+ * Current solution precreating /run/user/$UID showed problematic when this
+ * library was used out of a systemd-logind session from a programm with an
+ * unexpected SELinux context. Then /run/user/$UID, normally maintained by
+ * systemd, was assigned a SELinux label unexpected by systemd causing errors
+ * on a user logout [5]. We remedy it by restoring the label according to
+ * a file context policy.
+ *
* 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
* container images.
@@ -867,14 +954,27 @@ std::vector<Key> Repo::Impl::retrieve(const std::string & url)
* [2] https://bugzilla.redhat.com/show_bug.cgi?id=1769831
* [3] https://github.com/rpm-software-management/microdnf/issues/50
* [4] https://bugzilla.redhat.com/show_bug.cgi?id=1781601
+ * [5] https://issues.redhat.com/browse/RHEL-6421
*/
static void ensure_socket_dir_exists() {
auto logger(Log::getLogger());
+ char tmpdir[] = "/run/user/libdnf.XXXXXX";
std::string dirname = "/run/user/" + std::to_string(getuid());
- int res = mkdir(dirname.c_str(), 0700);
- if (res != 0 && errno != EEXIST) {
- logger->debug(tfm::format("Failed to create directory \"%s\": %d - %s",
- dirname, errno, strerror(errno)));
+
+ /* create_temporary_directory() assures 0700 mode and tries its best to
+ * correct a SELinux label. */
+ if (create_temporary_directory(tmpdir)) {
+ return;
+ }
+
+ /* Set the desired name. */
+ if (rename(tmpdir, dirname.c_str())) {
+ if (errno != EEXIST && errno != ENOTEMPTY && errno != EBUSY) {
+ logger->debug(tfm::format("Failed to rename \"%s\" directory to \"%s\": %s",
+ tmpdir, dirname, strerror(errno)));
+ }
+ rmdir(tmpdir);
+ return;
}
}
@@ -1163,8 +1263,8 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
bool Repo::Impl::isMetalinkInSync()
{
auto logger(Log::getLogger());
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- if (!mkdtemp(tmpdir)) {
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ if (create_temporary_directory(tmpdir)) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir, errTxt));
@@ -1237,8 +1337,8 @@ bool Repo::Impl::isRepomdInSync()
{
auto logger(Log::getLogger());
LrYumRepo *yum_repo;
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- if (!mkdtemp(tmpdir)) {
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ if (create_temporary_directory(tmpdir)) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir, errTxt));
@@ -1280,8 +1380,8 @@ void Repo::Impl::fetch(const std::string & destdir, std::unique_ptr<LrHandle> &&
throw RepoError(tfm::format(_("Cannot create repo destination directory \"%s\": %s"),
destdir, errTxt));
}
- auto tmpdir = destdir + "/tmpdir.XXXXXX";
- if (!mkdtemp(&tmpdir.front())) {
+ auto tmpdir = destdir + "/libdnf.XXXXXX";
+ if (create_temporary_directory(&tmpdir.front())) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir.c_str(), errTxt));
--
2.41.0

@ -0,0 +1,93 @@
From a0a32b4c2e2a03ff6ffcb6b7285905ec50892798 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Tue, 4 Jun 2024 06:57:19 -0400
Subject: [PATCH] repo: Don't try to perform labeling if SELinux is disabled
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The default for container execution is that `/sys/fs/selinux`
is not mounted, and the libselinux library function `is_selinux_enabled`
should be used to dynamically check if the system should attempt to perform SELinux labeling.
This is how it's done by rpm, ostree, and systemd for example.
But this code unconditionally tries to label if it finds a policy,
which breaks in an obscure corner case
when executed inside a container that includes policy files (e.g.
fedora/rhel-bootc) but when we're not using overlayfs for the backend
(with BUILDAH_BACKEND=vfs).
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libdnf/repo/Repo.cpp | 50 +++++++++++++++++++++++---------------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 16f15195..10b88813 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -679,34 +679,36 @@ static int create_temporary_directory(char *name_template) {
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 libdnf executes GnuPG which expects a default file context. */
- if (0 == getfscreatecon(&old_default_context)) {
- old_default_context_was_retrieved = 1;
- } else {
- logger->debug(tfm::format("Failed to retrieve a default SELinux context"));
- }
+ if (is_selinux_enabled()) {
+ /* 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 libdnf executes GnuPG which expects a default file context. */
+ if (0 == getfscreatecon(&old_default_context)) {
+ old_default_context_was_retrieved = 1;
+ } else {
+ logger->debug(tfm::format("Failed to retrieve a default SELinux context"));
+ }
- labeling_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
- if (NULL == labeling_handle) {
- logger->debug(tfm::format("Failed to open a SELinux labeling handle: %s",
- strerror(errno)));
- } else {
- if (selabel_lookup(labeling_handle, &new_default_context, name_template, 0700)) {
- /* 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 incpomplete. */
- logger->debug(tfm::format("Failed to look up a default SELinux label for \"%s\"",
- name_template));
+ labeling_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+ if (NULL == labeling_handle) {
+ logger->debug(tfm::format("Failed to open a SELinux labeling handle: %s",
+ strerror(errno)));
} else {
- if (setfscreatecon(new_default_context)) {
- logger->debug(tfm::format("Failed to set default SELinux context to \"%s\"",
- new_default_context));
+ if (selabel_lookup(labeling_handle, &new_default_context, name_template, 0700)) {
+ /* 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 incpomplete. */
+ logger->debug(tfm::format("Failed to look up a default SELinux label for \"%s\"",
+ name_template));
+ } else {
+ if (setfscreatecon(new_default_context)) {
+ logger->debug(tfm::format("Failed to set default SELinux context to \"%s\"",
+ new_default_context));
+ }
+ freecon(new_default_context);
}
- freecon(new_default_context);
+ selabel_close(labeling_handle);
}
- selabel_close(labeling_handle);
}
#endif
--
2.45.2

@ -42,6 +42,8 @@
%bcond_with rhsm
%endif
%bcond_without selinux
%if 0%{?rhel}
%bcond_with zchunk
%else
@ -56,7 +58,7 @@
Name: libdnf
Version: %{libdnf_major_version}.%{libdnf_minor_version}.%{libdnf_micro_version}
Release: 6%{?dist}
Release: 8%{?dist}.1
Summary: Library providing simplified C and Python API to libsolv
License: LGPLv2+
URL: https://github.com/rpm-software-management/libdnf
@ -65,6 +67,11 @@ Patch1: 0001-Allow-change-of-arch-during-security-updates-with-no.patch
Patch2: 0002-Add-repoid-to-solver-error-messages.patch
Patch3: 0003-Update-translations-RHEL-9-2.patch
Patch4: 0004-Update-translations-RHEL-9.3.patch
Patch5: 0005-filterAdvisory-installed_solvables-sort-RhBug2212838.patch
Patch6: 0006-hawkeysubject-get_best_selectors-only-obsol-oflatest.patch
Patch7: 0007-Avoid-reinstal-installonly-packages-marked-for-ERASE.patch
Patch8: 0008-PGP-Set-a-default-creation-SELinux-labels-on-GnuPG-d.patch
Patch9: 0009-repo-Don-t-try-to-perform-labeling-if-SELinux-is-dis.patch
BuildRequires: cmake
@ -88,6 +95,9 @@ BuildRequires: pkgconfig(zck) >= 0.9.11
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
%if %{with selinux}
BuildRequires: pkgconfig(libselinux)
%endif
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
@ -209,7 +219,8 @@ pushd build-py2
%define __builddir build-py2
%endif
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python2} -DWITH_MAN=OFF ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts} -DLIBDNF_MAJOR_VERSION=%{libdnf_major_version} -DLIBDNF_MINOR_VERSION=%{libdnf_minor_version} -DLIBDNF_MICRO_VERSION=%{libdnf_micro_version} \
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF} \
-DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
%make_build
popd
%endif
@ -223,7 +234,8 @@ pushd build-py3
%define __builddir build-py3
%endif
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python3} -DWITH_GIR=0 -DWITH_MAN=0 -Dgtkdoc=0 ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts} -DLIBDNF_MAJOR_VERSION=%{libdnf_major_version} -DLIBDNF_MINOR_VERSION=%{libdnf_minor_version} -DLIBDNF_MICRO_VERSION=%{libdnf_micro_version} \
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF} \
-DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
%make_build
popd
%endif
@ -309,6 +321,18 @@ popd
%endif
%changelog
* Fri Jun 21 2024 Petr Pisar <ppisar@redhat.com> - 0.69.0-8.1
- Do not set a default SELinux creation context if SELinux appears to be
disabled (RHEL-39796)
* Wed Oct 25 2023 Petr Pisar <ppisar@redhat.com> - 0.69.0-8
- Set default SELinux labels on GnuPG directories (RHEL-11238)
* Wed Oct 25 2023 Jaroslav Rohel <jrohel@redhat.com> - 0.69.0-7
- filterAdvisory: match installed_solvables sort with lower_bound (RhBug:2212838, RHEL-12123)
- hawkey.subject: get_best_selectors only obsoleters of latest (RhBug:2183279, RHEL-6304)
- Avoid reinstalling installonly packages marked for ERASE (RhBug:2163474, RHEL-12124)
* Fri Sep 08 2023 Marek Blaha <mblaha@redhat.com> - 0.69.0-6
- Update translations

Loading…
Cancel
Save