backport 2 patches from upstream

This commit is contained in:
wangziliang 2024-07-02 06:40:42 +00:00
parent d99e9081d9
commit f0b24c689b
3 changed files with 178 additions and 1 deletions

View File

@ -0,0 +1,130 @@
From cc95edd15b8a4fc4c381c85735e2f14a1dc0852e Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Wed, 8 May 2024 12:05:21 +0200
Subject: [PATCH] Fix countme bucket calculation
Actually use the system's installation time (if known) as the reference
point, instead of the first-ever countme event recorded for the given
repo.
This is what the dnf.conf(5) man page always said about the countme
option, the code just never lived up to that.
This makes bucket calculation more accurate:
1. System upgrades will no longer reset the bucket to 1 (this used to be
the case due to a new persistdir being created whenever $releasever
changed).
2. Systems that only reach out to the repos after an initial time period
after being installed will no longer appear younger than they really
are.
3. Prebuilt OS images that happen to include countme cookies created at
build time will no longer cause all the instances spawned from those
images (physical machines, VMs or containers) to appear older than
they really are.
Use the machine-id(5) file's mtime to infer the installation time. This
file is semantically tied to the system's lifetime since it's typically
populated at installation time or during the first boot by an installer
tool or init system, respectively, and remains unchanged.
The fact that it's a well-defined file with clear semantics ensures that
OS images won't accidentally include a prepopulated version of this file
with a timestamp corresponding to the image build, unlike our own cookie
files (see point 3 above).
In some cases, such as in OCI containers without an init system running,
the machine-id file may be missing or empty, even though the system is
still used long-term. To cover those, keep the original, relative epoch
as a fallback method. System upgrades aren't really a thing for such
systems so the above point 1 doesn't apply here.
Some containers, such as those created by toolbox(1), may also choose to
bind-mount the host's machine-id file, thus falling into the same bucket
as their host. Conveniently, that's what we want, since the purpose of
such containers is to blend with the host as much as possible.
Fixes: #1611
---
libdnf/repo/Repo-private.hpp | 1 +
libdnf/repo/Repo.cpp | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/libdnf/repo/Repo-private.hpp b/libdnf/repo/Repo-private.hpp
index 1f659e6f..88cadf7d 100644
--- a/libdnf/repo/Repo-private.hpp
+++ b/libdnf/repo/Repo-private.hpp
@@ -91,6 +91,7 @@ public:
void fetch(const std::string & destdir, std::unique_ptr<LrHandle> && h);
std::string getCachedir() const;
std::string getPersistdir() const;
+ time_t getSystemEpoch() const;
int getAge() const;
void expire();
bool isExpired() const;
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 40b0b68e..ead98618 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -900,7 +900,7 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
// Load the cookie
std::string fname = getPersistdir() + "/" + COUNTME_COOKIE;
int ver = COUNTME_VERSION; // file format version (for future use)
- time_t epoch = 0; // position of first-ever counted window
+ time_t epoch = 0; // position of first observed window
time_t win = COUNTME_OFFSET; // position of last counted window
int budget = -1; // budget for this window (-1 = generate)
std::ifstream(fname) >> ver >> epoch >> win >> budget;
@@ -926,8 +926,15 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
// Compute the position of this window
win = now - (delta % COUNTME_WINDOW);
+
+ // Compute the epoch from this system's epoch or, if unknown, declare
+ // this window as the epoch (unless stored in the cookie previously).
+ time_t sysepoch = getSystemEpoch();
+ if (sysepoch)
+ epoch = sysepoch - ((sysepoch - COUNTME_OFFSET) % COUNTME_WINDOW);
if (!epoch)
epoch = win;
+
// Window step (0 at epoch)
int step = (win - epoch) / COUNTME_WINDOW;
@@ -1221,6 +1228,31 @@ std::string Repo::Impl::getPersistdir() const
return result;
}
+/* Returns this system's installation time ("epoch") as a UNIX timestamp.
+ *
+ * Uses the machine-id(5) file's mtime as a good-enough source of truth. This
+ * file is typically tied to the system's installation or first boot where it's
+ * populated by an installer tool or init system, respectively, and is never
+ * changed afterwards.
+ *
+ * Some systems, such as containers that don't run an init system, may have the
+ * file missing, empty or uninitialized, in which case this function returns 0.
+ */
+time_t Repo::Impl::getSystemEpoch() const
+{
+ std::string filename = "/etc/machine-id";
+ std::string id;
+ struct stat st;
+
+ if (stat(filename.c_str(), &st) != 0 || !st.st_size)
+ return 0;
+ std::ifstream(filename) >> id;
+ if (id == "uninitialized")
+ return 0;
+
+ return st.st_mtime;
+}
+
int Repo::Impl::getAge() const
{
return time(NULL) - mtime(getMetadataPath(MD_TYPE_PRIMARY).c_str());
--
2.33.0

View File

@ -0,0 +1,39 @@
From 9c6e1c90b96cdb44d0093e417bd5d2e710881f94 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Wed, 8 May 2024 12:05:16 +0200
Subject: [PATCH] Fix up some comments in addCountmeFlag()
The buckets aren't really an array that's indexed in the code, they're
just sequential numbers for the URL flag. Also clarify why we're using
"this window" instead of "the current position of the sliding window" in
the comments.
---
libdnf/repo/Repo.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 73a3d7b4..40b0b68e 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -873,6 +873,9 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
* This is to align the time window with an absolute point in time rather
* than the last counting event (which could facilitate tracking across
* multiple such events).
+ *
+ * In the below comments, the window's current position will be referred to
+ * as "this window" for brevity.
*/
auto logger(Log::getLogger());
@@ -933,7 +936,7 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
for (i = 0; i < COUNTME_BUCKETS.size(); ++i)
if (step < COUNTME_BUCKETS[i])
break;
- int bucket = i + 1; // Buckets are indexed from 1
+ int bucket = i + 1; // Buckets are numbered from 1
// Set the flag
std::string flag = "countme=" + std::to_string(bucket);
--
2.33.0

View File

@ -18,7 +18,7 @@
Name: libdnf
Version: 0.70.2
Release: 4
Release: 5
Summary: Library providing simplified C and Python API to libsolv
License: LGPL-2.1-or-later
URL: https://github.com/rpm-software-management/libdnf
@ -51,6 +51,8 @@ Patch6005: backport-dnf-repo-Fix-utimes-error-messages.patch
Patch6006: backport-subject-py-Fix-memory-leak.patch
Patch6007: backport-MergedTransaction-Calculate-RPM-difference-between-two-same-versions-as-no-op.patch
Patch6008: backport-MergedTransaction-Fix-invalid-memory-access-when-dropping.patch
Patch6009: backport-Fix-countme-bucket-calculation.patch
Patch6010: backport-Fix-up-some-comments-in-addCountmeFlag.patch
%description
A Library providing simplified C and Python API to libsolv.
@ -130,6 +132,12 @@ popd
%{python3_sitearch}/hawkey/
%changelog
* Tue Jul 02 2024 wangziliang <wangziliang@kylinos.cn> - 0.70.2-5
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC: Fix countme bucket calculation
* Fri Jun 14 2024 hanhuihui <hanhuihui5@huawei.com> - 0.70.2-4
- Type:bugfix
- CVE:NA