From f07d74c3e62016c8ca35dd8cba9ba898285528fa Mon Sep 17 00:00:00 2001 From: LuWu <2398491106@qq.com> Date: Wed, 17 Jul 2024 15:32:58 +0800 Subject: [PATCH] [Backport]libdnf:Fix countme bucket calculation Reference:https://github.com/rpm-software-management/libdnf/commit/a41a2803dc8b24c83ed85718746fa97c1502de3d https://github.com/rpm-software-management/libdnf/commit/a7ef27917f01b32e44d0a5bbf7b06104f8275ec5 Conflict:no --- backport-Fix-countme-bucket-calculation.patch | 130 ++++++++++++++++++ ...x-up-some-comments-in-addCountmeFlag.patch | 39 ++++++ libdnf.spec | 7 +- 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 backport-Fix-countme-bucket-calculation.patch create mode 100644 backport-Fix-up-some-comments-in-addCountmeFlag.patch diff --git a/backport-Fix-countme-bucket-calculation.patch b/backport-Fix-countme-bucket-calculation.patch new file mode 100644 index 0000000..acb2b4b --- /dev/null +++ b/backport-Fix-countme-bucket-calculation.patch @@ -0,0 +1,130 @@ +From a7ef27917f01b32e44d0a5bbf7b06104f8275ec5 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +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 + +Conflict:NA +Reference:https://github.com/rpm-software-management/libdnf/commit/a7ef27917f01b32e44d0a5bbf7b06104f8275ec5 +--- + 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 1f659e6fb..88cadf7d6 100644 +--- a/libdnf/repo/Repo-private.hpp ++++ b/libdnf/repo/Repo-private.hpp +@@ -91,6 +91,7 @@ class Repo::Impl { + void fetch(const std::string & destdir, std::unique_ptr && 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 40b0b68ec..ead986189 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()); diff --git a/backport-Fix-up-some-comments-in-addCountmeFlag.patch b/backport-Fix-up-some-comments-in-addCountmeFlag.patch new file mode 100644 index 0000000..85a78b5 --- /dev/null +++ b/backport-Fix-up-some-comments-in-addCountmeFlag.patch @@ -0,0 +1,39 @@ +From a41a2803dc8b24c83ed85718746fa97c1502de3d Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +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. + +Conflict:NA +Reference:https://github.com/rpm-software-management/libdnf/commit/a41a2803dc8b24c83ed85718746fa97c1502de3d +--- + 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 73a3d7b42..40b0b68ec 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); diff --git a/libdnf.spec b/libdnf.spec index ab78f65..de2d983 100644 --- a/libdnf.spec +++ b/libdnf.spec @@ -18,7 +18,7 @@ Name: libdnf Version: 0.69.0 -Release: 9 +Release: 10 Summary: Library providing simplified C and Python API to libsolv License: LGPLv2+ URL: https://github.com/rpm-software-management/libdnf @@ -51,6 +51,8 @@ Patch6007: backport-dnf-repo-Fix-utimes-error-messages.patch Patch6008: backport-MergedTransaction-Calculate-RPM-difference-between-two-same-versions-as-no-op.patch Patch6009: backport-subject-py-Fix-memory-leak.patch Patch6010: backport-MergedTransaction-Fix-invalid-memory-access-when-dropping.patch +Patch6011: backport-Fix-countme-bucket-calculation.patch +Patch6012: backport-Fix-up-some-comments-in-addCountmeFlag.patch %description A Library providing simplified C and Python API to libsolv. @@ -130,6 +132,9 @@ popd %{python3_sitearch}/hawkey/ %changelog +* Wed Jul 17 2024 LuWu <2398491106@qq.com> - 0.69.0-10 +- libdnf:Fix countme bucket calculation + * Fri Jun 14 2024 hanhuihui - 0.69.0-9 - Type:bugfix - CVE:NA -- Gitee