Merge branch 'c8' into a8

This commit is contained in:
eabdullin 2024-05-24 08:37:46 +03:00
commit f400739692
8 changed files with 3716 additions and 4 deletions

View File

@ -0,0 +1,317 @@
From 0e13ac4820e72682b427cfe3cabcfa32561cf631 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Fri, 24 Mar 2023 13:22:41 +0100
Subject: [PATCH] Backport: Split modular packages to to repositories according
their origin
It will help to provide information about repository origin to libsolv
modular error messages.
---
libdnf/module/ModulePackageContainer.cpp | 42 ++++++++++++++----------
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index f9f861c1..546d5837 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -235,13 +235,6 @@ ModulePackageContainer::ModulePackageContainer(bool allArch, std::string install
pImpl->persistDir = dir;
}
- Pool * pool = dnf_sack_get_pool(pImpl->moduleSack);
- HyRepo hrepo = hy_repo_create("available");
- auto repoImpl = libdnf::repoGetImpl(hrepo);
- LibsolvRepo *repo = repo_create(pool, "available");
- repo->appdata = hrepo;
- repoImpl->libsolvRepo = repo;
- repoImpl->needs_internalizing = 1;
pImpl->installRoot = installRoot;
g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(),
"/etc/dnf/modules.d", NULL);
@@ -324,23 +317,36 @@ ModulePackageContainer::add(const std::string &fileContent, const std::string &
md.addMetadataFromString(fileContent, 0);
md.resolveAddedMetadata();
+ LibsolvRepo * repo = nullptr;
LibsolvRepo * r;
Id id;
+ // Search whether available repo was already created
FOR_REPOS(id, r) {
- if (strcmp(r->name, "available") == 0) {
- g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(),
- "/etc/dnf/modules.d", NULL);
- std::vector<ModulePackage *> packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID);
- for(auto const& modulePackagePtr: packages) {
- std::unique_ptr<ModulePackage> modulePackage(modulePackagePtr);
- pImpl->modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
- pImpl->persistor->insert(modulePackagePtr->getName(), path);
- }
-
- return;
+ if (strcmp(r->name, repoID.c_str()) == 0) {
+ repo = r;
}
}
+
+ // If not created yet, create it
+ if (!repo) {
+ Pool * pool = dnf_sack_get_pool(pImpl->moduleSack);
+ HyRepo hrepo = hy_repo_create(repoID.c_str());
+ auto repoImpl = libdnf::repoGetImpl(hrepo);
+ repo = repo_create(pool, repoID.c_str());
+ repo->appdata = hrepo;
+ repoImpl->libsolvRepo = repo;
+ repoImpl->needs_internalizing = 1;
+ }
+
+ // add all modules to repository and pass ownership to module container
+ g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(), "/etc/dnf/modules.d", NULL);
+ auto packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID);
+ for(auto const& modulePackagePtr: packages) {
+ std::unique_ptr<ModulePackage> modulePackage(modulePackagePtr);
+ pImpl->modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
+ pImpl->persistor->insert(modulePackagePtr->getName(), path);
+ }
}
Id
--
2.40.1
From dc8a7262f4955160172a32e54eb1db4a644471fa Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 21 Mar 2023 11:28:43 +0100
Subject: [PATCH] Backport: Add repoid to solver errors for RPMs
(RhBug:2179413)
Repoid is very useful to find a source of the issue. It tells which
repositories contains problematic packages.
https://bugzilla.redhat.com/show_bug.cgi?id=2179413
---
libdnf/goal/Goal.cpp | 101 +++++++++++++----------
libdnf/module/ModulePackageContainer.cpp | 2 +-
tests/hawkey/test_goal.cpp | 14 ++--
3 files changed, 64 insertions(+), 53 deletions(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index 6b2f91a2..b7710303 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -83,8 +83,8 @@ enum {RULE_DISTUPGRADE=1, RULE_INFARCH, RULE_UPDATE, RULE_JOB, RULE_JOB_UNSUPPOR
};
static const std::map<int, const char *> PKG_PROBLEMS_DICT = {
- {RULE_DISTUPGRADE, M_(" does not belong to a distupgrade repository")},
- {RULE_INFARCH, M_(" has inferior architecture")},
+ {RULE_DISTUPGRADE, M_("%s from %s does not belong to a distupgrade repository")},
+ {RULE_INFARCH, M_("%s from %s has inferior architecture")},
{RULE_UPDATE, M_("problem with installed package ")},
{RULE_JOB, M_("conflicting requests")},
{RULE_JOB_UNSUPPORTED, M_("unsupported request")},
@@ -94,24 +94,24 @@ static const std::map<int, const char *> PKG_PROBLEMS_DICT = {
{RULE_PKG, M_("some dependency problem")},
{RULE_BEST_1, M_("cannot install the best update candidate for package ")},
{RULE_BEST_2, M_("cannot install the best candidate for the job")},
- {RULE_PKG_NOT_INSTALLABLE_1, M_("package %s is filtered out by modular filtering")},
- {RULE_PKG_NOT_INSTALLABLE_2, M_("package %s does not have a compatible architecture")},
- {RULE_PKG_NOT_INSTALLABLE_3, M_("package %s is not installable")},
- {RULE_PKG_NOT_INSTALLABLE_4, M_("package %s is filtered out by exclude filtering")},
- {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by %s")},
- {RULE_PKG_SAME_NAME, M_("cannot install both %s and %s")},
- {RULE_PKG_CONFLICTS, M_("package %s conflicts with %s provided by %s")},
- {RULE_PKG_OBSOLETES, M_("package %s obsoletes %s provided by %s")},
- {RULE_PKG_INSTALLED_OBSOLETES, M_("installed package %s obsoletes %s provided by %s")},
- {RULE_PKG_IMPLICIT_OBSOLETES, M_("package %s implicitly obsoletes %s provided by %s")},
- {RULE_PKG_REQUIRES, M_("package %s requires %s, but none of the providers can be installed")},
- {RULE_PKG_SELF_CONFLICT, M_("package %s conflicts with %s provided by itself")},
- {RULE_YUMOBS, M_("both package %s and %s obsolete %s")}
+ {RULE_PKG_NOT_INSTALLABLE_1, M_("package %s from %s is filtered out by modular filtering")},
+ {RULE_PKG_NOT_INSTALLABLE_2, M_("package %s from %s does not have a compatible architecture")},
+ {RULE_PKG_NOT_INSTALLABLE_3, M_("package %s from %s is not installable")},
+ {RULE_PKG_NOT_INSTALLABLE_4, M_("package %s from %s is filtered out by exclude filtering")},
+ {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by %s from %s")},
+ {RULE_PKG_SAME_NAME, M_("cannot install both %s from %s and %s from %s")},
+ {RULE_PKG_CONFLICTS, M_("package %s from %s conflicts with %s provided by %s from %s")},
+ {RULE_PKG_OBSOLETES, M_("package %s from %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_INSTALLED_OBSOLETES, M_("installed package %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_IMPLICIT_OBSOLETES, M_("package %s from %s implicitly obsoletes %s provided by %s from %s")},
+ {RULE_PKG_REQUIRES, M_("package %s from %s requires %s, but none of the providers can be installed")},
+ {RULE_PKG_SELF_CONFLICT, M_("package %s from %s conflicts with %s provided by itself")},
+ {RULE_YUMOBS, M_("both package %s from %s and %s from %s obsolete %s")}
};
static const std::map<int, const char *> MODULE_PROBLEMS_DICT = {
- {RULE_DISTUPGRADE, M_(" does not belong to a distupgrade repository")},
- {RULE_INFARCH, M_(" has inferior architecture")},
+ {RULE_DISTUPGRADE, M_("%s from %s does not belong to a distupgrade repository")},
+ {RULE_INFARCH, M_("%s from %s has inferior architecture")},
{RULE_UPDATE, M_("problem with installed module ")},
{RULE_JOB, M_("conflicting requests")},
{RULE_JOB_UNSUPPORTED, M_("unsupported request")},
@@ -121,19 +121,19 @@ static const std::map<int, const char *> MODULE_PROBLEMS_DICT = {
{RULE_PKG, M_("some dependency problem")},
{RULE_BEST_1, M_("cannot install the best update candidate for module ")},
{RULE_BEST_2, M_("cannot install the best candidate for the job")},
- {RULE_PKG_NOT_INSTALLABLE_1, M_("module %s is disabled")},
- {RULE_PKG_NOT_INSTALLABLE_2, M_("module %s does not have a compatible architecture")},
- {RULE_PKG_NOT_INSTALLABLE_3, M_("module %s is not installable")},
- {RULE_PKG_NOT_INSTALLABLE_4, M_("module %s is disabled")},
- {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by module %s")},
- {RULE_PKG_SAME_NAME, M_("cannot install both modules %s and %s")},
- {RULE_PKG_CONFLICTS, M_("module %s conflicts with %s provided by %s")},
- {RULE_PKG_OBSOLETES, M_("module %s obsoletes %s provided by %s")},
- {RULE_PKG_INSTALLED_OBSOLETES, M_("installed module %s obsoletes %s provided by %s")},
- {RULE_PKG_IMPLICIT_OBSOLETES, M_("module %s implicitly obsoletes %s provided by %s")},
- {RULE_PKG_REQUIRES, M_("module %s requires %s, but none of the providers can be installed")},
- {RULE_PKG_SELF_CONFLICT, M_("module %s conflicts with %s provided by itself")},
- {RULE_YUMOBS, M_("both module %s and %s obsolete %s")}
+ {RULE_PKG_NOT_INSTALLABLE_1, M_("module %s from %s is disabled")},
+ {RULE_PKG_NOT_INSTALLABLE_2, M_("module %s from %s does not have a compatible architecture")},
+ {RULE_PKG_NOT_INSTALLABLE_3, M_("module %s from %s is not installable")},
+ {RULE_PKG_NOT_INSTALLABLE_4, M_("module %s from %s is disabled")},
+ {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by module %s from %s")},
+ {RULE_PKG_SAME_NAME, M_("cannot install both modules %s from %s and %s from %s")},
+ {RULE_PKG_CONFLICTS, M_("module %s from %s conflicts with %s provided by %s from %s")},
+ {RULE_PKG_OBSOLETES, M_("module %s from %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_INSTALLED_OBSOLETES, M_("installed module %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_IMPLICIT_OBSOLETES, M_("module %s from %s implicitly obsoletes %s provided by %s from %s")},
+ {RULE_PKG_REQUIRES, M_("module %s from %s requires %s, but none of the providers can be installed")},
+ {RULE_PKG_SELF_CONFLICT, M_("module %s from %s conflicts with %s provided by itself")},
+ {RULE_YUMOBS, M_("both module %s from %s and %s from %s obsolete %s")}
};
static std::string
@@ -147,9 +147,11 @@ libdnf_problemruleinfo2str(libdnf::PackageSet * modularExclude, Solver *solv, So
Solvable *ss;
switch (type) {
case SOLVER_RULE_DISTUPGRADE:
- return solvid2str(pool, source) + TM_(problemDict.at(RULE_DISTUPGRADE), 1);
+ return tfm::format(TM_(problemDict.at(RULE_DISTUPGRADE), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_INFARCH:
- return solvid2str(pool, source) + TM_(problemDict.at(RULE_INFARCH), 1);
+ return tfm::format(TM_(problemDict.at(RULE_DISTUPGRADE), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_UPDATE:
return std::string(TM_(problemDict.at(RULE_UPDATE), 1)) + solvid2str(pool, source);
case SOLVER_RULE_JOB:
@@ -172,44 +174,53 @@ libdnf_problemruleinfo2str(libdnf::PackageSet * modularExclude, Solver *solv, So
ss = pool->solvables + source;
if (pool_disabled_solvable(pool, ss)) {
if (modularExclude && modularExclude->has(source)) {
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_1), 1), solvid2str(pool, source).c_str());
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_1), 1),
+ solvid2str(pool, source).c_str(), pool_id2solvable(pool, source)->repo->name);
} else {
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_4), 1), solvid2str(pool, source).c_str());
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_4), 1),
+ solvid2str(pool, source).c_str(), pool_id2solvable(pool, source)->repo->name);
}
}
if (ss->arch && ss->arch != ARCH_SRC && ss->arch != ARCH_NOSRC &&
pool->id2arch && (ss->arch > pool->lastarch || !pool->id2arch[ss->arch]))
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_2), 1), solvid2str(pool, source).c_str());
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_3), 1), solvid2str(pool, source).c_str());
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_2), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_3), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP:
return tfm::format(TM_(problemDict.at(RULE_PKG_NOTHING_PROVIDES_DEP), 1), pool_dep2str(pool, dep),
- solvid2str(pool, source).c_str());
+ solvid2str(pool, source).c_str(), pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_PKG_SAME_NAME:
return tfm::format(TM_(problemDict.at(RULE_PKG_SAME_NAME), 1), solvid2str(pool, source).c_str(),
- solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, solvid2str(pool, target).c_str(),
+ pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_CONFLICTS:
return tfm::format(TM_(problemDict.at(RULE_PKG_CONFLICTS), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep), solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep),
+ solvid2str(pool, target).c_str(), pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_OBSOLETES:
return tfm::format(TM_(problemDict.at(RULE_PKG_OBSOLETES), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep), solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep),
+ solvid2str(pool, target).c_str(), pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_INSTALLED_OBSOLETES:
return tfm::format(TM_(problemDict.at(RULE_PKG_INSTALLED_OBSOLETES), 1),
solvid2str(pool, source).c_str(), pool_dep2str(pool, dep),
- solvid2str(pool, target).c_str());
+ solvid2str(pool, target).c_str(), pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_IMPLICIT_OBSOLETES:
return tfm::format(TM_(problemDict.at(RULE_PKG_IMPLICIT_OBSOLETES), 1),
solvid2str(pool, source).c_str(), pool_dep2str(pool, dep),
- solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, solvid2str(pool, target).c_str(),
+ pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_REQUIRES:
return tfm::format(TM_(problemDict.at(RULE_PKG_REQUIRES), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep));
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep));
case SOLVER_RULE_PKG_SELF_CONFLICT:
return tfm::format(TM_(problemDict.at(RULE_PKG_SELF_CONFLICT), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep));
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep));
case SOLVER_RULE_YUMOBS:
return tfm::format(TM_(problemDict.at(RULE_YUMOBS), 1), solvid2str(pool, source).c_str(),
- solvid2str(pool, target).c_str(), pool_dep2str(pool, dep));
+ pool_id2solvable(pool, source)->repo->name, solvid2str(pool, target).c_str(),
+ pool_id2solvable(pool, target)->repo->name, pool_dep2str(pool, dep));
default:
return solver_problemruleinfo2str(solv, type, source, target, dep);
}
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 546d5837..0dbece4d 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -341,7 +341,7 @@ ModulePackageContainer::add(const std::string &fileContent, const std::string &
// add all modules to repository and pass ownership to module container
g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(), "/etc/dnf/modules.d", NULL);
- auto packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID);
+ auto packages = md.getAllModulePackages(pImpl->moduleSack, repo, repoID);
for(auto const& modulePackagePtr: packages) {
std::unique_ptr<ModulePackage> modulePackage(modulePackagePtr);
pImpl->modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
diff --git a/tests/hawkey/test_goal.cpp b/tests/hawkey/test_goal.cpp
index f22e1c80..b2d7af9f 100644
--- a/tests/hawkey/test_goal.cpp
+++ b/tests/hawkey/test_goal.cpp
@@ -593,11 +593,11 @@ START_TEST(test_goal_describe_problem_rules)
auto problems = goal->describeProblemRules(0, true);
const char *expected[] = {
"conflicting requests",
- "nothing provides goodbye needed by hello-1-1.noarch"
+ "nothing provides goodbye needed by hello-1-1.noarch from main"
};
- fail_unless(problems.size() == 2);
- fail_unless(problems[0] == expected[0]);
- fail_unless(problems[1] == expected[1]);
+ ck_assert_int_eq(problems.size(), 2);
+ ck_assert_str_eq(problems[0].c_str(), expected[0]);
+ ck_assert_str_eq(problems[1].c_str(), expected[1]);
g_object_unref(pkg);
hy_goal_free(goal);
@@ -860,10 +860,10 @@ START_TEST(test_goal_lock)
auto problems = goal->describeProblemRules(0, true);
const char *expected[] = {
- "package bloop-ext-2.0-1.noarch requires bloop = 2.0-1, but none of the providers can be installed",
- "cannot install both bloop-2.0-1.noarch and bloop-1.0-1.noarch",
+ "package bloop-ext-2.0-1.noarch from updates requires bloop = 2.0-1, but none of the providers can be installed",
+ "cannot install both bloop-2.0-1.noarch from updates and bloop-1.0-1.noarch from @System",
"conflicting requests",
- "package bloop-ext-1.0-1.noarch is filtered out by exclude filtering"
+ "package bloop-ext-1.0-1.noarch from updates is filtered out by exclude filtering"
};
ck_assert_int_eq(problems.size(), 4);
ck_assert_str_eq(problems[0].c_str(), expected[0]);
--
2.40.1

View File

@ -0,0 +1,47 @@
From a5fe0e0eb6457ca51fabe8123d7407951cb8fcba Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Wed, 24 May 2023 12:35:29 +0200
Subject: [PATCH] conf: Support "proxy=_none_" in main config (RhBug:2155713)
It has the same meaning as "proxy=". Introduced for compatibility with yum.
Yum does not support a proxy option with an empty value. Instead, it has
the special value "_none_". The value "_none_" is case insensitive.
Support for "proxy=_none_" in the repository configuration was added some
time ago - in commit ea749e6238cdb54fe3b5add67875ab5912d2e766
= changelog =
msg: Support "proxy=_none_" in main config
type: enhancement
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2155713
---
libdnf/conf/ConfigMain.cpp | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/libdnf/conf/ConfigMain.cpp b/libdnf/conf/ConfigMain.cpp
index a6645d70..a775cf8c 100644
--- a/libdnf/conf/ConfigMain.cpp
+++ b/libdnf/conf/ConfigMain.cpp
@@ -476,7 +476,18 @@ ConfigMain::Impl::Impl(Config & owner)
}, nullptr, true
);
- owner.optBinds().add("proxy", proxy);
+ owner.optBinds().add("proxy", proxy,
+ [&](Option::Priority priority, const std::string & value){
+ auto tmpValue(value);
+ for (auto & ch : tmpValue)
+ ch = std::tolower(ch);
+ if (tmpValue == "_none_")
+ proxy.set(priority, "");
+ else
+ proxy.set(priority, value);
+ }, nullptr, false
+ );
+
owner.optBinds().add("proxy_username", proxy_username);
owner.optBinds().add("proxy_password", proxy_password);
owner.optBinds().add("proxy_auth_method", proxy_auth_method);
--
2.40.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
From d138dbf60588b73a8ee9499540c82a8950ba9432 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

View File

@ -0,0 +1,99 @@
From c32ce1071807176eb31d884d4185b20d944a28b9 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 b771030..6939d8a 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -639,6 +639,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)
@@ -1324,10 +1330,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;
}
@@ -1345,17 +1365,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

View File

@ -0,0 +1,335 @@
From 8752006f5f9c11bca3f04c99b463fd167caf0ddd 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 | 121 +++++++++++++++++++++++++++++++++++++-----
4 files changed, 129 insertions(+), 14 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d895b2bf..e5829e6a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,6 +34,7 @@ option(WITH_MAN "Enables hawkey man page generation" ON)
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(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 aa51dd28..df482f54 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
@@ -84,6 +86,9 @@ BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
BuildRequires: pkgconfig(libcrypto)
+%if %{with selinux}
+BuildRequires: pkgconfig(libselinux)
+%endif
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
@@ -205,7 +210,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
@@ -219,7 +225,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 998a6f94..10b15230 100644
--- a/libdnf/CMakeLists.txt
+++ b/libdnf/CMakeLists.txt
@@ -89,6 +89,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 d61a24a5..68b82ccc 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>
@@ -649,6 +654,78 @@ 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 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)) {
+ 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
+
+ return retval;
+}
+
static void gpgImportKey(gpgme_ctx_t context, int keyFd)
{
auto logger(Log::getLogger());
@@ -703,8 +780,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";
- mkdtemp(tmpdir);
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ create_temporary_directory(tmpdir);
Finalizer tmpDirRemover([&tmpdir](){
dnf_remove_recursive(tmpdir, NULL);
});
@@ -853,6 +930,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.
@@ -861,14 +945,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;
}
}
@@ -1151,8 +1248,8 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
bool Repo::Impl::isMetalinkInSync()
{
auto logger(Log::getLogger());
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- mkdtemp(tmpdir);
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ create_temporary_directory(tmpdir);
Finalizer tmpDirRemover([&tmpdir](){
dnf_remove_recursive(tmpdir, NULL);
});
@@ -1221,8 +1318,8 @@ bool Repo::Impl::isRepomdInSync()
{
auto logger(Log::getLogger());
LrYumRepo *yum_repo;
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- mkdtemp(tmpdir);
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ create_temporary_directory(tmpdir);
Finalizer tmpDirRemover([&tmpdir](){
dnf_remove_recursive(tmpdir, NULL);
});
@@ -1260,8 +1357,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

View File

@ -0,0 +1,228 @@
From 5b87a29c78fe7b3fce8ac167a1a650449d25f54c Mon Sep 17 00:00:00 2001
From: Dmitriy Popov <dpopov@cloudlinux.com>
Date: Wed, 1 May 2024 23:16:47 +0300
Subject: [PATCH] dnf-keyring-support-multiple-keys
Since it is known from the bug (and practically proven) that "rpm --import"
is capable of supporting multiple containers in one file, unlike the internal
implementation, due to the need to globally rewrite the structure of parameters.
https://github.com/rpm-software-management/rpm/pull/2242
"This does not affect rpmkeys --import because it explicitly checks
for multiple PGPTAG_PUBLIC_KEY packets and imports them separately"
The patch implies the logic of the cli rpmcliImportPubkeys
in dnf_keyring_add_public_key, except that instead of direct import,
it continues to expand the keyring as before, and then imports it,
making this change atomic.
Signed-off-by: Dmitriy Popov <dpopov@cloudlinux.com>
---
libdnf/dnf-keyring.cpp | 167 +++++++++++++++++++++++------------------
1 file changed, 96 insertions(+), 71 deletions(-)
diff --git a/libdnf/dnf-keyring.cpp b/libdnf/dnf-keyring.cpp
index 62a6248..f4afd35 100644
--- a/libdnf/dnf-keyring.cpp
+++ b/libdnf/dnf-keyring.cpp
@@ -62,13 +62,16 @@ dnf_keyring_add_public_key(rpmKeyring keyring,
gboolean ret = TRUE;
int rc;
gsize len;
- pgpArmor armor;
pgpDig dig = NULL;
rpmPubkey pubkey = NULL;
rpmPubkey *subkeys = NULL;
int nsubkeys = 0;
uint8_t *pkt = NULL;
g_autofree gchar *data = NULL;
+ char const * const pgpmark = "-----BEGIN PGP ";
+ size_t marklen = strlen(pgpmark);
+ int keyno = 1;
+ char *start = NULL;
/* ignore symlinks and directories */
if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
@@ -81,79 +84,99 @@ dnf_keyring_add_public_key(rpmKeyring keyring,
if (!ret)
goto out;
- /* rip off the ASCII armor and parse it */
- armor = pgpParsePkts(data, &pkt, &len);
- if (armor < 0) {
- ret = FALSE;
- g_set_error(error,
- DNF_ERROR,
- DNF_ERROR_GPG_SIGNATURE_INVALID,
- "failed to parse PKI file %s",
- filename);
- goto out;
- }
-
- /* make sure it's something we can add to rpm */
- if (armor != PGPARMOR_PUBKEY) {
- ret = FALSE;
- g_set_error(error,
- DNF_ERROR,
- DNF_ERROR_GPG_SIGNATURE_INVALID,
- "PKI file %s is not a public key",
- filename);
- goto out;
- }
+ start = strstr(data, pgpmark);
- /* test each one */
- pubkey = rpmPubkeyNew(pkt, len);
- if (pubkey == NULL) {
- ret = FALSE;
- g_set_error(error,
- DNF_ERROR,
- DNF_ERROR_GPG_SIGNATURE_INVALID,
- "failed to parse public key for %s",
- filename);
- goto out;
- }
-
- /* does the key exist in the keyring */
- dig = rpmPubkeyDig(pubkey);
- rc = rpmKeyringLookup(keyring, dig);
- if (rc == RPMRC_OK) {
- ret = TRUE;
- g_debug("%s is already present", filename);
- goto out;
- }
+ do {
+ uint8_t *pkt = NULL;
+ uint8_t *pkti = NULL;
+ size_t pktlen = 0;
+ size_t certlen;
+
+ /* Read pgp packet. */
+ if (pgpParsePkts(start, &pkt, &pktlen) == PGPARMOR_PUBKEY) {
+ pkti = pkt;
+
+ /* Iterate over certificates in pkt */
+ while (pktlen > 0) {
+ if (pgpPubKeyCertLen(pkti, pktlen, &certlen)) {
+ g_debug("%s: key %d import failed.\n", filename, keyno);
+ break;
+ }
+
+ /* test each one */
+ pubkey = rpmPubkeyNew(pkti, certlen);
+ if (pubkey == NULL) {
+ ret = FALSE;
+ g_set_error(error,
+ DNF_ERROR,
+ DNF_ERROR_GPG_SIGNATURE_INVALID,
+ "failed to parse public key for %s",
+ filename);
+ goto out;
+ }
+
+ /* add to in-memory keyring */
+ rc = rpmKeyringAddKey(keyring, pubkey);
+ if (rc == 1) {
+ ret = TRUE;
+ g_debug("%s is already added", filename);
+ goto out;
+ } else if (rc < 0) {
+ ret = FALSE;
+ g_set_error(error,
+ DNF_ERROR,
+ DNF_ERROR_GPG_SIGNATURE_INVALID,
+ "failed to add public key %s to rpmdb",
+ filename);
+ goto out;
+ }
+
+ subkeys = rpmGetSubkeys(pubkey, &nsubkeys);
+ for (int i = 0; i < nsubkeys; i++) {
+ rpmPubkey subkey = subkeys[i];
+ if (rpmKeyringAddKey(keyring, subkey) < 0) {
+ ret = FALSE;
+ g_set_error(error,
+ DNF_ERROR,
+ DNF_ERROR_GPG_SIGNATURE_INVALID,
+ "failed to add subkeys for %s to rpmdb",
+ filename);
+ goto out;
+ }
+ }
+
+ pkti += certlen;
+ pktlen -= certlen;
+ }
+ } else {
+ g_debug("%s: key %d not an armored public key.\n", filename, keyno);
+ }
- /* add to rpmdb automatically, without a prompt */
- rc = rpmKeyringAddKey(keyring, pubkey);
- if (rc == 1) {
- ret = TRUE;
- g_debug("%s is already added", filename);
- goto out;
- } else if (rc < 0) {
- ret = FALSE;
- g_set_error(error,
- DNF_ERROR,
- DNF_ERROR_GPG_SIGNATURE_INVALID,
- "failed to add public key %s to rpmdb",
- filename);
- goto out;
- }
+ /* See if there are more keys in the buffer */
+ if (start && start + marklen < data + len) {
+ start = strstr(start + marklen, pgpmark);
+ } else {
+ start = NULL;
+ }
- subkeys = rpmGetSubkeys(pubkey, &nsubkeys);
- for (int i = 0; i < nsubkeys; i++) {
- rpmPubkey subkey = subkeys[i];
- if (rpmKeyringAddKey(keyring, subkey) < 0) {
- ret = FALSE;
- g_set_error(error,
- DNF_ERROR,
- DNF_ERROR_GPG_SIGNATURE_INVALID,
- "failed to add subkeys for %s to rpmdb",
- filename);
- goto out;
+ keyno++;
+ if (pkt != NULL)
+ free(pkt); /* yes, free() */
+ pkt = NULL;
+ if (pubkey != NULL)
+ rpmPubkeyFree(pubkey);
+ pubkey = NULL;
+ if (subkeys != NULL) {
+ for (int i = 0; i < nsubkeys; i++) {
+ if (subkeys[i] != NULL) {
+ rpmPubkeyFree (subkeys[i]);
+ subkeys[i] = NULL;
+ }
+ }
+ free (subkeys);
+ subkeys = NULL;
}
- }
+ } while (start != NULL);
/* success */
g_debug("added missing public key %s to rpmdb", filename);
@@ -165,7 +188,9 @@ out:
rpmPubkeyFree(pubkey);
if (subkeys != NULL) {
for (int i = 0; i < nsubkeys; i++) {
- rpmPubkeyFree(subkeys[i]);
+ if (subkeys[i] != NULL) {
+ rpmPubkeyFree (subkeys[i]);
+ }
}
free(subkeys);
}
--
2.34.1

View File

@ -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: 14%{?dist}.alma
Release: 19%{?dist}.alma.2
Summary: Library providing simplified C and Python API to libsolv
License: LGPLv2+
URL: https://github.com/rpm-software-management/libdnf
@ -104,11 +106,18 @@ Patch40: 0040-Add-obsoletes-to-filtering-for-advisory-candidates.patch
Patch41: 0041-Fix-listing-a-repository-without-cpeid-RhBug-2066334.patch
Patch42: 0042-Allow-change-of-arch-during-security-updates-with-no.patch
Patch43: 0043-Update-translations.patch
Patch44: 0044-Add_repoid_to_solver_error_messagase.patch
Patch45: 0045-conf-Support-proxy-_none_-in-main-config-RhBug-21557.patch
Patch46: 0046-Update-translations-RHEL-8.9.patch
Patch47: 0047-filterAdvisory-installed_solvables-sort-RhBug2212838.patch
Patch48: 0048-Avoid-reinstal-installonly-packages-marked-for-ERASE.patch
Patch49: 0049-PGP-Set-a-default-creation-SELinux-labels-on-GnuPG-d.patch
# Almalinux patches
Patch10001: almalinux_bugtracker.patch
Patch10002: dnf-keyring-support-multiple-keys.patch
BuildRequires: cmake
BuildRequires: gcc
@ -132,6 +141,9 @@ BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
BuildRequires: pkgconfig(libcrypto)
%if %{with selinux}
BuildRequires: pkgconfig(libselinux)
%endif
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
@ -253,7 +265,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
@ -267,7 +280,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
@ -353,8 +367,25 @@ popd
%endif
%changelog
* Tue May 16 2023 Eduard Abdullin <eabdullin@almalinux.org> - 0.63.0-14.alma
* Fri May 24 2024 Eduard Abdullin <eabdullin@almalinux.org> - 0.63.0-19.alma.2
- Added patch for almalinux bugtracker
- Added patch to support multiple keys
* Wed Oct 18 2023 Petr Pisar <ppisar@redhat.com> - 0.63.0-19
- Set default SELinux labels on GnuPG directories (RHEL-6421)
* Fri Oct 13 2023 Jaroslav Rohel <jrohel@redhat.com> - 0.63.0-18
- filterAdvisory: match installed_solvables sort with lower_bound (RhBug:2212838, RHEL-1244)
- Avoid reinstalling installonly packages marked for ERASE (RhBug:2163474, RHEL-1253)
* Fri Sep 08 2023 Marek Blaha <mblaha@redhat.com> - 0.63.0-17
- Update translations
* Wed May 31 2023 Nicola Sella <nsella@redhat.com> - 0.63-0-16
- Support "proxy=_none_" in main config (RhBug:2155713)
* Wed May 17 2023 Jaroslav Rohel <jrohel@redhat.com> - 0.63.0-15
- Add repoid to solver error messages (RhBug:2179409,2179413)
* Wed Mar 08 2023 Marek Blaha <mblaha@redhat.com> - 0.63.0-14
- Update translations