From 1cb1ad160e8850992cb751d227968247f337f620 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Tue, 19 May 2026 18:40:03 -0400 Subject: [PATCH] import UBI rpm-4.19.1.1-23.el10 --- ...rd-field-in-passwd-group-causing-ent.patch | 55 + ...lifiers-like-pre-post-meta-for-weak-.patch | 118 ++ rpm-4.19.x-multisig-verify-fixes.patch | 1194 +++++++++++++++++ rpm-4.19.x-nsswitch-enable.patch | 474 +++++++ rpm.spec | 24 +- 5 files changed, 1862 insertions(+), 3 deletions(-) create mode 100644 0001-Fix-empty-password-field-in-passwd-group-causing-ent.patch create mode 100644 0001-Really-allow-qualifiers-like-pre-post-meta-for-weak-.patch create mode 100644 rpm-4.19.x-multisig-verify-fixes.patch create mode 100644 rpm-4.19.x-nsswitch-enable.patch diff --git a/0001-Fix-empty-password-field-in-passwd-group-causing-ent.patch b/0001-Fix-empty-password-field-in-passwd-group-causing-ent.patch new file mode 100644 index 0000000..dc65ddc --- /dev/null +++ b/0001-Fix-empty-password-field-in-passwd-group-causing-ent.patch @@ -0,0 +1,55 @@ +From 234b0be3653d18e9e97fff060fb882eef97cd575 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 6 Mar 2025 13:57:09 +0200 +Subject: [PATCH] Fix empty password field in passwd/group causing entry to be + ignored + +strtok() only handles non-empty tokens. Says so on the first line of +the description on the man page. Doh. So use our own argv splitting, +this is actually more handy anyhow. + +Fixes: #3594 +(backported from commit 75de02219100f381a84769d74eb58985975d49c5) +--- + lib/rpmug.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/lib/rpmug.c b/lib/rpmug.c +index 895fb50bf..1f99987dc 100644 +--- a/lib/rpmug.c ++++ b/lib/rpmug.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -73,12 +74,11 @@ static int lookup_field_in_file(const char *path, const char *val, int vcol, int + while ((str = fgets(buf, sizeof(buf), f)) != NULL) { + int nf = vcol > rcol ? vcol : rcol; + const char *fields[nf + 1]; +- char *tok, *save = NULL; + int col = -1; + +- while ((tok = strtok_r(str, ":", &save)) != NULL) { +- fields[++col] = tok; +- str = NULL; ++ ARGV_t tokens = argvSplitString(str, ":", ARGV_NONE); ++ for (ARGV_const_t tok = tokens; tok && *tok; tok++) { ++ fields[++col] = *tok; + if (col >= nf) + break; + } +@@ -89,6 +89,7 @@ static int lookup_field_in_file(const char *path, const char *val, int vcol, int + rc = 0; + } + } ++ argvFree(tokens); + } + + fclose(f); +-- +2.52.0 + diff --git a/0001-Really-allow-qualifiers-like-pre-post-meta-for-weak-.patch b/0001-Really-allow-qualifiers-like-pre-post-meta-for-weak-.patch new file mode 100644 index 0000000..d26d77a --- /dev/null +++ b/0001-Really-allow-qualifiers-like-pre-post-meta-for-weak-.patch @@ -0,0 +1,118 @@ +From a382c58a59848d1a6f137ff9e2bc435ca99c31cf Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 12 Mar 2024 14:28:13 +0200 +Subject: [PATCH 1/2] Add the ability to pass qualifiers to our dependency + tests + +(cherry picked from commit 9cb05896f70ebc480f717d3f2f958e933b451a40) +--- + tests/data/SPECS/deptest.spec | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/data/SPECS/deptest.spec b/tests/data/SPECS/deptest.spec +index 5a1ecdc55..f7cc12df2 100644 +--- a/tests/data/SPECS/deptest.spec ++++ b/tests/data/SPECS/deptest.spec +@@ -8,15 +8,15 @@ Summary: Testing dependency behavior + Group: Testing + License: GPL + BuildArch: noarch +-%{?reqs:Requires: %{reqs}} ++%{?reqs:Requires%{?reqflags:(%{reqflags})}: %{reqs}} + %{?provs:Provides: %{provs}} + %{?cfls:Conflicts: %{cfls}} + %{?obs:Obsoletes: %{obs}} +-%{?recs:Recommends: %{recs}} +-%{?sugs:Suggests: %{sugs}} +-%{?sups:Supplements: %{sups}} +-%{?ens:Enhances: %{ens}} +-%{?ord:OrderWithRequires: %{ord}} ++%{?recs:Recommends%{?recflags:(%{recflags})}: %{recs}} ++%{?sugs:Suggests%{?sugflags:(%{sugflags})}: %{sugs}} ++%{?sups:Supplements%{?supflags:(%{supflags})}: %{sups}} ++%{?ens:Enhances%{?ensflags:(%{ensflags})}: %{ens}} ++%{?ord:OrderWithRequires%{?ordflags:(%{ordflags})}: %{ord}} + %{?buildreqs:BuildRequires: %{buildreqs}} + %{?buildcfls:BuildConflicts: %{buildcfls}} + +-- +2.52.0 + + +From 480294fb8bfb8c4b0544eccc2dd47fb25999255d Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 12 Mar 2024 13:55:09 +0200 +Subject: [PATCH 2/2] Really allow qualifiers like pre/post/meta for weak + dependencies + +Commit ddbf30cf96a33319805b362b01d8a6fdfe7dea9c neglected to update the +preamble table types for the weak dependency tags, so it never worked. +Add a test to ensure it works and stays that way. + +Test depends on 078ccae5a655e044a9b867206cf4215acb3f0113 + +Fixes: #624 +(backported from commit 0644ba5755360cd6a33caa41ea09d3e25096bc72) +--- + build/parsePreamble.c | 8 ++++---- + tests/rpmbuild.at | 18 ++++++++++-------- + 2 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/build/parsePreamble.c b/build/parsePreamble.c +index de205d5f8..3693746f8 100644 +--- a/build/parsePreamble.c ++++ b/build/parsePreamble.c +@@ -1032,10 +1032,10 @@ static struct PreambleRec_s const preambleList[] = { + {RPMTAG_ICON, 0, 0, 0, LEN_AND_STR("icon")}, + {RPMTAG_PROVIDENAME, 0, 0, 0, LEN_AND_STR("provides")}, + {RPMTAG_REQUIRENAME, 2, 0, 0, LEN_AND_STR("requires")}, +- {RPMTAG_RECOMMENDNAME, 0, 0, 0, LEN_AND_STR("recommends")}, +- {RPMTAG_SUGGESTNAME, 0, 0, 0, LEN_AND_STR("suggests")}, +- {RPMTAG_SUPPLEMENTNAME, 0, 0, 0, LEN_AND_STR("supplements")}, +- {RPMTAG_ENHANCENAME, 0, 0, 0, LEN_AND_STR("enhances")}, ++ {RPMTAG_RECOMMENDNAME, 2, 0, 0, LEN_AND_STR("recommends")}, ++ {RPMTAG_SUGGESTNAME, 2, 0, 0, LEN_AND_STR("suggests")}, ++ {RPMTAG_SUPPLEMENTNAME, 2, 0, 0, LEN_AND_STR("supplements")}, ++ {RPMTAG_ENHANCENAME, 2, 0, 0, LEN_AND_STR("enhances")}, + {RPMTAG_PREREQ, 2, 1, 0, LEN_AND_STR("prereq")}, + {RPMTAG_CONFLICTNAME, 0, 0, 0, LEN_AND_STR("conflicts")}, + {RPMTAG_OBSOLETENAME, 0, 0, 0, LEN_AND_STR("obsoletes")}, +diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at +index f98e4988f..1d61afd2f 100644 +--- a/tests/rpmbuild.at ++++ b/tests/rpmbuild.at +@@ -753,21 +753,23 @@ RPMDB_INIT + runroot rpmbuild -bb --quiet \ + --define "pkg weakdeps" \ + --define "recs foo > 1.2.3" \ ++ --define "recflags post" \ + --define "sugs bar >= 0.1.2" \ + --define "sups baz" \ ++ --define "supflags preun" \ + --define "ens zap = 3" \ + /data/SPECS/deptest.spec + +-runroot rpm -qp --recommends /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm +-runroot rpm -qp --suggests /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm +-runroot rpm -qp --supplements /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm +-runroot rpm -qp --enhances /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm ++runroot rpm -qpv --recommends /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm ++runroot rpm -qpv --suggests /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm ++runroot rpm -qpv --supplements /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm ++runroot rpm -qpv --enhances /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm + ], + [0], +-[foo > 1.2.3 +-bar >= 0.1.2 +-baz +-zap = 3 ++[post: foo > 1.2.3 ++manual: bar >= 0.1.2 ++preun: baz ++manual: zap = 3 + ], + [ignore]) + RPMTEST_CLEANUP +-- +2.52.0 + diff --git a/rpm-4.19.x-multisig-verify-fixes.patch b/rpm-4.19.x-multisig-verify-fixes.patch new file mode 100644 index 0000000..20f051b --- /dev/null +++ b/rpm-4.19.x-multisig-verify-fixes.patch @@ -0,0 +1,1194 @@ +From 78a9fa4a10143f5042e77cbc3c12dfde17d10d45 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 27 Oct 2025 14:06:20 +0200 +Subject: [PATCH 01/11] Explicitly require at least one success and no failures + for verify pass + +Shouldn't change behavior in itself, but makes it a little bit safer +in principle and needed for the next step. + +(cherry picked from commit 7760e5466643c9c4d6624359a8fc1b1f2f220cff) +--- + lib/rpmvs.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index b8e69955a..2d5400708 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -502,6 +502,7 @@ static const struct rpmsinfo_s *getAlt(const struct rpmvs_s *vs, const struct rp + int rpmvsVerify(struct rpmvs_s *sis, int type, + rpmsinfoCb cb, void *cbdata) + { ++ int success = 0; + int failed = 0; + int cont = 1; + int range = 0, vfylevel = sis->vfylevel; +@@ -566,11 +567,13 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, + if (cb) + cont = cb(sinfo, cbdata); + +- if (sinfo->rc != RPMRC_OK) +- failed = 1; ++ if (sinfo->rc == RPMRC_OK) ++ success++; ++ else ++ failed++; + } + +- return failed; ++ return (success >= 1 && failed == 0) ? 0 : failed; + } + + static const char * rpmSigString(rpmRC res) +-- +2.52.0 + + +From 427473300432a8395325bff4b91302c4588031f8 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 27 Oct 2025 14:00:20 +0200 +Subject: [PATCH 02/11] Ignore NOTTRUSTED returns in verification + +We have currently no way of differentiating between signatures whose +algorithm is disabled in system policy and ones that are otherwise +no longer trustworthy, eg due to expiration. The peculiar thing about +these cases is that they are neither failures nor are they positive +verifications. It seems they are best dealt with by simply ignoring, +except for the verbose output where they need to be shown for diagnostic +purposes. + +This pointed out multiple flaws in the verification machinery which +was still rather attuned to one signature per package, and making +assumptions that never were really valid, but completely broken now. + +We simply can't make decisions after any single item in the callback, +we need to process the whole lot to make sense of it, and we need +to rank our failure codes to figure the most relevant for the final +return. Also, we need to honor the configured verify level in the +transaction verification step too. + +One of the flaws found by this was that a V4 signature NOKEY result +was overriding a FAIL result from V3 signature. Adjust the original +test for to only check for V4 signatures, and add another test +exhibiting the new behavior where the failure shows up more prominently. + +Fixes: #3996 + +Backported from commit a594a12339e61057c15556ee71c44a5231fac9be +--- + lib/rpmvs.c | 14 ++++++++-- + lib/transaction.c | 67 ++++++++++++++++++++++++++++------------------- + 2 files changed, 52 insertions(+), 29 deletions(-) + +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index 2d5400708..667a2074f 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -567,10 +567,20 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, + if (cb) + cont = cb(sinfo, cbdata); + +- if (sinfo->rc == RPMRC_OK) ++ switch (sinfo->rc) { ++ case RPMRC_OK: + success++; +- else ++ break; ++ case RPMRC_FAIL: ++ case RPMRC_NOKEY: ++ case RPMRC_NOTFOUND: + failed++; ++ break; ++ case RPMRC_NOTTRUSTED: ++ default: ++ /* ignore */ ++ break; ++ }; + } + + return (success >= 1 && failed == 0) ? 0 : failed; +diff --git a/lib/transaction.c b/lib/transaction.c +index b828fe395..a3c95c3d7 100644 +--- a/lib/transaction.c ++++ b/lib/transaction.c +@@ -1232,38 +1232,51 @@ struct vfydata_s { + int vfylevel; + }; + ++static int sortRC(int rc) ++{ ++ switch (rc) { ++ case RPMRC_OK: return 0; ++ case RPMRC_NOTFOUND: return 1; ++ case RPMRC_NOTTRUSTED: return 2; ++ case RPMRC_NOKEY: return 3; ++ case RPMRC_FAIL: return 4; ++ } ++ return -1; ++} ++ + static int vfyCb(struct rpmsinfo_s *sinfo, void *cbdata) + { + struct vfydata_s *vd = cbdata; + +- if (sinfo->type & RPMSIG_VERIFIABLE_TYPE && sinfo->rc != RPMRC_NOTFOUND) { +- int res = (sinfo->rc != RPMRC_OK); +- /* Take care not to override a previous failure with success */ +- if (res > vd->type[sinfo->type]) +- vd->type[sinfo->type] = res; +- } ++ /* Take care not to override a previous failure with success */ ++ if (sortRC(sinfo->rc) > sortRC(vd->type[sinfo->type])) { + +- switch (sinfo->rc) { +- case RPMRC_OK: +- break; +- case RPMRC_NOTFOUND: +- vd->msg = xstrdup((sinfo->type == RPMSIG_SIGNATURE_TYPE) ? +- _("no signature") : _("no digest")); +- break; +- case RPMRC_NOKEY: +- /* +- * Legacy compat: if signatures are not required, install must +- * succeed despite missing key. +- */ +- if (!(vd->vfylevel & RPMSIG_SIGNATURE_TYPE)) +- sinfo->rc = RPMRC_OK; +- /* fallthrough */ +- default: +- if (sinfo->rc) +- vd->msg = rpmsinfoMsg(sinfo); +- break; ++ switch (sinfo->rc) { ++ case RPMRC_OK: ++ break; ++ case RPMRC_NOTFOUND: ++ free(vd->msg); ++ vd->msg = xstrdup((sinfo->type == RPMSIG_SIGNATURE_TYPE) ? ++ _("no signature") : _("no digest")); ++ break; ++ case RPMRC_NOKEY: ++ /* ++ * Legacy compat: if signatures are not required, install must ++ * succeed despite missing key. ++ */ ++ if (!(vd->vfylevel & RPMSIG_SIGNATURE_TYPE)) ++ sinfo->rc = RPMRC_OK; ++ /* fallthrough */ ++ default: ++ if (sinfo->rc) { ++ free(vd->msg); ++ vd->msg = rpmsinfoMsg(sinfo); ++ } ++ break; ++ } ++ vd->type[sinfo->type] = sinfo->rc; + } +- return (sinfo->rc == 0); ++ return 1; + } + + static ARGI_t initPkgDigests(FD_t fd) +@@ -1324,7 +1337,7 @@ static int verifyPackage(rpmts ts, rpmte p, struct rpmvs_s *vs, int vfylevel) + } + + if (prc == RPMRC_OK) +- prc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd); ++ prc = rpmvsVerify(vs, vfylevel, vfyCb, &vd); + + /* Record verify result */ + if (vd.type[RPMSIG_SIGNATURE_TYPE] == RPMRC_OK) +-- +2.52.0 + + +From d198f3061254f5fa663595ef36bd79233c042ec9 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 6 Nov 2025 16:47:58 +0200 +Subject: [PATCH 03/11] Don't assume all digests we look for can be found + during signing + +This has worked more or less accidentally up to now, but once verify +algorithms are sorted, its more likely to happen. + +(cherry picked from commit 04799ffc5f76c010eba4ee9df243512ac3f6561a) +--- + sign/rpmgensig.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c +index 33c9510e0..6f6264ffa 100644 +--- a/sign/rpmgensig.c ++++ b/sign/rpmgensig.c +@@ -619,9 +619,9 @@ static rpmRC includeVeritySignatures(FD_t fd, Header *sigp, Header *hdrp) + static int msgCb(struct rpmsinfo_s *sinfo, void *cbdata) + { + char **msg = cbdata; +- if (sinfo->rc && *msg == NULL) ++ if (sinfo->rc && sinfo->rc != RPMRC_NOTFOUND && *msg == NULL) + *msg = rpmsinfoMsg(sinfo); +- return (sinfo->rc != RPMRC_FAIL); ++ return 1; + } + + /* Require valid digests on entire package for signing. */ +-- +2.52.0 + + +From c15ca8b275ba2474a295cb813f237f3fc9257cc8 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 6 Nov 2025 16:33:00 +0200 +Subject: [PATCH 04/11] Fix a typo/thinko in verify element sorting per + algorithms + +Commit 48eb5abb6f069d65c75e5df8673194bfdb8be926 contained a stupid +typo/thinko causing signature and hash algorithms to be compared to +itself. The fix is as obvious as the mistake is silly, but it had been +masking bigger issues in the verification, now dragged to daylight +with the multiple signature verification semantics. Now that the logic +is fixed in a594a12339e61057c15556ee71c44a5231fac9be we can do the +obvious change finally. + +There are lot of changes but the only thing changing is the output +order, with newest algorithms first (newest in the order they have been +added to the OpenPGP standard) + +This also points out another issue: rpm v6 signatures get sorted last +which is wrong, but that's a separate issue in that it's because the +sigalgo value is not populated for them in the first place. That'll +be dealt with separately. + +Fixes: #1057 + +Backported from commit 35099525e2d719f49435f790ce7bcabbd8a8cae4 +--- + lib/rpmvs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index 667a2074f..06aa73b7e 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -477,9 +477,9 @@ static int sinfoCmp(const void *a, const void *b) + rc = sb->type - sa->type; + /* strongest (in the "newer is better" sense) algos first */ + if (rc == 0) +- rc = sb->sigalgo - sb->sigalgo; ++ rc = sb->sigalgo - sa->sigalgo; + if (rc == 0) +- rc = sb->hashalgo - sb->hashalgo; ++ rc = sb->hashalgo - sa->hashalgo; + /* last resort, these only makes sense from consistency POV */ + if (rc == 0) + rc = sb->id - sa->id; +-- +2.52.0 + + +From dd85f3e774188b3c69a18bffc67777d2f6f7da1e Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 20 Nov 2025 14:09:12 +0200 +Subject: [PATCH 05/11] Verify all types in transaction verify again + +Commit a594a12339e61057c15556ee71c44a5231fac9be changed the transaction +verify to only verify the enforced types, but that's subtly wrong: we +should verify everything that is not explicitly disabled. The difference +to the enforcing level is that when enforcing, there must be one +positive success whereas otherwise lack of failure suffices. + +Test for this specifically: in the existing test-case we *should* get +the failure on a bad digest from the malformed payload, although that's +not being enforced. Add a second test with --nodigest to check for the +enforcing signature mode specifically. + +(cherry picked from commit dad07208a14b76b6133bd9798b57c4b0e8c6c953) +--- + lib/transaction.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/transaction.c b/lib/transaction.c +index a3c95c3d7..e1e93db70 100644 +--- a/lib/transaction.c ++++ b/lib/transaction.c +@@ -1337,7 +1337,7 @@ static int verifyPackage(rpmts ts, rpmte p, struct rpmvs_s *vs, int vfylevel) + } + + if (prc == RPMRC_OK) +- prc = rpmvsVerify(vs, vfylevel, vfyCb, &vd); ++ prc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd); + + /* Record verify result */ + if (vd.type[RPMSIG_SIGNATURE_TYPE] == RPMRC_OK) +-- +2.52.0 + + +From b0f76bce63efb5906610364cd761f5645d6026de Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 11 Dec 2025 15:17:28 +0200 +Subject: [PATCH 06/11] Fix bogus verify output in some order dependent cases + +The "bad" tracking in the rpmkeys -K callback has no chance of working +correctly with multiple items where some might be disabled or missing. +Let rpmvsVerify() handle the calculation, and return the failed types +through its return code. + +Make the rpmvsVerify() stuff more explicit as well: in enforcing modes, +we always require the full package range to be covered, and mixing +enforcing mode with RPMVSF_NEEDPAYLOAD needs to fail because it cannot +then cover the whole package. And then base the return code on the +coverage explicitly. + +Add some commentary to this spaghetti while at it. + +(cherry-picked from commit 9a68128a64826456f0e26c975fb221b263c2d83e) +--- + lib/rpmchecksig.c | 8 ++------ + lib/rpmvs.c | 23 +++++++++++------------ + lib/rpmvs.h | 20 ++++++++++++++++++++ + 3 files changed, 33 insertions(+), 18 deletions(-) + +diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c +index 3a3a4bd59..7a3c4b22b 100644 +--- a/lib/rpmchecksig.c ++++ b/lib/rpmchecksig.c +@@ -120,7 +120,6 @@ static int readFile(FD_t fd, char **msg) + + struct vfydata_s { + int seen; +- int bad; + int verbose; + }; + +@@ -128,8 +127,6 @@ static int vfyCb(struct rpmsinfo_s *sinfo, void *cbdata) + { + struct vfydata_s *vd = cbdata; + vd->seen |= sinfo->type; +- if (sinfo->rc != RPMRC_OK) +- vd->bad |= sinfo->type; + if (vd->verbose) { + char *vsmsg = rpmsinfoMsg(sinfo); + rpmlog(RPMLOG_NOTICE, " %s\n", vsmsg); +@@ -212,7 +209,6 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, + { + char *msg = NULL; + struct vfydata_s vd = { .seen = 0, +- .bad = 0, + .verbose = rpmIsVerbose(), + }; + int rc; +@@ -229,11 +225,11 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, + + if (!vd.verbose) { + if (vd.seen & RPMSIG_DIGEST_TYPE) { +- rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_DIGEST_TYPE) ? ++ rpmlog(RPMLOG_NOTICE, " %s", (rc & RPMSIG_DIGEST_TYPE) ? + _("DIGESTS") : _("digests")); + } + if (vd.seen & RPMSIG_SIGNATURE_TYPE) { +- rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_SIGNATURE_TYPE) ? ++ rpmlog(RPMLOG_NOTICE, " %s", (rc & RPMSIG_SIGNATURE_TYPE) ? + _("SIGNATURES") : _("signatures")); + } + rpmlog(RPMLOG_NOTICE, " %s\n", rc ? _("NOT OK") : _("OK")); +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index 06aa73b7e..b0d2a784b 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -502,10 +502,10 @@ static const struct rpmsinfo_s *getAlt(const struct rpmvs_s *vs, const struct rp + int rpmvsVerify(struct rpmvs_s *sis, int type, + rpmsinfoCb cb, void *cbdata) + { +- int success = 0; + int failed = 0; + int cont = 1; +- int range = 0, vfylevel = sis->vfylevel; ++ int vfylevel = sis->vfylevel; ++ int range = vfylevel ? (RPMSIG_HEADER|RPMSIG_PAYLOAD) : 0; + int verified[3] = { 0, 0, 0 }; + + /* sort for consistency and rough "better comes first" semantics*/ +@@ -536,10 +536,6 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, + if (verified[RPMSIG_SIGNATURE_TYPE]) + vfylevel |= RPMSIG_SIGNATURE_TYPE; + +- /* Cannot verify payload if RPMVSF_NEEDPAYLOAD is set */ +- if (sis->vsflags & RPMVSF_NEEDPAYLOAD) +- range &= ~RPMSIG_PAYLOAD; +- + for (int i = 0; i < sis->nsigs && cont; i++) { + struct rpmsinfo_s *sinfo = &sis->sigs[i]; + int strength = (sinfo->type | sinfo->strength); +@@ -568,22 +564,25 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, + cont = cb(sinfo, cbdata); + + switch (sinfo->rc) { +- case RPMRC_OK: +- success++; +- break; + case RPMRC_FAIL: + case RPMRC_NOKEY: +- case RPMRC_NOTFOUND: +- failed++; ++ failed |= sinfo->type; + break; ++ case RPMRC_OK: + case RPMRC_NOTTRUSTED: ++ case RPMRC_NOTFOUND: + default: + /* ignore */ + break; + }; + } + +- return (success >= 1 && failed == 0) ? 0 : failed; ++ if ((vfylevel & RPMSIG_DIGEST_TYPE) && (verified[RPMSIG_DIGEST_TYPE] != range)) ++ failed |= RPMSIG_DIGEST_TYPE; ++ if ((vfylevel & RPMSIG_SIGNATURE_TYPE) && (verified[RPMSIG_SIGNATURE_TYPE] != range)) ++ failed |= RPMSIG_SIGNATURE_TYPE; ++ ++ return failed; + } + + static const char * rpmSigString(rpmRC res) +diff --git a/lib/rpmvs.h b/lib/rpmvs.h +index 4085db952..250d59ceb 100644 +--- a/lib/rpmvs.h ++++ b/lib/rpmvs.h +@@ -69,6 +69,26 @@ void rpmvsFiniRange(struct rpmvs_s *sis, int range); + + int rpmvsRange(struct rpmvs_s *vs); + ++/* ++ * This is the main rpm package integrity verification machinery, and ++ * a peculiar beast at that because of all the legacy compatibility modes ++ * it needs to support in addition to the more modern enforcing modes. ++ * ++ * All verifiables (signatures, digests) indicated in the type bitmask are ++ * verified, a negative result causes a failure of that type in all modes. ++ * ++ * Return a bitmask of the failed verifiable types, or zero on success. ++ * Success semantics depend on the verification mode specified at rpmvsCreate() ++ * time: ++ * - In "none" verifylevel (rpm < 4.14 compatibility mode), there are no ++ * additional constraints. Notably rpmReadPackageFile() always uses this. ++ * - In "digest", "signature" and "all" modes, there must be no failures and ++ * a at least one positive result of each enabled verifiable type, ++ * governing the entire package (header + payload). ++ * ++ * To make matters worse, callbacks (need to) modify some results to ++ * get the desired behavior in some cases. ++ */ + int rpmvsVerify(struct rpmvs_s *sis, int type, + rpmsinfoCb cb, void *cbdata); + +-- +2.52.0 + + +From df310fa8cd8718d133f0ef2aec4aab87f3819604 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 20 Nov 2025 16:19:50 +0200 +Subject: [PATCH 07/11] Drop NOTFOUNDs output for items that are disabled in + rpm config + +RPM 6.0 disabled header+payload MD5 and header SHA1 digests in the +default configuration, so we don't look for these things even if they +are there. Emitting NOTFOUND for what you are not looking for is misleading, +don't do that. + +Skip digests and signatures disabled in rpm configuration from the +verification. This builds on top of the previous commit and does not +work without it. + +NOTE: Two tests now output "(null)" instead of "no digest", which is +obviously wrong. Upstream does not exhibit this behavior in the +configuration but the issue exists there too. Fixing the output +in a separate patch to keep commits and their order close to upstream. + +Fixes: #3303 + +Backported from 11dc680bdc43f65fedbfb71edb2315b86075a1d4 +--- + lib/rpmvs.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index b0d2a784b..88a29c97e 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -342,6 +342,9 @@ static void rpmvsAppend(struct rpmvs_s *sis, hdrblob blob, + if (!(vi->vi.type & RPMSIG_VERIFIABLE_TYPE)) + return; + ++ if (rpmsinfoDisabled(&vi->vi, sis->vsflags)) ++ return; ++ + const char *o = (blob->il > blob->ril) ? _("header") : _("package"); + struct rpmtd_s td; + rpmRC rc = hdrblobGet(blob, vi->tag, &td); +@@ -349,7 +352,7 @@ static void rpmvsAppend(struct rpmvs_s *sis, hdrblob blob, + + rpmvsReserve(sis, nitems); + +- if (!rpmsinfoDisabled(&vi->vi, sis->vsflags) && rc == RPMRC_OK) { ++ if (rc == RPMRC_OK) { + while (rpmtdNext(&td) >= 0) { + if (!rpmsinfoInit(vi, ti, &td, o, &sis->sigs[sis->nsigs])) { + /* Don't bother with v3/v4 sigs when v6 sigs exist */ +@@ -509,7 +512,8 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, + int verified[3] = { 0, 0, 0 }; + + /* sort for consistency and rough "better comes first" semantics*/ +- qsort(sis->sigs, sis->nsigs, sizeof(*sis->sigs), sinfoCmp); ++ if (sis->sigs) ++ qsort(sis->sigs, sis->nsigs, sizeof(*sis->sigs), sinfoCmp); + + for (int i = 0; i < sis->nsigs && cont; i++) { + struct rpmsinfo_s *sinfo = &sis->sigs[i]; +-- +2.52.0 + + +From 0ec9d523399e42056b61a4785bcf54b56b028dc7 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 18 Nov 2025 10:58:49 +0200 +Subject: [PATCH 08/11] Introduce yet another variant of rpmKeyringVerifySig() + for returning lints + +The keyring verify interface looks at one signature per call, and cannot +know what is an error or warning in the bigger picture when multiple +signatures and policies over them are involved, that decision must be left +for the caller. And so we need to return any lints from the low-level +crypto implementation instead of logging them here. + +Backported from 8da92f9cfba7178e0bbcecfdcaebd7ec25db06e6, but this is +really just a rough estimate of that interface because we lack a years +worth of other improvements in this area. +--- + include/rpm/rpmkeyring.h | 13 +++++++++++++ + rpmio/rpmkeyring.c | 29 +++++++++++++++++++++++------ + 2 files changed, 36 insertions(+), 6 deletions(-) + +diff --git a/include/rpm/rpmkeyring.h b/include/rpm/rpmkeyring.h +index 3d8d55773..6e92bdd94 100644 +--- a/include/rpm/rpmkeyring.h ++++ b/include/rpm/rpmkeyring.h +@@ -7,6 +7,7 @@ + * RPM keyring API + */ + ++#include + #include + #include + +@@ -43,6 +44,18 @@ int rpmKeyringAddKey(rpmKeyring keyring, rpmPubkey key); + */ + rpmRC rpmKeyringVerifySig(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx); + ++/** \ingroup rpmkeyring ++ * Perform combined keyring lookup and signature verification ++ * @param keyring keyring handle ++ * @param sig OpenPGP signature parameters ++ * @param ctx signature hash context ++ * @param keyptr matching key (weak reference, do not free) or NULL ++ * @param lintsptr lints (if any) ++ * @return RPMRC_OK / RPMRC_FAIL / RPMRC_NOKEY ++ */ ++rpmRC rpmKeyringVerifySig3(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx, ++ rpmPubkey * keyptr, ARGV_t *lintsptr); ++ + /** \ingroup rpmkeyring + * Reference a keyring. + * @param keyring keyring handle +diff --git a/rpmio/rpmkeyring.c b/rpmio/rpmkeyring.c +index e3eb9e6ea..36c0ca2e2 100644 +--- a/rpmio/rpmkeyring.c ++++ b/rpmio/rpmkeyring.c +@@ -261,16 +261,18 @@ static rpmPubkey findbySig(rpmKeyring keyring, pgpDigParams sig) + return key; + } + +-rpmRC rpmKeyringVerifySig(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx) ++rpmRC rpmKeyringVerifySig3(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx, ++ rpmPubkey * keyptr, ARGV_t *lintsptr) + { + rpmRC rc = RPMRC_FAIL; ++ rpmPubkey key = NULL; + + if (keyring) + pthread_rwlock_rdlock(&keyring->lock); + + if (sig && ctx) { ++ key = findbySig(keyring, sig); + pgpDigParams pgpkey = NULL; +- rpmPubkey key = findbySig(keyring, sig); + + if (key) + pgpkey = key->pgpkey; +@@ -278,14 +280,29 @@ rpmRC rpmKeyringVerifySig(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx) + /* We call verify even if key not found for a signature sanity check */ + char *lints = NULL; + rc = pgpVerifySignature2(pgpkey, sig, ctx, &lints); +- if (lints) { +- rpmlog(rc ? RPMLOG_ERR : RPMLOG_WARNING, "%s\n", lints); +- free(lints); +- } ++ if (lints && lintsptr) ++ argvAdd(lintsptr, lints); ++ free(lints); + } + ++ if (keyptr) ++ *keyptr = key; ++ + if (keyring) + pthread_rwlock_unlock(&keyring->lock); + + return rc; + } ++ ++rpmRC rpmKeyringVerifySig(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx) ++{ ++ ARGV_t lints = NULL; ++ rpmRC rc = rpmKeyringVerifySig3(keyring, sig, ctx, NULL, &lints); ++ if (lints) { ++ for (char **l = lints; l && *l; l++) ++ rpmlog(rc ? RPMLOG_ERR : RPMLOG_WARNING, "%s\n", *l); ++ argvFree(lints); ++ } ++ return rc; ++} ++ +-- +2.52.0 + + +From b613fbf95c70c64afd3989f542c79f2616ddbe11 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Wed, 26 Nov 2025 13:44:19 +0200 +Subject: [PATCH 09/11] Move signature lints output to post-verification where + we know the result + +The callbacks cannot possibly know the final result in the face of +multiple signatures, some possibly disabled on the system level. It +gets rather verbose if there are multiple signatures of which some are +disabled in the system configuration, while possibly returning "OK". + +We need to do a second round once we know the final result to know +whether we should emit lints at all, and with that we can now +drop the stderr [ignore]'s from the multisignature tests. + +Fixes: #4036 + +Backported from commit 349bb010d26cb893ba6c22535fd6a73e96b2430d +This has test-changes that aren't present in the upstream commit because +we didn't painfully backport the 5db51df43431b0b3d0ceb4351c673fa4559ed8fe +test refactor, and in this original version with combined stdout/stderr, +the output does differ somewhat. +--- + lib/rpmchecksig.c | 17 ++++++++++++++++- + lib/rpmvs.c | 17 ++++++++++++++--- + lib/rpmvs.h | 3 +++ + 3 files changed, 33 insertions(+), 4 deletions(-) + +diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c +index 7a3c4b22b..ff6295838 100644 +--- a/lib/rpmchecksig.c ++++ b/lib/rpmchecksig.c +@@ -121,6 +121,7 @@ static int readFile(FD_t fd, char **msg) + struct vfydata_s { + int seen; + int verbose; ++ int rc; + }; + + static int vfyCb(struct rpmsinfo_s *sinfo, void *cbdata) +@@ -135,6 +136,17 @@ static int vfyCb(struct rpmsinfo_s *sinfo, void *cbdata) + return 1; + } + ++static int lintCb(struct rpmsinfo_s *sinfo, void *cbdata) ++{ ++ struct vfydata_s *vd = (struct vfydata_s *)cbdata; ++ if (vd->rc && sinfo->lints) { ++ char *msg = argvJoin(sinfo->lints, "\n"); ++ rpmlog(RPMLOG_ERR, "%s\n", msg); ++ free(msg); ++ } ++ return 1; ++} ++ + rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, + hdrblob *sigblobp, hdrblob *blobp, char **emsg) + { +@@ -210,6 +222,7 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, + char *msg = NULL; + struct vfydata_s vd = { .seen = 0, + .verbose = rpmIsVerbose(), ++ .rc = 0, + }; + int rc; + struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); +@@ -221,7 +234,9 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, + if (rc) + goto exit; + +- rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd); ++ rc = vd.rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd); ++ ++ rpmvsForeach(vs, lintCb, &vd); + + if (!vd.verbose) { + if (vd.seen & RPMSIG_DIGEST_TYPE) { +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index 88a29c97e..763481386 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -265,6 +265,7 @@ static void rpmsinfoFini(struct rpmsinfo_s *sinfo) + rpmDigestFinal(sinfo->ctx, NULL, NULL, 0); + free(sinfo->msg); + free(sinfo->descr); ++ argvFree(sinfo->lints); + memset(sinfo, 0, sizeof(*sinfo)); + } + } +@@ -589,6 +590,15 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, + return failed; + } + ++void rpmvsForeach(struct rpmvs_s *sis, rpmsinfoCb cb, void *cbdata) ++{ ++ int cont = 1; ++ for (int i = 0; i < sis->nsigs && cont; i++) { ++ struct rpmsinfo_s *sinfo = &sis->sigs[i]; ++ cont = cb(sinfo, cbdata); ++ } ++} ++ + static const char * rpmSigString(rpmRC res) + { + const char * str; +@@ -644,9 +654,10 @@ static rpmRC + verifySignature(rpmKeyring keyring, struct rpmsinfo_s *sinfo) + { + rpmRC res = RPMRC_FAIL; +- if (pgpSignatureType(sinfo->sig) == PGPSIGTYPE_BINARY) +- res = rpmKeyringVerifySig(keyring, sinfo->sig, sinfo->ctx); +- ++ if (pgpSignatureType(sinfo->sig) == PGPSIGTYPE_BINARY) { ++ res = rpmKeyringVerifySig3(keyring, sinfo->sig, sinfo->ctx, ++ NULL, &sinfo->lints); ++ } + return res; + } + +diff --git a/lib/rpmvs.h b/lib/rpmvs.h +index 250d59ceb..7a6acb2ca 100644 +--- a/lib/rpmvs.h ++++ b/lib/rpmvs.h +@@ -33,6 +33,7 @@ struct rpmsinfo_s { + /* verify results */ + rpmRC rc; + char *msg; ++ ARGV_t lints; + }; + + /** +@@ -92,6 +93,8 @@ int rpmvsRange(struct rpmvs_s *vs); + int rpmvsVerify(struct rpmvs_s *sis, int type, + rpmsinfoCb cb, void *cbdata); + ++void rpmvsForeach(struct rpmvs_s *sis, rpmsinfoCb cb, void *cbdata); ++ + rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, + hdrblob *sigblobp, hdrblob *blobp, char **emsg); + +-- +2.52.0 + + +From 5cd5c9a0c37c11e857b5b8a224b4f7fa5ed0db16 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Wed, 10 Dec 2025 13:16:15 +0200 +Subject: [PATCH 10/11] Fix transaction verification output as well + +Similarly to the previous commit, the callbacks have no chance of getting +the final result code right in the face of multiple signatures, some of +which may be disabled on the system level and should be ignored. + +Split the callback output from the logic bits to a separate stage, +called after getting the final results from rpmvsVerify(). The callbacks +still have way too much special logic but that's for another rainy day +to sort out. + +Related: #4036 + +Backported from commit 294b68b872de851153fc882eee9d2970093dff4e +--- + lib/package.c | 55 ++++++++++++++++++++++++++--------------------- + lib/rpmvs.h | 2 ++ + lib/transaction.c | 2 +- + 3 files changed, 33 insertions(+), 26 deletions(-) + +diff --git a/lib/package.c b/lib/package.c +index 000f2fcdd..0763ae691 100644 +--- a/lib/package.c ++++ b/lib/package.c +@@ -25,7 +25,6 @@ typedef struct pkgdata_s *pkgdatap; + typedef void (*hdrvsmsg)(struct rpmsinfo_s *sinfo, pkgdatap pkgdata, const char *msg); + + struct pkgdata_s { +- hdrvsmsg msgfunc; + const char *fn; + char *msg; + rpmRC rc; +@@ -158,28 +157,23 @@ static int handleHdrVS(struct rpmsinfo_s *sinfo, void *cbdata) + { + struct pkgdata_s *pkgdata = cbdata; + +- if (pkgdata->msgfunc) { +- char *vsmsg = rpmsinfoMsg(sinfo); +- pkgdata->msgfunc(sinfo, pkgdata, vsmsg); +- free(vsmsg); +- } +- + /* Remember actual return code, but don't override a previous failure */ +- if (sinfo->rc && pkgdata->rc != RPMRC_FAIL) ++ if (sortRC(sinfo->rc) > sortRC(pkgdata->rc)) + pkgdata->rc = sinfo->rc; + +- /* Preserve traditional behavior for now: only failure prevents read */ +- if (sinfo->rc != RPMRC_FAIL) +- sinfo->rc = RPMRC_OK; +- + return 1; + } + + +-static void appendhdrmsg(struct rpmsinfo_s *sinfo, struct pkgdata_s *pkgdata, +- const char *msg) ++static int appendhdrmsg(struct rpmsinfo_s *sinfo, void *cbdata) + { +- pkgdata->msg = rstrscat(&pkgdata->msg, "\n", msg, NULL); ++ struct pkgdata_s *pkgdata = (struct pkgdata_s *)cbdata; ++ if (sinfo->rc != RPMRC_NOTFOUND) { ++ char *msg = rpmsinfoMsg(sinfo); ++ pkgdata->msg = rstrscat(&pkgdata->msg, "\n", msg, NULL); ++ free(msg); ++ } ++ return 1; + } + + rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg) +@@ -189,7 +183,6 @@ rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg) + rpmKeyring keyring = rpmtsGetKeyring(ts, 1); + struct hdrblob_s blob; + struct pkgdata_s pkgdata = { +- .msgfunc = appendhdrmsg, + .fn = NULL, + .msg = NULL, + .rc = RPMRC_OK, +@@ -207,6 +200,7 @@ rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg) + rpmvsFiniRange(vs, RPMSIG_HEADER); + + rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, handleHdrVS, &pkgdata); ++ rpmvsForeach(vs, appendhdrmsg, &pkgdata); + + rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), uc); + +@@ -306,29 +300,37 @@ void applyRetrofits(Header h) + } + } + +-static void loghdrmsg(struct rpmsinfo_s *sinfo, struct pkgdata_s *pkgdata, +- const char *msg) ++static int loghdrmsg(struct rpmsinfo_s *sinfo, void *cbdata) + { ++ const struct pkgdata_s *pkgdata = (const struct pkgdata_s *)cbdata; + int lvl = RPMLOG_DEBUG; ++ int log = 1; ++ + switch (sinfo->rc) { +- case RPMRC_OK: /* Signature is OK. */ ++ case RPMRC_NOTFOUND: /* Signature/digest not present. */ ++ log = 0; + break; + case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */ ++ case RPMRC_OK: /* Signature is OK. */ ++ break; + case RPMRC_NOKEY: /* Public key is unavailable. */ + /* XXX Print NOKEY/NOTTRUSTED warning only once. */ + if (stashKeyid(sinfo->keyid) == 0) + lvl = RPMLOG_WARNING; + break; +- case RPMRC_NOTFOUND: /* Signature/digest not present. */ +- lvl = RPMLOG_WARNING; +- break; + default: + case RPMRC_FAIL: /* Signature does not verify. */ + lvl = RPMLOG_ERR; + break; + } + +- rpmlog(lvl, "%s: %s\n", pkgdata->fn, msg); ++ if (log) { ++ char *msg = rpmsinfoMsg(sinfo); ++ rpmlog(lvl, "%s: %s\n", pkgdata->fn, msg); ++ free(msg); ++ } ++ ++ return 1; + } + + rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) +@@ -342,7 +344,6 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) + rpmKeyring keyring = rpmtsGetKeyring(ts, 1); + struct rpmvs_s *vs = rpmvsCreate(0, vsflags, keyring); + struct pkgdata_s pkgdata = { +- .msgfunc = loghdrmsg, + .fn = fn ? fn : Fdescr(fd), + .msg = NULL, + .rc = RPMRC_OK, +@@ -358,7 +359,11 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) + + /* Actually all verify discovered signatures and digests */ + rc = RPMRC_FAIL; +- if (!rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, handleHdrVS, &pkgdata)) { ++ rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, handleHdrVS, &pkgdata); ++ rpmvsForeach(vs, loghdrmsg, &pkgdata); ++ ++ /* Preserve traditional behavior for now: only failure prevents read */ ++ if (pkgdata.rc != RPMRC_FAIL) { + /* Finally import the headers and do whatever required retrofits etc */ + if (hdrp) { + if (hdrblobImport(sigblob, 0, &sigh, &msg)) +diff --git a/lib/rpmvs.h b/lib/rpmvs.h +index 7a6acb2ca..e8c6f03e2 100644 +--- a/lib/rpmvs.h ++++ b/lib/rpmvs.h +@@ -98,6 +98,8 @@ void rpmvsForeach(struct rpmvs_s *sis, rpmsinfoCb cb, void *cbdata); + rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, + hdrblob *sigblobp, hdrblob *blobp, char **emsg); + ++RPM_GNUC_INTERNAL ++int sortRC(int rc); + #ifdef __cplusplus + } + #endif +diff --git a/lib/transaction.c b/lib/transaction.c +index e1e93db70..069260f73 100644 +--- a/lib/transaction.c ++++ b/lib/transaction.c +@@ -1232,7 +1232,7 @@ struct vfydata_s { + int vfylevel; + }; + +-static int sortRC(int rc) ++int sortRC(int rc) + { + switch (rc) { + case RPMRC_OK: return 0; +-- +2.52.0 + + +From 16cf620b9627c4fb47871929a49f60d3f47282e0 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Wed, 14 Jan 2026 11:57:46 +0200 +Subject: [PATCH 11/11] Fix "package X does not verify: (null)" output in some + configurations + +Commit 11dc680bdc43f65fedbfb71edb2315b86075a1d4 means that there are +configurations where the verify callback never encounters NOTFOUND items +so we can't rely on that to generate a message for the user. +Add an explicit check and a generic error message for this situation, +and a test that triggers the situation. + +Related: #3303 + +(cherry-picked from commit fb1252f5792f26203ee7533c0f180406c2898682) +--- + lib/transaction.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lib/transaction.c b/lib/transaction.c +index 069260f73..ecf6ee332 100644 +--- a/lib/transaction.c ++++ b/lib/transaction.c +@@ -1346,8 +1346,11 @@ static int verifyPackage(rpmts ts, rpmte p, struct rpmvs_s *vs, int vfylevel) + verified |= RPMSIG_DIGEST_TYPE; + rpmteSetVerified(p, verified); + +- if (prc) ++ if (prc) { ++ if (vd.msg == NULL) ++ vd.msg = xstrdup(_("no verifiable digest or signature available")); + rpmteAddProblem(p, RPMPROB_VERIFY, NULL, vd.msg, 0); ++ } + + vd.msg = _free(vd.msg); + headerFree(auxh); +-- +2.52.0 + +From 5e7a01fd8532bbbf14eae6c6c848080a0e5d27a9 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 9 Apr 2024 08:36:40 +0300 +Subject: [PATCH 1/3] Fix int/enum mismatch in rpmtsImportPubkey() return code + handling + +Actually simplifies the code too. + +(cherry picked from commit 0a28664671b6cc81bef1f866fc29b32537eff263) +--- + lib/rpmts.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/lib/rpmts.c b/lib/rpmts.c +index a282d9fc5..d5aede5ce 100644 +--- a/lib/rpmts.c ++++ b/lib/rpmts.c +@@ -618,9 +618,9 @@ rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen + if (txn == NULL) + return rc; + +- krc = pgpPubKeyLint(pkt, pktlen, &lints); ++ rc = pgpPubKeyLint(pkt, pktlen, &lints); + if (lints) { +- if (krc != RPMRC_OK) { ++ if (rc != RPMRC_OK) { + rpmlog(RPMLOG_ERR, "%s\n", lints); + } else { + /* XXX Hack to ease testing between different backends */ +@@ -629,8 +629,7 @@ rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen + } + free(lints); + } +- if (krc != RPMRC_OK) { +- rc = krc; ++ if (rc != RPMRC_OK) { + goto exit; + } + +-- +2.53.0 + + +From 5ab6e9401c03b7ead9175ced82ebf8f4069e4307 Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 7 May 2024 13:36:41 +0200 +Subject: [PATCH 2/3] Fix error handling in rpmtsImportPubkey + +The call to pgpPubKeyLint() modified the rc code, which the +following code assumed to be RPMRC_FAIL. + +Also, the return code of the database operation was always +overwritten with RPMRC_OK. + +(cherry picked from commit 00a3170dada2b7053088512c1d18c29801020460) +--- + lib/rpmts.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/lib/rpmts.c b/lib/rpmts.c +index d5aede5ce..f0698defe 100644 +--- a/lib/rpmts.c ++++ b/lib/rpmts.c +@@ -618,19 +618,18 @@ rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen + if (txn == NULL) + return rc; + +- rc = pgpPubKeyLint(pkt, pktlen, &lints); +- if (lints) { +- if (rc != RPMRC_OK) { ++ if (pgpPubKeyLint(pkt, pktlen, &lints) != RPMRC_OK) { ++ if (lints) { + rpmlog(RPMLOG_ERR, "%s\n", lints); +- } else { +- /* XXX Hack to ease testing between different backends */ +- if (rpmIsNormal()) +- rpmlog(RPMLOG_WARNING, "%s\n", lints); +- } +- free(lints); ++ free(lints); ++ } ++ goto exit; + } +- if (rc != RPMRC_OK) { +- goto exit; ++ if (lints) { ++ /* XXX Hack to ease testing between different backends */ ++ if (rpmIsNormal()) ++ rpmlog(RPMLOG_WARNING, "%s\n", lints); ++ free(lints); + } + + /* XXX keyring wont load if sigcheck disabled, force it temporarily */ +@@ -659,14 +658,16 @@ rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen + headerPutUint32(h, RPMTAG_INSTALLTID, &tid, 1); + + /* Add header to database. */ ++ rc = RPMRC_OK; + if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { + if (ts->keyringtype == KEYRING_FS) + rc = rpmtsImportFSKey(txn, h, 0); + else + rc = rpmtsImportHeader(txn, h, 0); + } ++ } else { ++ rc = RPMRC_OK; /* already have key */ + } +- rc = RPMRC_OK; + + exit: + /* Clean up. */ +-- +2.53.0 + + +From 80b7a28ac7db8514bab594bad70bb6418be4567b Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 29 Jan 2026 14:52:03 +0200 +Subject: [PATCH 3/3] Reflect pgpPubKeyLint() error code in + rpmtxnImportPubkey() return + +Current rpm-sequoia versions only return OK/FAIL from pgpPubKeyLint() +so it's not possible to devise a test to exhibit the change until +rpm-sequoia is updated. We can only observe that the behavior does NOT +change. + +Fixes: #4096 +(backported from commit 9296d05a34a25a5caa3f6a7202cf931f52ae6846) +--- + lib/rpmts.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lib/rpmts.c b/lib/rpmts.c +index f0698defe..2f293e751 100644 +--- a/lib/rpmts.c ++++ b/lib/rpmts.c +@@ -618,7 +618,8 @@ rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen + if (txn == NULL) + return rc; + +- if (pgpPubKeyLint(pkt, pktlen, &lints) != RPMRC_OK) { ++ rc = pgpPubKeyLint(pkt, pktlen, &lints); ++ if (rc != RPMRC_OK) { + if (lints) { + rpmlog(RPMLOG_ERR, "%s\n", lints); + free(lints); +@@ -632,6 +633,8 @@ rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen + free(lints); + } + ++ rc = RPMRC_FAIL; /* still assuming failure */ ++ + /* XXX keyring wont load if sigcheck disabled, force it temporarily */ + rpmtsSetVSFlags(ts, (oflags & ~RPMVSF_MASK_NOSIGNATURES)); + keyring = rpmtsGetKeyring(ts, 1); +-- +2.53.0 + diff --git a/rpm-4.19.x-nsswitch-enable.patch b/rpm-4.19.x-nsswitch-enable.patch new file mode 100644 index 0000000..bde5755 --- /dev/null +++ b/rpm-4.19.x-nsswitch-enable.patch @@ -0,0 +1,474 @@ +From 2645c3421e21e844108c4258044cd8fafe551b2f Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Fri, 28 Nov 2025 11:05:47 +0200 +Subject: [PATCH 1/3] Let the system runtime environment provide users and + groups + +Rpm would prefer users and groups always provided by packages, but +the real world is more complicated, and organizations may want to +package software utilizing centrally managed groups for access control. +To permit this, as the first step we need to let user() and group() +dependencies to be provided by the system runtime environment. + +Add a new system provides check to dependency resolution - we only +add user and group provides here but there are many other potential +areas in this direction. + +Add a new sub-package to the klang family to have something with both +a user and group dependency not provided by itself and adjust existing +test for the extra output, add tests for various rpm -U and -V scenarios +with system provided user/group. + +This is all "good old" C to minimize backporting effort, we'll need to +bring this to 4.x anyhow. + +Related: #3994 +(backported from commit 3617d160eb6a1a8a95689db5eb5648355ea60c2a) +--- + lib/depends.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +diff --git a/lib/depends.c b/lib/depends.c +index d336e14d7..bb903e5a0 100644 +--- a/lib/depends.c ++++ b/lib/depends.c +@@ -17,6 +17,7 @@ + #include "rpmds_internal.h" + #include "rpmfi_internal.h" /* rpmfiles stuff for now */ + #include "misc.h" ++#include "rpmug.h" + + #include "backend/dbiset.h" + +@@ -680,6 +681,48 @@ exit: + return set1 ? set1 : dbiIndexSetNew(0); + } + ++/* Check a string for foo(bar) style pattern, return value in parenthesis */ ++static int isDep(const char *depn, size_t dlen, const char *dtype, ++ char **depval) ++{ ++ size_t dtlen = strlen(dtype); ++ int rc = 0; ++ ++ if (rstreqn(depn, dtype, dtlen) && depn[dlen-1] == ')') { ++ size_t l = dlen - dtlen - 1; ++ if (depval) ++ *depval = rstrndup(depn + dtlen, l); ++ rc = 1; ++ } ++ ++ return rc; ++} ++ ++static int systemProvides(rpmts ts, rpmds dep) ++{ ++ int rc = 1; ++ const char *dtype = NULL; ++ const char *n = rpmdsN(dep); ++ size_t nlen = strlen(n); ++ char *dval = NULL; ++ ++ if (isDep(n, nlen, "user(", &dval)) { ++ uid_t uid = 0; ++ rc = rpmugUid(dval, &uid) < 0; ++ dtype = "(system user)"; ++ } else if (isDep(n, nlen, "group(", &dval)) { ++ gid_t gid = 0; ++ rc = rpmugGid(dval, &gid) < 0; ++ dtype = "(system group)"; ++ } ++ if (dtype) ++ rpmdsNotify(dep, dtype, rc); ++ ++ free(dval); ++ ++ return rc; ++} ++ + /** + * Check dep for an unsatisfied dependency. + * @param ts transaction set +@@ -714,6 +757,10 @@ retry: + goto unsatisfied; + } + ++ /* See if the runtime system provides it, similar to rpmlib provides */ ++ if (systemProvides(ts, dep) == 0) ++ goto exit; ++ + /* Dont look at pre-requisites of already installed packages */ + if (!adding && isTransientReq(dsflags)) + goto exit; +-- +2.52.0 + + +From 33edb47b3c3e644efb3ed69f4067be8fc315f50b Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Thu, 22 Jan 2026 12:07:11 +0100 +Subject: [PATCH 2/3] Honor alternate root in system user/group provides + +Commit 3617d160eb6a1a8a95689db5eb5648355ea60c2a missed the --root use +case, causing it to only ever look up users and groups on the host, +which is of course wrong. This is because rpmtsCheck() (where this +dependency check is done) happens well before we enter the target +chroot. + +Fix that by initializing the chroot in rpmtsCheck() and adapting rpmug +to take the target chroot into account when constructing the passwd and +group file paths. + +Don't enter the chroot in rpmtsCheck(), though, as that would introduce +the need to run test transactions as the root user and thus potentially +break existing use cases out there. We may revisit this in the future, +though, since technically the transaction check should be done inside +the target chroot. + +Note that this new rpmug logic, much like the existing one, is based on +the assumption that the rpmug cache is flushed across chroots. However, +this is currently the case only when setting a new chroot, not when +entering or leaving one, which will be fixed separately via #4093. + +Add a test to cover the --root use case with system provides, too. + +Fixes: #4094 +(backported from commit 6052d50603410d5f55f2ebdca3b88af52b32a880) +--- + lib/depends.c | 5 +++++ + lib/rpmchroot.c | 6 ++++++ + lib/rpmchroot.h | 7 +++++++ + lib/rpmug.c | 9 ++++++++- + 4 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/lib/depends.c b/lib/depends.c +index bb903e5a0..3503231dc 100644 +--- a/lib/depends.c ++++ b/lib/depends.c +@@ -17,6 +17,7 @@ + #include "rpmds_internal.h" + #include "rpmfi_internal.h" /* rpmfiles stuff for now */ + #include "misc.h" ++#include "rpmchroot.h" + #include "rpmug.h" + + #include "backend/dbiset.h" +@@ -1095,6 +1096,9 @@ int rpmtsCheck(rpmts ts) + if (!filedepHashNumKeys(reqnotfilehash)) + reqnotfilehash = filedepHashFree(reqnotfilehash); + ++ /* Enable system provides lookup from the target root */ ++ rpmChrootSet(rpmtsRootDir(ts)); ++ + /* + * Look at all of the added packages and make sure their dependencies + * are satisfied. +@@ -1177,6 +1181,7 @@ int rpmtsCheck(rpmts ts) + } + rpmtsiFree(pi); + ++ rpmChrootSet(NULL); + if (rdb) + rpmdbCtrl(rdb, RPMDB_CTRL_UNLOCK_RO); + +diff --git a/lib/rpmchroot.c b/lib/rpmchroot.c +index ebcece6c2..eab05a00d 100644 +--- a/lib/rpmchroot.c ++++ b/lib/rpmchroot.c +@@ -166,6 +166,12 @@ int rpmChrootOut(void) + return rc; + } + ++const char *rpmChrootPath(void) ++{ ++ const char *path = rootState.rootDir; ++ return (path && rstreq(path, "/")) ? NULL : path; ++} ++ + int rpmChrootDone(void) + { + return (rootState.chrootDone > 0); +diff --git a/lib/rpmchroot.h b/lib/rpmchroot.h +index ba7dea504..6c5f73d33 100644 +--- a/lib/rpmchroot.h ++++ b/lib/rpmchroot.h +@@ -16,6 +16,13 @@ extern "C" { + RPM_GNUC_INTERNAL + int rpmChrootSet(const char *rootDir); + ++/** \ingroup rpmchroot ++ * Return absolute path to current chroot directory. ++ * return chroot directory (or NULL if "/" or unset) ++ */ ++RPM_GNUC_INTERNAL ++const char *rpmChrootPath(void); ++ + /** \ingroup rpmchroot + * Enter chroot if necessary. + * return -1 on error, 0 on success. +diff --git a/lib/rpmug.c b/lib/rpmug.c +index 316e326f3..7ced4dea4 100644 +--- a/lib/rpmug.c ++++ b/lib/rpmug.c +@@ -6,6 +6,7 @@ + #include + + #include "misc.h" ++#include "rpmchroot.h" + #include "rpmug.h" + #include "debug.h" + +@@ -23,12 +24,18 @@ static __thread struct rpmug_s *rpmug = NULL; + static const char *getpath(const char *bn, const char *dfl, char **dest) + { + if (*dest == NULL) { ++ const char *root = rpmChrootPath(); + char *s = rpmExpand("%{_", bn, "_path}", NULL); + if (*s == '%' || *s == '\0') { + free(s); + s = xstrdup(dfl); + } +- *dest = s; ++ if (root && !rpmChrootDone()) { ++ *dest = rpmGetPath(root, s, NULL); ++ free(s); ++ } else { ++ *dest = s; ++ } + } + return *dest; + } +-- +2.52.0 + + +From ef6765b49260c8592f4b57e07a4c87bfc0f15806 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Tue, 27 Jan 2026 12:38:33 +0100 +Subject: [PATCH 3/3] Add back support for NSS based user/group lookups + +Commit f3eaeeb7341085e1850e914350cf1f33d538320d eliminated NSS lookup +completely but it perhaps went one step too far by also doing that for +non-chroot operations where NSS may be desired, such as in enterprise +environments with centralized user and group management and packages +that ship files owned by such network accounts. + +Fix that by partially reverting the above commit. Keep NSS disabled in +chroot operations and/or when the %_passwd_path or %_group_path macros +are set. The latter (macros) now also serves as a tunable to explicitly +disable NSS for users and/or groups even in non-chroot operations, and +preserves the existing behavior on systems where these macros have been +set, as that indicates the intent to use those specific paths. + +Make NSS lookups the default (again), by commenting out both macros in +the stock configuration. + +This also makes "rpm --root" consistent with "systemd-sysusers --root" +(as well as our own sysusers.sh script) which implements the same kind +of logic when checking for the presence of users/groups before creating +them. + +Commit 007b4c33a2a558fc1f062b8ceab0aeab41a36dac added a retry for the +get*nam() calls in case of an error but there doesn't seem to be any +obvious or documented reason for that (anymore), so don't revert that +part for the sake of simplicity, we can always add it back later. + +Enable the lookup test added in previous commits now that all the pieces +are in place. + +Fixes: RHEL-118365 +(backported from commit 4ce1359ebc50d305b41eec5d2f1a730f7d724e04) +--- + docs/man/rpm.8.md | 9 +++++++- + lib/rpmug.c | 56 ++++++++++++++++++++++++++++++++++++++--------- + macros.in | 5 +++-- + 3 files changed, 57 insertions(+), 13 deletions(-) + +diff --git a/docs/man/rpm.8.md b/docs/man/rpm.8.md +index c9c4473fd..e909a0a7a 100644 +--- a/docs/man/rpm.8.md ++++ b/docs/man/rpm.8.md +@@ -199,10 +199,17 @@ These options can be used in all the different modes. + installing, or **%prep** if building, a package) will be run after a + chroot(2) to *DIRECTORY*. + +- Note that rpm assumes the environment inside the root is set up by ++ Note that **rpm** assumes the environment inside the root is set up by + the caller, such as any mounts needed for the operation inside the + root directory. + ++ NSS (Name Service Switch) will *not* be used for user and group lookups in ++ package operations. Instead, **rpm** will do its own file-based lookups ++ using the **passwd**(5) and **group**(5) files in their standard locations, ++ or those configured with the **%\_passwd_path** and **%\_group_path** ++ macros, inside *DIRECTORY*. Note that, if *DIRECTORY* is */* (the forward ++ slash), NSS will be used as normal. ++ + **-D, \--define=\'***MACRO EXPR***\'** + + : Defines *MACRO* with value *EXPR*. +diff --git a/lib/rpmug.c b/lib/rpmug.c +index 7ced4dea4..895fb50bf 100644 +--- a/lib/rpmug.c ++++ b/lib/rpmug.c +@@ -1,5 +1,7 @@ + #include "system.h" + ++#include ++#include + #include + #include + #include +@@ -11,6 +13,7 @@ + #include "debug.h" + + struct rpmug_s { ++ // Empty path means use system lookup + char *pwpath; + char *grppath; + char *lastGname; +@@ -28,7 +31,8 @@ static const char *getpath(const char *bn, const char *dfl, char **dest) + char *s = rpmExpand("%{_", bn, "_path}", NULL); + if (*s == '%' || *s == '\0') { + free(s); +- s = xstrdup(dfl); ++ // Use system lookup unless chrooting ++ s = root ? xstrdup(dfl) : xstrdup(""); + } + if (root && !rpmChrootDone()) { + *dest = rpmGetPath(root, s, NULL); +@@ -37,7 +41,7 @@ static const char *getpath(const char *bn, const char *dfl, char **dest) + *dest = s; + } + } +- return *dest; ++ return **dest ? *dest : NULL; + } + + static const char *pwfile(void) +@@ -177,9 +181,17 @@ int rpmugUid(const char * thisUname, uid_t * uid) + rpmugInit(); + + if (rpmug->lastUname == NULL || !rstreq(thisUname, rpmug->lastUname)) { ++ const char *path = pwfile(); + long id; +- if (lookup_num(pwfile(), thisUname, 0, 2, &id)) +- return -1; ++ if (path) { ++ if (lookup_num(path, thisUname, 0, 2, &id)) ++ return -1; ++ } else { ++ struct passwd *pwent = getpwnam(thisUname); ++ if (pwent == NULL) ++ return -1; ++ id = pwent->pw_uid; ++ } + free(rpmug->lastUname); + rpmug->lastUname = xstrdup(thisUname); + rpmug->lastUid = id; +@@ -200,9 +212,17 @@ int rpmugGid(const char * thisGname, gid_t * gid) + rpmugInit(); + + if (rpmug->lastGname == NULL || !rstreq(thisGname, rpmug->lastGname)) { ++ const char *path = grpfile(); + long id; +- if (lookup_num(grpfile(), thisGname, 0, 2, &id)) +- return -1; ++ if (path) { ++ if (lookup_num(path, thisGname, 0, 2, &id)) ++ return -1; ++ } else { ++ struct group *grent = getgrnam(thisGname); ++ if (grent == NULL) ++ return -1; ++ id = grent->gr_gid; ++ } + free(rpmug->lastGname); + rpmug->lastGname = xstrdup(thisGname); + rpmug->lastGid = id; +@@ -221,10 +241,18 @@ const char * rpmugUname(uid_t uid) + rpmugInit(); + + if (uid != rpmug->lastUid) { ++ const char *path = pwfile(); + char *uname = NULL; + +- if (lookup_str(pwfile(), uid, 2, 0, &uname)) +- return NULL; ++ if (path) { ++ if (lookup_str(path, uid, 2, 0, &uname)) ++ return NULL; ++ } else { ++ struct passwd *pwent = getpwuid(uid); ++ if (pwent == NULL) ++ return NULL; ++ uname = pwent->pw_name; ++ } + + rpmug->lastUid = uid; + free(rpmug->lastUname); +@@ -241,10 +269,18 @@ const char * rpmugGname(gid_t gid) + rpmugInit(); + + if (gid != rpmug->lastGid) { ++ const char *path = grpfile(); + char *gname = NULL; + +- if (lookup_str(grpfile(), gid, 2, 0, &gname)) +- return NULL; ++ if (path) { ++ if (lookup_str(path, gid, 2, 0, &gname)) ++ return NULL; ++ } else { ++ struct group *grent = getgrgid(gid); ++ if (grent == NULL) ++ return NULL; ++ gname = grent->gr_name; ++ } + + rpmug->lastGid = gid; + free(rpmug->lastGname); +diff --git a/macros.in b/macros.in +index 5534f1ed7..ef413a358 100644 +--- a/macros.in ++++ b/macros.in +@@ -133,8 +133,9 @@ + %_keyringpath %{_dbpath}/pubkeys/ + + # Location of passwd(5) and group(5), as : separated list +-%_passwd_path /etc/passwd +-%_group_path /etc/group ++# Uncomment to disable NSS lookups ++#%_passwd_path /etc/passwd ++#%_group_path /etc/group + + # location of sysusers.d(5) directory + %_sysusersdir @sysusersdir@ +-- +2.52.0 + +diff -up rpm-4.19.1.1/docs/man/rpm.8.orig rpm-4.19.1.1/docs/man/rpm.8 +--- rpm-4.19.1.1/docs/man/rpm.8.orig 2026-01-28 13:18:58.025706793 +0100 ++++ rpm-4.19.1.1/docs/man/rpm.8 2026-01-28 13:18:49.367626076 +0100 +@@ -185,9 +185,18 @@ if installing, or \f[B]%prep\f[R] if bui + after a chroot(2) to \f[I]DIRECTORY\f[R]. + .RS + .PP +-Note that rpm assumes the environment inside the root is set up by the +-caller, such as any mounts needed for the operation inside the root +-directory. ++Note that \f[B]rpm\f[R] assumes the environment inside the root is set ++up by the caller, such as any mounts needed for the operation inside the ++root directory. ++.PP ++NSS (Name Service Switch) will \f[I]not\f[R] be used for user and group ++lookups in package operations. ++Instead, \f[B]rpm\f[R] will do its own file-based lookups using the ++\f[B]passwd\f[R](5) and \f[B]group\f[R](5) files in their standard ++locations, or those configured with the \f[B]%_passwd_path\f[R] and ++\f[B]%_group_path\f[R] macros, inside \f[I]DIRECTORY\f[R]. ++Note that, if \f[I]DIRECTORY\f[R] is \f[I]/\f[R] (the forward slash), ++NSS will be used as normal. + .RE + .TP + \f[B]-D, --define=\[aq]\f[R]\f[I]MACRO EXPR\f[R]\f[B]\[aq]\f[R] diff --git a/rpm.spec b/rpm.spec index 0244d52..b6583a2 100644 --- a/rpm.spec +++ b/rpm.spec @@ -27,7 +27,7 @@ %global rpmver 4.19.1.1 #global snapver rc1 -%global baserelease 20 +%global baserelease 23 %global sover 10 %global srcver %{rpmver}%{?snapver:-%{snapver}} @@ -169,6 +169,12 @@ rpm-4.19.x-multisig.patch rpm-4.19.x-pqc-algo.patch rpm-4.19.x-pqc-fixes.patch +0001-Really-allow-qualifiers-like-pre-post-meta-for-weak-.patch + +rpm-4.19.x-multisig-verify-fixes.patch +rpm-4.19.x-nsswitch-enable.patch +0001-Fix-empty-password-field-in-passwd-group-causing-ent.patch + # These are not yet upstream rpm-4.7.1-geode-i686.patch @@ -462,7 +468,7 @@ rm $RPM_BUILD_ROOT/%{rpmhome}/rpmdump %pre # Symlink all rpmdb files to the new location if we're still using /var/lib/rpm -if [ -d /var/lib/rpm ]; then +if [ ! -L /var/lib/rpm ] && [ -d /var/lib/rpm ]; then mkdir -p /usr/lib/sysimage/rpm rpmdb_files=$(find /var/lib/rpm -maxdepth 1 -type f | sed 's|^/var/lib/rpm/||g' | sort) for rpmdb_file in ${rpmdb_files[@]}; do @@ -477,7 +483,7 @@ if [ -x /usr/bin/systemctl ]; then fi %posttrans -if [ -d /var/lib/rpm ]; then +if [ ! -L /var/lib/rpm ] && [ -d /var/lib/rpm ]; then touch /var/lib/rpm/.migratedb fi if [ ! -d /var/lib/rpm ] && [ -d /usr/lib/sysimage/rpm ] && [ ! -f /usr/lib/sysimage/rpm/.rpmdbdirsymlink_created ]; then @@ -658,6 +664,18 @@ fi %doc %{_defaultdocdir}/rpm/API/ %changelog +* Thu Feb 05 2026 Michal Domonkos - 4.19.1.1-23 +- Fix key import API to return NOTTRUSTED for disabled algorithms (RHEL-112394) + +* Tue Jan 27 2026 Michal Domonkos - 4.19.1.1-22 +- Ignore signatures made by unknown or disabled algorithms (RHEL-112394) +- Enable NSS-based user and group lookups again (RHEL-118365) +- Fix ignored password field if empty in passwd/group file (RHEL-118365) + +* Thu Nov 27 2025 Michal Domonkos - 4.19.1.1-21 +- Fix pre/post/meta/etc. qualifiers for weak dependencies (RHEL-101936) +- Fix redundant rpmdb-migrate.service runs (RHEL-96510) + * Tue Aug 26 2025 Michal Domonkos - 4.19.1.1-20 - Fix rpmsign(8) man page (RHEL-109221)