Skip to content

Commit

Permalink
Use rpmdbCookie from librpm, remove hawkey.Sack._rpmdb_version
Browse files Browse the repository at this point in the history
`dnf_sack_get_rpmdb_version` function that computed the hash of installed
packages was removed. `rpmdbCookie` function from librpm is used in context
part of libdnf instead.

The private Python function `hawkey.Sack._rpmdb_version()` was removed too.
It was used by DNF. The new version of DNF uses
`rpm.TransactionSet.dbCookie()` function from librpm, which wraps
the `rpmdbCookie` function. So the same librpm function will be used
in context part of libdnf (e.g. by microdnf) and in the DNF.

`rpmdbCookie` funkcion is safer. It also detect reinstalation of package
as a change. That will be needed in the future to determining if the libsolv
cache is still valid.
It also solves the libdnf problem with SHA1 in FIPS mode.

= changelog =
msg: Use `rpmdbCookie` from librpm, remove `hawkey.Sack._rpmdb_version`
type: bugfix
related: https://bugzilla.redhat.com/show_bug.cgi?id=2043476
  • Loading branch information
jrohel authored and j-mracek committed Feb 4, 2022
1 parent e006df8 commit 6fd718b
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 87 deletions.
2 changes: 1 addition & 1 deletion VERSION.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
set (DEFAULT_LIBDNF_MAJOR_VERSION 0)
set (DEFAULT_LIBDNF_MINOR_VERSION 65)
set (DEFAULT_LIBDNF_MINOR_VERSION 66)
set (DEFAULT_LIBDNF_MICRO_VERSION 0)

if(DEFINED LIBDNF_MAJOR_VERSION)
Expand Down
4 changes: 2 additions & 2 deletions libdnf.spec
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%global libsolv_version 0.7.20
%global libmodulemd_version 2.13.0
%global librepo_version 1.13.1
%global dnf_conflict 4.3.0
%global dnf_conflict 4.11.0
%global swig_version 3.0.12
%global libdnf_major_version 0
%global libdnf_minor_version 65
%global libdnf_minor_version 66
%global libdnf_micro_version 0

%define __cmake_in_source_build 1
Expand Down
15 changes: 0 additions & 15 deletions libdnf/dnf-sack-private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,4 @@ std::pair<std::vector<std::vector<std::string>>, libdnf::ModulePackageContainer:

std::vector<libdnf::ModulePackage *> requiresModuleEnablement(DnfSack * sack, const libdnf::PackageSet * installSet);

/**
* @brief Return fingerprint of installed RPMs.
* The format is <count>:<hash>.
* <count> is a count of installed RPMs.
* <hash> is a sha1 hash of sorted sha1hdr hashes of installed RPMs.
*
* The count can be computed from the command line by running:
* rpm -qa --qf='%{name}\n' | grep -v '^gpg-pubkey$' | wc -l
*
* The hash can be computed from the command line by running:
* rpm -qa --qf='%{name} %{sha1header}\n' | grep -v '^gpg-pubkey ' \
* | cut -d ' ' -f 2 | LC_ALL=C sort | tr -d '\n' | sha1sum
*/
std::string dnf_sack_get_rpmdb_version(DnfSack *sack);

#endif // HY_SACK_INTERNAL_H
40 changes: 0 additions & 40 deletions libdnf/dnf-sack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ extern "C" {
#include "module/ModulePackage.hpp"
#include "repo/Repo-private.hpp"
#include "repo/solvable/DependencyContainer.hpp"
#include "utils/crypto/sha1.hpp"
#include "utils/File.hpp"
#include "utils/utils.hpp"
#include "log.hpp"
Expand Down Expand Up @@ -2535,42 +2534,3 @@ std::pair<std::vector<std::vector<std::string>>, libdnf::ModulePackageContainer:
setModuleExcludes(sack, hotfixRepos, *moduleContainer);
return ret;
}

std::string dnf_sack_get_rpmdb_version(DnfSack *sack) {
// collect all sha1hdr checksums
// they are sufficiently unique IDs that represent installed RPMs
std::vector<std::string> checksums;

// iterate all @System repo RPMs (rpmdb records)
libdnf::Query query{sack, libdnf::Query::ExcludeFlags::IGNORE_EXCLUDES};
query.installed();

auto pset = query.getResultPset();
Id id = -1;
while(true) {
id = pset->next(id);
if (id == -1) {
break;
}
DnfPackage *pkg = dnf_package_new(sack, id);
// store pkgid (equals to sha1hdr)
checksums.push_back(libdnf::string::fromCstring(dnf_package_get_pkgid(pkg)));
g_object_unref(pkg);
}

// sort checksums to compute the output checksum always the same
std::sort(checksums.begin(), checksums.end());

SHA1Hash h;
for (auto & checksum : checksums) {
h.update(checksum.c_str());
}

// build <count>:<hash> output
std::ostringstream result;
result << checksums.size();
result << ":";
result << h.hexdigest();

return result.str();
}
48 changes: 27 additions & 21 deletions libdnf/dnf-transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* This object represents an RPM transaction.
*/

#include <rpm/rpmdb.h>
#include <rpm/rpmlib.h>
#include <rpm/rpmlog.h>
#include <rpm/rpmts.h>
Expand All @@ -53,6 +54,7 @@
#include "transaction/Swdb.hpp"
#include "transaction/Transformer.hpp"
#include "utils/bgettext/bgettext-lib.h"
#include "utils/utils.hpp"

typedef enum {
DNF_TRANSACTION_STEP_STARTED,
Expand Down Expand Up @@ -1136,9 +1138,8 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state
libdnf::Swdb *swdb = priv->swdb;
PluginHookContextTransactionData data{PLUGIN_HOOK_ID_CONTEXT_PRE_TRANSACTION, transaction, goal, state};
DnfSack * sack = hy_goal_get_sack(goal);
DnfSack * rpmdb_version_sack = NULL;
std::string rpmdb_begin;
std::string rpmdb_end;
std::unique_ptr<char, decltype(free)*> rpmdb_cookie_uptr{nullptr, free};
std::string rpmdb_cookie;

/* take lock */
ret = dnf_state_take_lock(state, DNF_LOCK_TYPE_RPMDB, DNF_LOCK_MODE_PROCESS, error);
Expand Down Expand Up @@ -1431,17 +1432,24 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state
if (!dnf_context_plugin_hook(priv->context, PLUGIN_HOOK_ID_CONTEXT_PRE_TRANSACTION, &data, nullptr))
goto out;

// FIXME get commandline
if (sack) {
rpmdb_begin = dnf_sack_get_rpmdb_version(sack);
} else {
// if sack is not available, create a custom instance
rpmdb_version_sack = dnf_sack_new();
dnf_sack_load_system_repo(rpmdb_version_sack, nullptr, DNF_SACK_LOAD_FLAG_NONE, nullptr);
rpmdb_begin = dnf_sack_get_rpmdb_version(rpmdb_version_sack);
g_object_unref(rpmdb_version_sack);
// Open rpm database if it is not already open
if (!rpmtsGetRdb(priv->ts)) {
rc = rpmtsOpenDB(priv->ts, rpmtsGetDBMode(priv->ts));
if (rc != 0) {
ret = FALSE;
g_set_error(
error, DNF_ERROR, DNF_ERROR_INTERNAL_ERROR, _("Error %i opening rpm database"), rc);
goto out;
}
}
swdb->beginTransaction(_get_current_time(), rpmdb_begin, "", priv->uid);

rpmdb_cookie_uptr.reset(rpmdbCookie(rpmtsGetRdb(priv->ts)));
rpmdb_cookie = libdnf::string::fromCstring(rpmdb_cookie_uptr.get());
if (rpmdb_cookie.empty()) {
g_critical(_("The rpmdbCookie() function did not return cookie of rpm database."));
}
// FIXME get commandline
swdb->beginTransaction(_get_current_time(), rpmdb_cookie, "", priv->uid);

/* run the transaction */
priv->state = dnf_state_get_child(state);
Expand Down Expand Up @@ -1481,14 +1489,12 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state
if (!ret)
goto out;

// finalize swdb transaction
// always load a new sack with rpmdb state after the transaction
rpmdb_version_sack = dnf_sack_new();
dnf_sack_load_system_repo(rpmdb_version_sack, nullptr, DNF_SACK_LOAD_FLAG_NONE, nullptr);
rpmdb_end = dnf_sack_get_rpmdb_version(rpmdb_version_sack);
g_object_unref(rpmdb_version_sack);

swdb->endTransaction(_get_current_time(), rpmdb_end.c_str(), libdnf::TransactionState::DONE);
rpmdb_cookie_uptr.reset(rpmdbCookie(rpmtsGetRdb(priv->ts)));
rpmdb_cookie = libdnf::string::fromCstring(rpmdb_cookie_uptr.get());
if (rpmdb_cookie.empty()) {
g_critical(_("The rpmdbCookie() function did not return cookie of rpm database."));
}
swdb->endTransaction(_get_current_time(), rpmdb_cookie, libdnf::TransactionState::DONE);
swdb->closeTransaction();

data.hookId = PLUGIN_HOOK_ID_CONTEXT_TRANSACTION;
Expand Down
8 changes: 0 additions & 8 deletions python/hawkey/sack-py.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -783,13 +783,6 @@ load_repo(_SackObject *self, PyObject *args, PyObject *kwds) try
Py_RETURN_NONE;
} CATCH_TO_PYTHON

static PyObject *
rpmdb_version(_SackObject *self, PyObject *unused) try
{
auto result = dnf_sack_get_rpmdb_version(self->sack);
return PyString_FromString(result.c_str());
} CATCH_TO_PYTHON

static Py_ssize_t
len(_SackObject *self) try
{
Expand Down Expand Up @@ -858,7 +851,6 @@ PyMethodDef sack_methods[] = {
METH_VARARGS | METH_KEYWORDS, NULL},
{"load_repo", (PyCFunction)load_repo, METH_VARARGS | METH_KEYWORDS,
NULL},
{"_rpmdb_version", (PyCFunction)rpmdb_version, METH_VARARGS | METH_KEYWORDS, NULL},
{NULL} /* sentinel */
};

Expand Down

0 comments on commit 6fd718b

Please sign in to comment.