summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-09-10 03:05:12 +0000
committerCoprDistGit <infra@openeuler.org>2023-09-10 03:05:12 +0000
commit2bc2b430bc4c1a9a0bfd1c01da68bd53bf7da052 (patch)
treea2af4fd609c7decacbf0ea11926ea338596fb179
parent0ae9f87336a3d78d8fbc0a1e5c75cba5f9cf8597 (diff)
automatic import of rpm
-rw-r--r--.gitignore1
-rw-r--r--0001-add-default-machine-name-to-support-loongarch.patch30
-rw-r--r--Add-digest-list-plugin.patch586
-rw-r--r--Add-license-to-digest_list.c.patch34
-rw-r--r--Add-loongarch-architecture-support.patch99
-rw-r--r--Avoid-generating-digest-lists-if-they-are-already-pa.patch50
-rw-r--r--Check-rpm-parser.patch29
-rw-r--r--Don-t-add-dist-to-release-if-it-is-already-there.patch26
-rw-r--r--Fix-digest_list_counter.patch81
-rw-r--r--Generate-digest-lists-before-calling-genCpioListAndH.patch255
-rw-r--r--Generate-digest-lists.patch323
-rw-r--r--Remove-digest-list-from-the-kernel-during-package-re.patch106
-rw-r--r--Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch38
-rw-r--r--add-dist-to-release-by-default.patch37
-rw-r--r--backport-Actually-return-an-error-in-parseScript-if-parsing-f.patch48
-rw-r--r--backport-Add-a-hashed-flag-to-pgpPrtSubtype.patch55
-rw-r--r--backport-Add-a-test-for-special-device-node-installation.patch79
-rw-r--r--backport-Add-optional-callback-on-directory-changes-during-rp.patch105
-rw-r--r--backport-Avoid-double-frees-if-EVP_PKEY_assign_RSA-fails.patch95
-rw-r--r--backport-Avoid-reading-out-of-bounds-of-the-i18ntable.patch29
-rw-r--r--backport-Avoid-unneded-MPI-reparsing.patch39
-rw-r--r--backport-Bury-rpmio-FD-use-to-fsmUnpack.patch129
-rw-r--r--backport-CVE-2021-35937-CVE-2021-35939.patch281
-rw-r--r--backport-CVE-2021-35938.patch40
-rw-r--r--backport-Check-file-iterator-for-being-NULL-consistently.patch67
-rw-r--r--backport-Check-inside-root-when-querying-for-files.patch38
-rw-r--r--backport-Check-that-the-CRC-length-is-correct.patch27
-rw-r--r--backport-Close-file-before-replacing-signed.patch27
-rw-r--r--backport-Consolidate-skipped-hardlink-with-content-case-with-.patch56
-rw-r--r--backport-Convert-the-file-creation-steps-the-at-family-of-cal.patch189
-rw-r--r--backport-Fix-BANames-leak-in-handlePreambleTag.patch26
-rw-r--r--backport-Fix-Header-leak-when-running-rpm2cpio.patch29
-rw-r--r--backport-Fix-OpenPGP-key-ID-parsing-regression.patch28
-rw-r--r--backport-Fix-__cplusplus-misspelled-as-_cplusplus.patch39
-rw-r--r--backport-Fix-a-copy-paste-help-description-of-whatconflicts-R.patch26
-rw-r--r--backport-Fix-a-memleak-in-ndb-from-opened-but-not-closed-dbis.patch26
-rw-r--r--backport-Fix-a-segfault-on-a-non-stringable-argument-to-macro.patch58
-rw-r--r--backport-Fix-changelog-parsing-affecting-caller-timezone-stat.patch30
-rw-r--r--backport-Fix-eiu-sourceURL-info-leak-in-rpmInstall.patch31
-rw-r--r--backport-Fix-elf-leak-in-getElfColor.patch28
-rw-r--r--backport-Fix-file-leak-when-src-rpm-in-URL-format-is-used-for.patch33
-rw-r--r--backport-Fix-fileleak-and-memleak-in-rpmInstall.patch63
-rw-r--r--backport-Fix-fileleak-when-urlGetFile-fails-in-rpmInstall.patch30
-rw-r--r--backport-Fix-h-blob-leak-when-installing-source-rpms.patch28
-rw-r--r--backport-Fix-hash-context-leak.patch34
-rw-r--r--backport-Fix-hashlen-overflow.patch46
-rw-r--r--backport-Fix-header-leak-in-rpmInstall.patch42
-rw-r--r--backport-Fix-install-of-block-and-character-special-files-219.patch110
-rw-r--r--backport-Fix-memleak-when-fsmRename-failed-in-fsmCommit.patch28
-rw-r--r--backport-Fix-memleak-when-running-generate_buildrequires.patch27
-rw-r--r--backport-Fix-memory-leak-in-pgpPrtParams-1.patch25
-rw-r--r--backport-Fix-memory-leak-in-pgpPrtParams.patch38
-rw-r--r--backport-Fix-old-Python-ts.check-argument-order-regression.patch32
-rw-r--r--backport-Fix-possible-NULL-pointer-dereference-in-rpmfcClassi.patch39
-rw-r--r--backport-Fix-possible-descriptor-leak-in-fsmOpenat.patch45
-rw-r--r--backport-Fix-possible-null-pointer-reference-in-ndb.patch28
-rw-r--r--backport-Fix-prog-leak-in-parseScript.patch35
-rw-r--r--backport-Fix-return-value-checks-in-OpenSSL-code.patch131
-rw-r--r--backport-Fix-rpm-lua-rpm_vercmp-error-message-if-second-argum.patch26
-rw-r--r--backport-Fix-rpmDigestBundleFinal-and-Update-return-code-on-i.patch40
-rw-r--r--backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch67
-rw-r--r--backport-Fix-sbp-leak-when-running-rpmbuild-with-quiet.patch28
-rw-r--r--backport-Fix-short-circuiting-of-version-strings-in-expressio.patch50
-rw-r--r--backport-Fix-some-Lua-stack-leaks-in-our-initialization-code.patch35
-rw-r--r--backport-Fix-use-after-free-in-haveSignature.patch33
-rw-r--r--backport-Ignore-subkeys-that-cannot-be-used-for-signing.patch104
-rw-r--r--backport-Make-pgpPubkeyFingerprint-do-something-meaningful-ag.patch64
-rw-r--r--backport-Make-rpmfiSetFX-return-code-meaningful.patch51
-rw-r--r--backport-Move-file-metadata-setting-back-to-unpack-stage.patch69
-rw-r--r--backport-Parse-key-usage-flags.patch78
-rw-r--r--backport-Prevent-NULL-deref-in-rpmfsGetStates.patch25
-rw-r--r--backport-Prevent-readelf-internet-access-during-rpaths-checki.patch32
-rw-r--r--backport-Process-MPI-s-from-all-kinds-of-signatures.patch57
-rw-r--r--backport-Refactor-pgpDigParams-construction-to-helper-functio.patch52
-rw-r--r--backport-Remove-obscure-check-for-package-build-time-from-reb.patch41
-rw-r--r--backport-Require-creation-time-to-be-unique-and-hashed.patch101
-rw-r--r--backport-Return-descriptor-of-created-file-from-fsmMkfile.patch65
-rw-r--r--backport-Revert-Explictly-skip-non-installed-files-on-erasur.patch32
-rw-r--r--backport-Simplify-rpm_print-fixing-a-Lua-stack-leak-as-a-bonu.patch39
-rw-r--r--backport-Skip-recorded-symlinks-in-setperms-RhBug-1900662.patch40
-rw-r--r--backport-Switch-the-floating-point-type-in-rpmhook-from-float.patch57
-rw-r--r--backport-Use-fd-based-ops-for-metadata-in-FA_TOUCH-mode-too-w.patch46
-rw-r--r--backport-Use-proper-type-for-copyTagsFromMainDebug.patch27
-rw-r--r--backport-Use-root-as-default-UID_0_USER-and-UID_0_GROUP.patch29
-rw-r--r--backport-Use-unsigned-integers-more-consistently-in-the-handl.patch63
-rw-r--r--backport-Validate-and-require-subkey-binding-signatures-on-PG.patch327
-rw-r--r--backport-bugfix-wrong-symlink-length-on-some-filesystems.patch44
-rw-r--r--backport-rpm2cpio.sh-Don-t-drop-newlines-from-header-sizes.patch35
-rw-r--r--backport-rpm2cpio.sh-only-read-needed-bytes-of-file-magic.patch27
-rw-r--r--backport-rpm2cpio.sh-strip-null-bytes-with-tr.patch35
-rw-r--r--backport-rpmkeys-exit-non-zero-on-I-O-errors.patch53
-rw-r--r--backport-support-for-POSIX-getopt-behaviour.patch33
-rw-r--r--backport-treat-0-as-valid-file-descriptor.patch27
-rw-r--r--bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch80
-rw-r--r--bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch35
-rw-r--r--call-process_digest_list-after-files-are-added.patch115
-rw-r--r--dont-remove-ima-xattr-of-parser-when-upgrading.patch35
-rw-r--r--fix-lsetxattr-error-in-container.patch64
-rw-r--r--get-in-use-of-ndb.patch42
-rw-r--r--revert-always-execute-file-trigger-scriptlet-callbac.patch26
-rw-r--r--rpm-4.12.0-rpm2cpio-hack.patch18
-rw-r--r--rpm-Add-sw64-architecture.patch172
-rw-r--r--rpm-selinux-plugin-check-context-file-exist.patch26
-rw-r--r--rpm.spec733
-rw-r--r--sources1
-rw-r--r--still-in-use-of-python-scripts-from-old-version.patch210
106 files changed, 7623 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..6686b11 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/rpm-4.17.0.tar.bz2
diff --git a/0001-add-default-machine-name-to-support-loongarch.patch b/0001-add-default-machine-name-to-support-loongarch.patch
new file mode 100644
index 0000000..f127fe0
--- /dev/null
+++ b/0001-add-default-machine-name-to-support-loongarch.patch
@@ -0,0 +1,30 @@
+From f492b34a694a4bf40e075a030c01f360eaa5500e Mon Sep 17 00:00:00 2001
+From: Wenlong Zhang <zhangwenlong@loongson.cn>
+Date: Fri, 27 May 2022 09:41:38 +0800
+Subject: [PATCH] add default machine name to support loongarch
+
+---
+ lib/rpmrc.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/lib/rpmrc.c b/lib/rpmrc.c
+index 120777c..bd0dbca 100644
+--- a/lib/rpmrc.c
++++ b/lib/rpmrc.c
+@@ -1242,6 +1242,13 @@ static void defaultMachine(rpmrcCtx ctx, const char ** arch, const char ** os)
+ }
+ # endif /* riscv */
+
++# if defined(__linux__) && defined(__loongarch__)
++ if (sizeof(long) == 4)
++ strcpy(un.machine, "loongarch32");
++ else if (sizeof(long) == 8)
++ strcpy(un.machine, "loongarch64");
++# endif /* loongarch */
++
+ # if defined(__GNUC__) && defined(__alpha__)
+ {
+ unsigned long amask, implver;
+--
+2.27.0
+
diff --git a/Add-digest-list-plugin.patch b/Add-digest-list-plugin.patch
new file mode 100644
index 0000000..2256824
--- /dev/null
+++ b/Add-digest-list-plugin.patch
@@ -0,0 +1,586 @@
+From e49074a4e4bd0699d2c4a5bb3a0dc5ca45e19e12 Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Wed, 26 Feb 2020 15:54:24 +0100
+Subject: [PATCH 2/3] Add digest list plugin
+
+---
+ macros.in | 1 +
+ plugins/Makefile.am | 4 +
+ plugins/digest_list.c | 498 ++++++++++++++++++++++++++++++++++++++++++
+ rpmio/digest.h | 1 +
+ rpmio/rpmpgp.c | 3 +
+ 5 files changed, 507 insertions(+)
+ create mode 100644 plugins/digest_list.c
+
+diff --git a/macros.in b/macros.in
+index 402749362..8619c1323 100644
+--- a/macros.in
++++ b/macros.in
+@@ -1184,6 +1184,7 @@ package or when debugging this package.\
+ %__transaction_prioreset %{__plugindir}/prioreset.so
+ %__transaction_audit %{__plugindir}/audit.so
+ %__transaction_dbus_announce %{__plugindir}/dbus_announce.so
++%__transaction_digest_list %{__plugindir}/digest_list.so
+
+ #------------------------------------------------------------------------------
+ # Macros for further automated spec %setup and patch application
+diff --git a/plugins/Makefile.am b/plugins/Makefile.am
+index d4ef039ed..07aa3585b 100644
+--- a/plugins/Makefile.am
++++ b/plugins/Makefile.am
+@@ -48,3 +48,7 @@ audit_la_sources = audit.c
+ audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@
+ plugins_LTLIBRARIES += audit.la
+ endif
++
++digest_list_la_sources = digest_list.c
++digest_list_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
++plugins_LTLIBRARIES += digest_list.la
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+new file mode 100644
+index 000000000..beb397309
+--- /dev/null
++++ b/plugins/digest_list.c
+@@ -0,0 +1,499 @@
++#include "system.h"
++#include "errno.h"
++
++#include <fcntl.h>
++#include <rpm/rpmlog.h>
++#include <rpm/rpmts.h>
++#include <rpm/header.h>
++#include <rpmio/digest.h>
++#include <rpmio/rpmpgp.h>
++#include <rpm/rpmfileutil.h>
++#include "lib/rpmplugin.h"
++#include <netinet/in.h>
++#include <sys/stat.h>
++#include <openssl/sha.h>
++#include <sys/xattr.h>
++#include <linux/xattr.h>
++#include <asm/byteorder.h>
++#include <sys/wait.h>
++
++#include "debug.h"
++
++#define IMA_DIR "/sys/kernel/security/ima"
++#define DIGEST_LIST_DATA_PATH IMA_DIR "/digest_list_data"
++#define DIGEST_LIST_DATA_DEL_PATH IMA_DIR "/digest_list_data_del"
++#define DIGEST_LIST_COUNT IMA_DIR "/digests_count"
++#define DIGEST_LIST_DEFAULT_PATH "/etc/ima/digest_lists"
++#define RPM_PARSER "/usr/libexec/rpm_parser"
++
++#define DIGEST_LIST_OP_ADD 0
++#define DIGEST_LIST_OP_DEL 1
++
++enum hash_algo {
++ HASH_ALGO_MD4,
++ HASH_ALGO_MD5,
++ HASH_ALGO_SHA1,
++ HASH_ALGO_RIPE_MD_160,
++ HASH_ALGO_SHA256,
++ HASH_ALGO_SHA384,
++ HASH_ALGO_SHA512,
++ HASH_ALGO_SHA224,
++ HASH_ALGO_RIPE_MD_128,
++ HASH_ALGO_RIPE_MD_256,
++ HASH_ALGO_RIPE_MD_320,
++ HASH_ALGO_WP_256,
++ HASH_ALGO_WP_384,
++ HASH_ALGO_WP_512,
++ HASH_ALGO_TGR_128,
++ HASH_ALGO_TGR_160,
++ HASH_ALGO_TGR_192,
++ HASH_ALGO_SM3_256,
++ HASH_ALGO__LAST
++};
++
++#define PGPHASHALGO__LAST PGPHASHALGO_SHA224 + 1
++enum hash_algo pgp_algo_mapping[PGPHASHALGO__LAST] = {
++ [PGPHASHALGO_MD5] = HASH_ALGO_MD5,
++ [PGPHASHALGO_SHA1] = HASH_ALGO_SHA1,
++ [PGPHASHALGO_SHA224] = HASH_ALGO_SHA224,
++ [PGPHASHALGO_SHA256] = HASH_ALGO_SHA256,
++ [PGPHASHALGO_SHA384] = HASH_ALGO_SHA384,
++ [PGPHASHALGO_SHA512] = HASH_ALGO_SHA512,
++};
++
++/* from integrity.h */
++enum evm_ima_xattr_type {
++ IMA_XATTR_DIGEST = 0x01,
++ EVM_XATTR_HMAC,
++ EVM_IMA_XATTR_DIGSIG,
++ IMA_XATTR_DIGEST_NG,
++ EVM_XATTR_PORTABLE_DIGSIG,
++ EVM_IMA_XATTR_DIGEST_LIST,
++ IMA_XATTR_LAST
++};
++
++struct evm_ima_xattr_data {
++ uint8_t type;
++ uint8_t digest[SHA512_DIGEST_LENGTH + 1];
++} __attribute__((packed));
++
++struct signature_v2_hdr {
++ uint8_t type; /* xattr type */
++ uint8_t version; /* signature format version */
++ uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */
++ __be32 keyid; /* IMA key identifier - not X509/PGP specific */
++ __be16 sig_size; /* signature size */
++ uint8_t sig[0]; /* signature payload */
++} __attribute__((packed));
++
++static int upload_digest_list(char *path, int type, int digest_list_signed)
++{
++ size_t size;
++ char buf[21];
++ const char *ima_path = DIGEST_LIST_DATA_PATH;
++ struct stat st;
++ pid_t pid;
++ int ret = 0, fd;
++
++ if (type == TR_REMOVED)
++ ima_path = DIGEST_LIST_DATA_DEL_PATH;
++
++ if (stat(ima_path, &st) == -1)
++ return 0;
++
++ /* First determine if kernel interface can accept new digest lists */
++ fd = open(DIGEST_LIST_COUNT, O_RDONLY);
++ if (fd < 0) {
++ rpmlog(RPMLOG_ERR, "digest_list: could not open IMA interface "
++ "'%s': %s\n", DIGEST_LIST_COUNT, strerror(errno));
++ return -EACCES;
++ }
++
++ ret = read(fd, buf, sizeof(buf));
++ close(fd);
++
++ if (ret <= 0) {
++ rpmlog(RPMLOG_ERR, "digest_list: could not read from IMA "
++ "interface '%s': %s\n", DIGEST_LIST_COUNT,
++ strerror(errno));
++ return -EACCES;
++ }
++
++ /* Last character is newline */
++ buf[ret - 1] = '\0';
++
++ rpmlog(RPMLOG_DEBUG, "digest_list: digests count %s\n", buf);
++
++ if (*buf == '0') {
++ rpmlog(RPMLOG_DEBUG, "digest_list: not uploading '%s' to IMA "
++ "interface '%s'\n", path, ima_path);
++ return RPMRC_OK;
++ }
++
++ /* If the digest list is not signed, execute the RPM parser */
++ if (!digest_list_signed) {
++ if ((pid = fork()) == 0) {
++ execlp(RPM_PARSER, RPM_PARSER, (type == TR_ADDED) ?
++ "add" : "del", path, NULL);
++ _exit(EXIT_FAILURE);
++ }
++
++ waitpid(pid, &ret, 0);
++ if (ret != 0)
++ rpmlog(RPMLOG_ERR, "digest_list: %s returned %d\n",
++ RPM_PARSER, ret);
++ return 0;
++ }
++
++ fd = open(ima_path, O_WRONLY);
++ if (fd < 0) {
++ rpmlog(RPMLOG_ERR, "digest_list: could not open IMA interface "
++ "'%s': %s\n", ima_path, strerror(errno));
++ return -EACCES;
++ }
++
++ /* Write the path of the digest list to securityfs */
++ size = write(fd, path, strlen(path));
++ if (size != strlen(path)) {
++ rpmlog(RPMLOG_ERR, "digest_list: could not write '%s' to IMA "
++ "interface '%s': %s\n", path, ima_path, strerror(errno));
++ ret = -EIO;
++ goto out;
++ }
++
++ rpmlog(RPMLOG_DEBUG, "digest_list: written '%s' to '%s'\n", path,
++ ima_path);
++out:
++ close(fd);
++ return ret;
++}
++
++static int write_rpm_digest_list(rpmte te, char *path)
++{
++ FD_t fd;
++ ssize_t written;
++ Header rpm = rpmteHeader(te);
++ rpmtd immutable;
++ int ret = 0;
++
++ immutable = rpmtdNew();
++ headerGet(rpm, RPMTAG_HEADERIMMUTABLE, immutable, 0);
++
++ fd = Fopen(path, "w.ufdio");
++ if (fd == NULL || Ferror(fd)) {
++ ret = -EACCES;
++ goto out;
++ }
++
++ written = Fwrite(rpm_header_magic, sizeof(uint8_t),
++ sizeof(rpm_header_magic), fd);
++
++ if (written != sizeof(rpm_header_magic)) {
++ ret = -EIO;
++ goto out;
++ }
++
++ written = Fwrite(immutable->data, sizeof(uint8_t),
++ immutable->count, fd);
++ if (written != immutable->count || Ferror(fd))
++ ret = -EIO;
++out:
++ Fclose(fd);
++ rpmtdFree(immutable);
++ return ret;
++}
++
++static int write_rpm_digest_list_ima_xattr(rpmte te, char *path)
++{
++ rpmtd signature;
++ ssize_t written;
++ uint8_t sig[2048] = { 0 };
++ pgpDigParams sigp = NULL;
++ struct signature_v2_hdr *sig_hdr = (struct signature_v2_hdr *)sig;
++ Header rpm = rpmteHeader(te);
++ FD_t fd;
++ int ret = 0, sig_size, sig_size_rounded;
++
++ signature = rpmtdNew();
++ headerGet(rpm, RPMTAG_RSAHEADER, signature, 0);
++ ret = pgpPrtParams(signature->data, signature->count,
++ PGPTAG_SIGNATURE, &sigp);
++
++ if (ret) {
++ ret = -ENOENT;
++ goto out;
++ }
++
++ fd = Fopen(path, "a.ufdio");
++ if (fd == NULL || Ferror(fd)) {
++ ret = -EACCES;
++ goto out;
++ }
++
++ written = Fwrite(sigp->hash, sizeof(uint8_t),
++ sigp->hashlen, fd);
++ if (written != sigp->hashlen || Ferror(fd)) {
++ ret = -EIO;
++ goto out;
++ }
++
++ if (sigp->version == 4) {
++ /* V4 trailer is six octets long (rfc4880) */
++ uint8_t trailer[6];
++ uint32_t nb = sigp->hashlen;
++ nb = htonl(nb);
++ trailer[0] = sigp->version;
++ trailer[1] = 0xff;
++ memcpy(trailer+2, &nb, 4);
++
++ written = Fwrite(trailer, sizeof(uint8_t), sizeof(trailer), fd);
++ if (written != sizeof(trailer) || Ferror(fd)) {
++ ret = -EIO;
++ goto out;
++ }
++ }
++
++ Fclose(fd);
++
++ sig_hdr->type = EVM_IMA_XATTR_DIGSIG;
++ sig_hdr->version = 2;
++ sig_hdr->hash_algo = pgp_algo_mapping[sigp->hash_algo];
++ memcpy((void *)&sig_hdr->keyid, sigp->signid + sizeof(uint32_t),
++ sizeof(uint32_t));
++
++ sig_size = (pgpMpiBits(sigp->data) + 7) >> 3;
++ if (sizeof(sig_hdr) + sig_size > sizeof(sig)) {
++ rpmlog(RPMLOG_ERR,
++ "digest_list: signature in %s too big\n", path);
++ ret = -E2BIG;
++ goto out;
++ }
++
++ sig_size_rounded = ((sig_size + 7) >> 3) * 8;
++ sig_hdr->sig_size = __cpu_to_be16(sig_size_rounded);
++
++ memcpy(sig_hdr->sig + sig_size_rounded - sig_size,
++ (uint8_t *)sigp->data + 2, sig_size);
++
++ ret = lsetxattr(path, XATTR_NAME_IMA,
++ sig, sizeof(*sig_hdr) + sig_size_rounded, 0);
++ if (ret < 0)
++ rpmlog(RPMLOG_ERR, "digest_list: could not apply security.ima "
++ "on '%s': %s\n", path, strerror(errno));
++ else
++ rpmlog(RPMLOG_DEBUG, "digest_list: security.ima successfully "
++ "applied on '%s'\n", path);
++out:
++ pgpDigParamsFree(sigp);
++ rpmtdFree(signature);
++ return ret;
++}
++
++static int write_digest_list_ima_xattr(rpmte te, char *path, char *path_sig)
++{
++ rpmtd signature;
++ uint8_t sig[2048] = { 0 };
++ pgpDigParams sigp = NULL;
++ struct signature_v2_hdr *sig_hdr = (struct signature_v2_hdr *)sig;
++ Header rpm = rpmteHeader(te);
++ FD_t fd;
++ struct stat st;
++ int ret = 0, sig_size;
++
++ signature = rpmtdNew();
++ headerGet(rpm, RPMTAG_RSAHEADER, signature, 0);
++ ret = pgpPrtParams(signature->data, signature->count,
++ PGPTAG_SIGNATURE, &sigp);
++
++ if (ret) {
++ ret = -ENOENT;
++ goto out;
++ }
++
++ sig_hdr->type = EVM_IMA_XATTR_DIGSIG;
++ sig_hdr->version = 2;
++ sig_hdr->hash_algo = HASH_ALGO_SHA256;
++ memcpy((void *)&sig_hdr->keyid, sigp->signid + sizeof(uint32_t),
++ sizeof(uint32_t));
++
++ if (stat(path_sig, &st) == -1) {
++ ret = -EACCES;
++ goto out;
++ }
++
++ if (sizeof(sig_hdr) + st.st_size > sizeof(sig)) {
++ rpmlog(RPMLOG_ERR, "digest_list: signature in %s too big\n",
++ path);
++ ret = -E2BIG;
++ goto out;
++ }
++
++ fd = Fopen(path_sig, "r.ufdio");
++ if (fd < 0) {
++ rpmlog(RPMLOG_ERR, "digest_list: could not open '%s': %s\n",
++ path_sig, strerror(errno));
++ ret = -EACCES;
++ goto out;
++ }
++
++ sig_size = Fread(sig_hdr->sig, sizeof(uint8_t), st.st_size, fd);
++ if (sig_size != st.st_size || Ferror(fd)) {
++ rpmlog(RPMLOG_ERR, "digest_list: could not read '%s': %s\n",
++ path_sig, strerror(errno));
++ Fclose(fd);
++ ret = -EIO;
++ goto out;
++ }
++
++ sig_hdr->sig_size = __cpu_to_be16(sig_size);
++
++ rpmlog(RPMLOG_DEBUG,
++ "digest_list: read signature of %d bytes from '%s'\n",
++ sig_size, path_sig);
++
++ ret = lsetxattr(path, XATTR_NAME_IMA,
++ sig, sizeof(*sig_hdr) + sig_size, 0);
++ if (ret < 0)
++ rpmlog(RPMLOG_ERR, "digest_list: could not apply security.ima "
++ "on '%s': %s\n", path, strerror(errno));
++ else
++ rpmlog(RPMLOG_DEBUG, "digest_list: security.ima successfully "
++ "applied on '%s'\n", path);
++out:
++ pgpDigParamsFree(sigp);
++ rpmtdFree(signature);
++ return ret;
++}
++
++static int process_digest_list(rpmte te, int parser)
++{
++ char *path = NULL, *path_sig = NULL;
++ int digest_list_signed = 0;
++ struct stat st;
++ ssize_t size;
++ rpmRC ret = RPMRC_OK;
++
++ path = malloc(PATH_MAX);
++ if (!path) {
++ ret = RPMRC_FAIL;
++ goto out;
++ }
++
++ path_sig = malloc(PATH_MAX);
++ if (!path_sig) {
++ ret = RPMRC_FAIL;
++ goto out;
++ }
++
++ if (parser)
++ snprintf(path_sig, PATH_MAX,
++ "%s.sig/0-parser_list-compact-libexec.sig",
++ DIGEST_LIST_DEFAULT_PATH);
++ else
++ snprintf(path_sig, PATH_MAX,
++ "%s.sig/0-metadata_list-compact-%s-%s-%s.%s.sig",
++ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te),
++ rpmteR(te), rpmteA(te));
++
++ if (!stat(path_sig, &st))
++ digest_list_signed = 1;
++
++ if (parser && !digest_list_signed)
++ goto out;
++
++ if (parser)
++ snprintf(path, PATH_MAX, "%s/0-parser_list-compact-libexec",
++ DIGEST_LIST_DEFAULT_PATH);
++ else
++ snprintf(path, PATH_MAX,
++ "%s/0-metadata_list-compact-%s-%s-%s.%s",
++ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te),
++ rpmteR(te), rpmteA(te));
++
++ if (stat(path, &st) == -1)
++ goto out;
++
++ if (!parser && !digest_list_signed)
++ snprintf(path, PATH_MAX, "%s/0-metadata_list-rpm-%s-%s-%s.%s",
++ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te),
++ rpmteR(te), rpmteA(te));
++
++ size = lgetxattr(path, XATTR_NAME_IMA, NULL, 0);
++
++ /* Don't upload again if digest list was already processed */
++ if ((rpmteType(te) == TR_ADDED && size > 0) ||
++ (rpmteType(te) == TR_REMOVED && size < 0)) {
++ rpmlog(RPMLOG_DEBUG, "digest_list: '%s' already processed, "
++ "nothing to do\n", path);
++ goto out;
++ }
++
++ if (rpmteType(te) == TR_ADDED) {
++ if (!digest_list_signed) {
++ /* Write RPM header to the disk */
++ ret = write_rpm_digest_list(te, path);
++ if (ret < 0) {
++ ret = RPMRC_FAIL;
++ goto out;
++ }
++
++ /* Write RPM header sig to security.ima */
++ ret = write_rpm_digest_list_ima_xattr(te, path);
++ } else {
++ ret = write_digest_list_ima_xattr(te, path, path_sig);
++ }
++
++ if (ret < 0) {
++ ret = RPMRC_FAIL;
++ goto out;
++ }
++ }
++
++ /* Upload digest list to securityfs */
++ upload_digest_list(path, rpmteType(te), digest_list_signed);
++
++ if (rpmteType(te) == TR_REMOVED) {
++ if (!digest_list_signed) {
++ unlink(path);
++ goto out;
++ }
++
++ ret = lremovexattr(path, XATTR_NAME_IMA);
++ if (ret < 0)
++ rpmlog(RPMLOG_ERR, "digest_list: cannot remove "
++ "security.ima from '%s'\n", path);
++ else
++ rpmlog(RPMLOG_DEBUG, "digest_list: security.ima "
++ "successfully removed from '%s'\n", path);
++ }
++out:
++ free(path);
++ free(path_sig);
++ return ret;
++}
++
++static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
++{
++ process_digest_list(te, 0);
++ if (!strcmp(rpmteN(te), "digest-list-tools"))
++ process_digest_list(te, 1);
++
++ return RPMRC_OK;
++}
++
++static rpmRC digest_list_psm_post(rpmPlugin plugin, rpmte te, int res)
++{
++ if (res != RPMRC_OK)
++ return RPMRC_OK;
++
++ process_digest_list(te, 0);
++ if (!strcmp(rpmteN(te), "digest-list-tools"))
++ process_digest_list(te, 1);
++
++ return RPMRC_OK;
++}
++
++struct rpmPluginHooks_s digest_list_hooks = {
++ .psm_pre = digest_list_psm_pre,
++ .psm_post = digest_list_psm_post,
++};
+diff --git a/rpmio/digest.h b/rpmio/digest.h
+index 9e0cde3b9..01ca10d92 100644
+--- a/rpmio/digest.h
++++ b/rpmio/digest.h
+@@ -24,6 +24,7 @@ struct pgpDigAlg_s {
+ struct pgpDigParams_s {
+ char * userid;
+ uint8_t * hash;
++ const uint8_t * data;
+ uint8_t tag;
+
+ uint8_t version; /*!< version number. */
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 46cd0f31a..3c6b18b53 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -600,6 +600,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ }
+
+ p = ((uint8_t *)v) + sizeof(*v);
++ _digp->data = p;
+ rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
+ } break;
+ case 4:
+@@ -658,6 +659,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ if (p > hend)
+ return 1;
+
++ _digp->data = p;
+ rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
+ } break;
+ default:
+@@ -745,6 +747,7 @@ static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
+ }
+
+ p = ((uint8_t *)v) + sizeof(*v);
++ _digp->data = p;
+ rc = pgpPrtPubkeyParams(v->pubkey_algo, p, h, hlen, _digp);
+ }
+ } break;
+--
+2.27.GIT
+
diff --git a/Add-license-to-digest_list.c.patch b/Add-license-to-digest_list.c.patch
new file mode 100644
index 0000000..fe07b05
--- /dev/null
+++ b/Add-license-to-digest_list.c.patch
@@ -0,0 +1,34 @@
+From 676cd4c0b90043b745a39b43446e42e80948c643 Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Fri, 12 Mar 2021 10:57:24 +0100
+Subject: [PATCH 5/5] Add license to digest_list.c
+
+---
+ plugins/digest_list.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+index cfde5cd1d..992a7e81a 100644
+--- a/plugins/digest_list.c
++++ b/plugins/digest_list.c
+@@ -1,3 +1,17 @@
++/*
++ * Copyright (C) 2020-2021 Huawei Technologies Duesseldorf GmbH
++ *
++ * Author: Roberto Sassu <roberto.sassu@huawei.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation, version 2 of the
++ * License.
++ *
++ * File: digest_list.c
++ * Plugin to load digest lists in the Linux kernel.
++ */
++
+ #include "system.h"
+ #include "errno.h"
+
+--
+2.26.2
+
diff --git a/Add-loongarch-architecture-support.patch b/Add-loongarch-architecture-support.patch
new file mode 100644
index 0000000..80c9c41
--- /dev/null
+++ b/Add-loongarch-architecture-support.patch
@@ -0,0 +1,99 @@
+From 3100da59abd272fc3f301a30ebabedf86b0b4a00 Mon Sep 17 00:00:00 2001
+From: Sun Haiyong <sunhaiyong@loongson.cn>
+Date: Tue, 21 Dec 2021 20:40:27 +0800
+Subject: [PATCH] Add loongarch architecture support.
+
+---
+ installplatform | 12 ++++++++++++
+ rpmrc.in | 17 +++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/installplatform b/installplatform
+index 12339fc..74c50a2 100755
+--- a/installplatform
++++ b/installplatform
+@@ -168,6 +168,18 @@ for ARCH in noarch `grep ^arch_canon $RPMRC | cut -d: -f2`; do
+ CANONARCH=mips64r6el
+ CANONCOLOR=3
+ ;;
++ loongarch32)
++ ISANAME=loongarch
++ ISABITS=32
++ CANONARCH=loongarch32
++ CANONCOLOR=0
++ ;;
++ loongarch64)
++ ISANAME=loongarch
++ ISABITS=64
++ CANONARCH=loongarch64
++ CANONCOLOR=3
++ ;;
+ m68k)
+ ISANAME=m68k
+ ISABITS=32
+diff --git a/rpmrc.in b/rpmrc.in
+index 5bd9ba3..fc2932a 100644
+--- a/rpmrc.in
++++ b/rpmrc.in
+@@ -67,6 +67,8 @@ optflags: mipsr6el -O2 -g
+ optflags: mips64r6 -O2 -g
+ optflags: mips64r6el -O2 -g
+
++optflags: loongarch64 -O2 -g
++
+ optflags: armv3l -O2 -g -march=armv3
+ optflags: armv4b -O2 -g -march=armv4
+ optflags: armv4l -O2 -g -march=armv4
+@@ -137,6 +139,9 @@ archcolor: mipsr6el 1
+ archcolor: mips64r6 2
+ archcolor: mips64r6el 2
+
++archcolor: loongarch32 1
++archcolor: loongarch64 2
++
+ archcolor: m68k 1
+
+ archcolor: m68kmint 1
+@@ -257,6 +262,9 @@ arch_canon: mips64r6el: mips64r6el 21
+ arch_canon: riscv: riscv64 22
+ arch_canon: riscv64: riscv64 22
+
++arch_canon: loongarch32: loongarch32 25
++arch_canon: loongarch64: loongarch64 26
++
+ #############################################################
+ # Canonical OS names and numbers
+
+@@ -360,6 +368,9 @@ buildarchtranslate: mipsr6el: mipsr6el
+ buildarchtranslate: mips64r6: mips64r6
+ buildarchtranslate: mips64r6el: mips64r6el
+
++buildarchtranslate: loongarch32: loongarch32
++buildarchtranslate: loongarch64: loongarch64
++
+ buildarchtranslate: m68k: m68k
+
+ buildarchtranslate: atarist: m68kmint
+@@ -449,6 +460,9 @@ arch_compat: mipsr6el: noarch
+ arch_compat: mips64r6: mipsr6
+ arch_compat: mips64r6el: mipsr6el
+
++arch_compat: loongarch32: noarch
++arch_compat: loongarch64: loongarch32
++
+ arch_compat: hppa2.0: hppa1.2
+ arch_compat: hppa1.2: hppa1.1
+ arch_compat: hppa1.1: hppa1.0
+@@ -586,6 +600,9 @@ buildarch_compat: mipsr6el: noarch
+ buildarch_compat: mips64r6: noarch
+ buildarch_compat: mips64r6el: noarch
+
++buildarch_compat: loongarch32: noarch
++buildarch_compat: loongarch64: noarch
++
+ buildarch_compat: armv4b: noarch
+ buildarch_compat: armv8l: armv7l
+ buildarch_compat: armv7l: armv6l
+--
+2.30.0
+
diff --git a/Avoid-generating-digest-lists-if-they-are-already-pa.patch b/Avoid-generating-digest-lists-if-they-are-already-pa.patch
new file mode 100644
index 0000000..ecfedb9
--- /dev/null
+++ b/Avoid-generating-digest-lists-if-they-are-already-pa.patch
@@ -0,0 +1,50 @@
+From d0b01bb4366ca467bfd1386820fe17ae58aa3c8c Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Wed, 17 Mar 2021 17:25:46 +0100
+Subject: [PATCH] Avoid generating digest lists if they are already packaged
+
+---
+ build/files.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/build/files.c b/build/files.c
+index d5c83a094..a30828e1c 100644
+--- a/build/files.c
++++ b/build/files.c
+@@ -51,6 +51,7 @@
+ #define DEBUG_ID_DIR "/usr/lib/debug/.build-id"
+ #define DEBUG_DWZ_DIR "/usr/lib/debug/.dwz"
+ #define DIGEST_LIST_DIR "/.digest_lists"
++#define DEST_DIGEST_LIST_DIR "/etc/ima/digest_lists"
+
+ #undef HASHTYPE
+ #undef HTKEYTYPE
+@@ -993,7 +994,7 @@ static void genDigestListInput(FileList fl, Package pkg, int isSrc)
+ char buf[BUFSIZ];
+ char file_info[BUFSIZ];
+ char file_digest[128 * 2 + 1];
+- int i;
++ int i, gen_digest_lists = 1;
+ uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo;
+ Header h = pkg->header; /* just a shortcut */
+
+@@ -1100,9 +1101,15 @@ static void genDigestListInput(FileList fl, Package pkg, int isSrc)
+ strlen(flp->caps) ? flp->caps : "");
+ appendStringBuf(check_fileList_bin_pkg, file_info);
+ }
++
++ if (S_ISREG(flp->fl_mode) &&
++ !strncmp(flp->cpioPath, DEST_DIGEST_LIST_DIR,
++ sizeof(DEST_DIGEST_LIST_DIR) - 1))
++ gen_digest_lists = 0;
+ }
+
+- if (genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0)
++ if (gen_digest_lists &&
++ genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0)
+ fl->processingFailed = 1;
+ }
+
+--
+2.26.2
+
diff --git a/Check-rpm-parser.patch b/Check-rpm-parser.patch
new file mode 100644
index 0000000..43052a2
--- /dev/null
+++ b/Check-rpm-parser.patch
@@ -0,0 +1,29 @@
+From 18df7feaf512cf4d7548121e1f04d4e7066fb324 Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Wed, 10 Mar 2021 12:23:32 +0100
+Subject: [PATCH 2/5] Check rpm parser
+
+---
+ plugins/digest_list.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+index bb778c57f..c62f8c22f 100644
+--- a/plugins/digest_list.c
++++ b/plugins/digest_list.c
+@@ -131,6 +131,12 @@ static int upload_digest_list(char *path, int type, int digest_list_signed)
+
+ /* If the digest list is not signed, execute the RPM parser */
+ if (!digest_list_signed) {
++ if (stat(RPM_PARSER, &st) == -1) {
++ rpmlog(RPMLOG_DEBUG, "digest_list: %s not found, "
++ "not uploading digest list\n", RPM_PARSER);
++ return 0;
++ }
++
+ if ((pid = fork()) == 0) {
+ execlp(RPM_PARSER, RPM_PARSER, (type == TR_ADDED) ?
+ "add" : "del", path, NULL);
+--
+2.26.2
+
diff --git a/Don-t-add-dist-to-release-if-it-is-already-there.patch b/Don-t-add-dist-to-release-if-it-is-already-there.patch
new file mode 100644
index 0000000..8820ef2
--- /dev/null
+++ b/Don-t-add-dist-to-release-if-it-is-already-there.patch
@@ -0,0 +1,26 @@
+From 90b01a63c7c3312c25d2c3b74508a98b51e703fa Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Wed, 22 Jul 2020 17:24:58 +0200
+Subject: [PATCH 3/3] Don't add dist to release if it is already there
+
+---
+ build/parsePreamble.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/build/parsePreamble.c b/build/parsePreamble.c
+index 147059bb5..c3d898b4c 100644
+--- a/build/parsePreamble.c
++++ b/build/parsePreamble.c
+@@ -810,7 +810,8 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
+ SINGLE_TOKEN_ONLY;
+ if (tag == RPMTAG_RELEASE) {
+ char *dist = rpmExpand("%{?dist}",NULL);
+- rasprintf(&field,"%s%s",field,dist);
++ rasprintf(&field,"%s%s",field,
++ (dist && strstr(field, dist)) ? "" : dist);
+ free(dist);
+ }
+ if (rpmCharCheck(spec, field, ALLOWED_CHARS_VERREL))
+--
+2.27.GIT
+
diff --git a/Fix-digest_list_counter.patch b/Fix-digest_list_counter.patch
new file mode 100644
index 0000000..b9a3cd9
--- /dev/null
+++ b/Fix-digest_list_counter.patch
@@ -0,0 +1,81 @@
+From 8ecd5fc6884ae165e38e16b900cc4da90665b9db Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Wed, 10 Mar 2021 12:22:39 +0100
+Subject: [PATCH 1/5] Fix digest_list_counter
+
+---
+ plugins/digest_list.c | 38 +++++++++++++++++++++++---------------
+ 1 file changed, 23 insertions(+), 15 deletions(-)
+
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+index 2dfa21e35..bb778c57f 100644
+--- a/plugins/digest_list.c
++++ b/plugins/digest_list.c
+@@ -477,8 +477,8 @@ int digest_list_counter;
+ static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
+ {
+ Header rpm = rpmteHeader(te);
+- rpmtd dirnames;
+- int i;
++ rpmtd dirnames, dirindexes;
++ int i = -1;
+
+ digest_list_counter = 0;
+
+@@ -487,13 +487,26 @@ static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
+
+ while ((i = rpmtdNext(dirnames)) >= 0) {
+ char *dirname = (char *) rpmtdGetString(dirnames);
++
+ if (!strncmp(dirname, DIGEST_LIST_DEFAULT_PATH,
+- sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
+- digest_list_counter++;
++ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1) &&
++ dirname[sizeof(DIGEST_LIST_DEFAULT_PATH) - 1] == '/')
++ break;
+ }
+
+ rpmtdFree(dirnames);
+
++ if (i == -1)
++ return RPMRC_OK;
++
++ dirindexes = rpmtdNew();
++ headerGet(rpm, RPMTAG_DIRINDEXES, dirindexes, 0);
++ while (rpmtdNext(dirindexes) >= 0)
++ if (rpmtdGetNumber(dirindexes) == i)
++ digest_list_counter++;
++
++ rpmtdFree(dirindexes);
++
+ cur_te = te;
+ return RPMRC_OK;
+ }
+@@ -517,18 +530,13 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
+ (!pre && action != FA_CREATE))
+ return RPMRC_OK;
+
+- if (digest_list_counter) {
+- if (!pre) {
+- if (!strncmp(path, DIGEST_LIST_DEFAULT_PATH,
+- sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
+- digest_list_counter--;
+- } else {
+- digest_list_counter = 0;
+- }
++ if (strncmp(path, DIGEST_LIST_DEFAULT_PATH,
++ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1) ||
++ path[sizeof(DIGEST_LIST_DEFAULT_PATH) - 1] != '/')
++ return RPMRC_OK;
+
+- if (digest_list_counter)
+- return RPMRC_OK;
+- }
++ if (!pre && --digest_list_counter)
++ return RPMRC_OK;
+
+ process_digest_list(cur_te, 0);
+ if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
+--
+2.26.2
+
diff --git a/Generate-digest-lists-before-calling-genCpioListAndH.patch b/Generate-digest-lists-before-calling-genCpioListAndH.patch
new file mode 100644
index 0000000..bc85a01
--- /dev/null
+++ b/Generate-digest-lists-before-calling-genCpioListAndH.patch
@@ -0,0 +1,255 @@
+From 2b0cab0ed63e77582b047f723b69a0e3dd647566 Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Wed, 12 Aug 2020 18:23:42 +0200
+Subject: [PATCH] Generate digest lists before calling genCpioListAndHeader()
+
+Signed-off-by: luhuaxin <luhuaxin1@huawei.com>
+---
+ build/files.c | 182 ++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 147 insertions(+), 35 deletions(-)
+
+diff --git a/build/files.c b/build/files.c
+index d1e56c0..5358ead 100644
+--- a/build/files.c
++++ b/build/files.c
+@@ -1000,20 +1000,149 @@ static int seenHardLink(FileRecords files, FileListRec flp, rpm_ino_t *fileid)
+ * @param pkg (sub) package
+ * @param isSrc pass 1 for source packages 0 otherwise
+ */
+-static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
++static void genDigestListInput(FileList fl, Package pkg, int isSrc)
+ {
+ FileListRec flp;
+ char buf[BUFSIZ];
+ char file_info[BUFSIZ];
+ char file_digest[128 * 2 + 1];
++ int i;
++ uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo;
++ Header h = pkg->header; /* just a shortcut */
++
++ /*
++ * See if non-md5 file digest algorithm is requested. If not
++ * specified, quietly assume md5. Otherwise check if supported type.
++ */
++ digestalgo = rpmExpandNumeric(isSrc ? "%{_source_filedigest_algorithm}" :
++ "%{_binary_filedigest_algorithm}");
++ if (digestalgo == 0) {
++ digestalgo = defaultalgo;
++ }
++
++ if (rpmDigestLength(digestalgo) == 0) {
++ rpmlog(RPMLOG_WARNING,
++ _("Unknown file digest algorithm %u, falling back to MD5\n"),
++ digestalgo);
++ digestalgo = defaultalgo;
++ }
++
++ /* Sort the big list */
++ if (fl->files.recs) {
++ qsort(fl->files.recs, fl->files.used,
++ sizeof(*(fl->files.recs)), compareFileListRecs);
++ }
++
++ /* Generate the header. */
++ for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) {
++ /* Merge duplicate entries. */
++ while (i < (fl->files.used - 1) &&
++ rstreq(flp->cpioPath, flp[1].cpioPath)) {
++
++ /* Two entries for the same file found, merge the entries. */
++ /* Note that an %exclude is a duplication of a file reference */
++
++ /* file flags */
++ flp[1].flags |= flp->flags;
++
++ if (!(flp[1].flags & RPMFILE_EXCLUDE))
++ rpmlog(RPMLOG_WARNING, _("File listed twice: %s\n"),
++ flp->cpioPath);
++
++ /* file mode */
++ if (S_ISDIR(flp->fl_mode)) {
++ if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
++ (flp->specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)))
++ flp[1].fl_mode = flp->fl_mode;
++ } else {
++ if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
++ (flp->specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)))
++ flp[1].fl_mode = flp->fl_mode;
++ }
++
++ /* uid */
++ if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
++ (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
++ {
++ flp[1].fl_uid = flp->fl_uid;
++ flp[1].uname = flp->uname;
++ }
++
++ /* gid */
++ if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
++ (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
++ {
++ flp[1].fl_gid = flp->fl_gid;
++ flp[1].gname = flp->gname;
++ }
++
++ /* verify flags */
++ if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
++ (flp->specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)))
++ flp[1].verifyFlags = flp->verifyFlags;
++
++ /* XXX to-do: language */
++
++ flp++; i++;
++ }
++
++ /* Skip files that were marked with %exclude. */
++ if (flp->flags & RPMFILE_EXCLUDE)
++ {
++ argvAdd(&pkg->fileExcludeList, flp->cpioPath);
++ continue;
++ }
++
++ buf[0] = '\0';
++ if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST))
++ (void) rpmDoDigest(digestalgo, flp->diskPath, 1,
++ (unsigned char *)buf);
++ headerPutString(h, RPMTAG_FILEDIGESTS, buf);
++ snprintf(file_digest, sizeof(file_digest), "%s", buf);
++
++ if (check_fileList_bin_pkg && S_ISREG(flp->fl_mode) &&
++ !(flp->flags & RPMFILE_GHOST)) {
++ appendStringBuf(check_fileList_bin_pkg, "path=");
++ appendStringBuf(check_fileList_bin_pkg, flp->diskPath);
++ snprintf(file_info, sizeof(file_info),
++ "|digestalgopgp=%d|digest=%s|mode=%d"
++ "|uname=%s|gname=%s|caps=%s\n",
++ digestalgo, file_digest, flp->fl_mode,
++ rpmstrPoolStr(fl->pool, flp->uname),
++ rpmstrPoolStr(fl->pool, flp->gname), flp->caps &&
++ strlen(flp->caps) ? flp->caps : "");
++ appendStringBuf(check_fileList_bin_pkg, file_info);
++ }
++ }
++
++ if (genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0)
++ fl->processingFailed = 1;
++}
++
++/**
++ * Add file entries to header.
++ * @todo Should directories have %doc/%config attributes? (#14531)
++ * @todo Remove RPMTAG_OLDFILENAMES, add dirname/basename instead.
++ * @param fl package file tree walk data
++ * @param pkg (sub) package
++ * @param isSrc pass 1 for source packages 0 otherwise
++ */
++static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
++{
++ FileListRec flp;
++ char buf[BUFSIZ];
+ int i, npaths = 0;
+ int fail_on_dupes = rpmExpandNumeric("%{?_duplicate_files_terminate_build}") > 0;
+ uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo;
+ rpm_loff_t totalFileSize = 0;
+ Header h = pkg->header; /* just a shortcut */
+- int processed = 0;
+ time_t source_date_epoch = 0;
+ char *srcdate = getenv("SOURCE_DATE_EPOCH");
++ struct rpmtd_s oldfiledigests;
++
++ headerGet(h, RPMTAG_FILEDIGESTS, &oldfiledigests, HEADERGET_ALLOC);
++ headerDel(h, RPMTAG_FILEDIGESTS);
++ rpmtdInit(&oldfiledigests);
+
+ /* Limit the maximum date to SOURCE_DATE_EPOCH if defined
+ * similar to the tar --clamp-mtime option
+@@ -1080,9 +1209,8 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
+
+ pkg->dpaths = xmalloc((fl->files.used + 1) * sizeof(*pkg->dpaths));
+
+-process_files:
+ /* Generate the header. */
+- for (i = processed, flp = fl->files.recs + processed; i < fl->files.used; i++, flp++) {
++ for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) {
+ rpm_ino_t fileid = flp - fl->files.recs;
+
+ /* Merge duplicate entries. */
+@@ -1212,13 +1340,17 @@ process_files:
+ if (fl->haveCaps) {
+ headerPutString(h, RPMTAG_FILECAPS, flp->caps);
+ }
+-
++
+ buf[0] = '\0';
+- if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST))
+- (void) rpmDoDigest(digestalgo, flp->diskPath, 1,
+- (unsigned char *)buf);
+- headerPutString(h, RPMTAG_FILEDIGESTS, buf);
+- snprintf(file_digest, sizeof(file_digest), "%s", buf);
++ if (strstr(flp->diskPath, DIGEST_LIST_DIR) || !oldfiledigests.count) {
++ if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST))
++ (void) rpmDoDigest(digestalgo, flp->diskPath, 1,
++ (unsigned char *)buf);
++ headerPutString(h, RPMTAG_FILEDIGESTS, buf);
++ } else {
++ headerPutString(h, RPMTAG_FILEDIGESTS,
++ rpmtdNextString(&oldfiledigests));
++ }
+
+ buf[0] = '\0';
+ if (S_ISLNK(flp->fl_mode)) {
+@@ -1259,31 +1391,6 @@ process_files:
+ flp->flags &= PARSEATTR_MASK;
+
+ headerPutUint32(h, RPMTAG_FILEFLAGS, &(flp->flags) ,1);
+-
+- if (!processed && check_fileList_bin_pkg && S_ISREG(flp->fl_mode) &&
+- !(flp->flags & RPMFILE_GHOST)) {
+- appendStringBuf(check_fileList_bin_pkg, "path=");
+- appendStringBuf(check_fileList_bin_pkg, flp->diskPath);
+- snprintf(file_info, sizeof(file_info),
+- "|digestalgopgp=%d|digest=%s|mode=%d"
+- "|uname=%s|gname=%s|caps=%s\n",
+- digestalgo, file_digest, flp->fl_mode,
+- rpmstrPoolStr(fl->pool, flp->uname),
+- rpmstrPoolStr(fl->pool, flp->gname), flp->caps &&
+- strlen(flp->caps) ? flp->caps : "");
+- appendStringBuf(check_fileList_bin_pkg, file_info);
+- }
+- }
+-
+- if (!processed) {
+- if (genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0) {
+- fl->processingFailed = 1;
+- } else if (i < fl->files.used) {
+- pkg->dpaths = xrealloc(pkg->dpaths,
+- (fl->files.used + 1) * sizeof(*pkg->dpaths));
+- processed = i;
+- goto process_files;
+- }
+ }
+
+ pkg->dpaths[npaths] = NULL;
+@@ -1324,6 +1431,7 @@ process_files:
+ /* Binary packages with dirNames cannot be installed by legacy rpm. */
+ (void) rpmlibNeedsFeature(pkg, "CompressedFileNames", "3.0.4-1");
+ }
++ rpmtdFreeData(&oldfiledigests);
+ }
+
+ static FileRecords FileRecordsFree(FileRecords files)
+@@ -2808,6 +2916,10 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
+ if (checkHardLinks(&fl.files))
+ (void) rpmlibNeedsFeature(pkg, "PartialHardlinkSets", "4.0.4-1");
+
++ genDigestListInput(&fl, pkg, 0);
++ if (fl.processingFailed)
++ goto exit;
++
+ genCpioListAndHeader(&fl, pkg, 0);
+
+ exit:
+--
+2.33.0
+
diff --git a/Generate-digest-lists.patch b/Generate-digest-lists.patch
new file mode 100644
index 0000000..7fbac1c
--- /dev/null
+++ b/Generate-digest-lists.patch
@@ -0,0 +1,323 @@
+From 4d1801825c754171962050ee9c36c2d69c630ece Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Thu, 12 Mar 2020 17:29:55 +0100
+Subject: [PATCH 1/3] Generate digest lists
+
+---
+ build/files.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 169 insertions(+), 7 deletions(-)
+
+diff --git a/build/files.c b/build/files.c
+index 6dfd801c8..ab6938d8c 100644
+--- a/build/files.c
++++ b/build/files.c
+@@ -50,6 +50,7 @@
+ #define DEBUG_LIB_PREFIX "/usr/lib/debug/"
+ #define DEBUG_ID_DIR "/usr/lib/debug/.build-id"
+ #define DEBUG_DWZ_DIR "/usr/lib/debug/.dwz"
++#define DIGEST_LIST_DIR "/.digest_lists"
+
+ #undef HASHTYPE
+ #undef HTKEYTYPE
+@@ -129,6 +130,8 @@ typedef struct AttrRec_s {
+
+ /* list of files */
+ static StringBuf check_fileList = NULL;
++/* list of files per binary package */
++static StringBuf check_fileList_bin_pkg = NULL;
+
+ typedef struct FileEntry_s {
+ rpmfileAttrs attrFlags;
+@@ -193,6 +196,10 @@ typedef struct FileList_s {
+ struct FileEntry_s cur;
+ } * FileList;
+
++static char *digest_list_dir;
++
++static int genDigestList(Header header, FileList fl, StringBuf fileList);
++
+ static void nullAttrRec(AttrRec ar)
+ {
+ memset(ar, 0, sizeof(*ar));
+@@ -997,11 +997,14 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
+ {
+ FileListRec flp;
+ char buf[BUFSIZ];
++ char file_info[BUFSIZ];
++ char file_digest[128 * 2 + 1];
+ int i, npaths = 0;
+ int fail_on_dupes = rpmExpandNumeric("%{?_duplicate_files_terminate_build}") > 0;
+ uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo;
+ rpm_loff_t totalFileSize = 0;
+ Header h = pkg->header; /* just a shortcut */
++ int processed = 0;
+ time_t source_date_epoch = 0;
+ char *srcdate = getenv("SOURCE_DATE_EPOCH");
+
+@@ -1058,8 +1067,9 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
+
+ pkg->dpaths = xmalloc((fl->files.used + 1) * sizeof(*pkg->dpaths));
+
++process_files:
+ /* Generate the header. */
+- for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) {
++ for (i = processed, flp = fl->files.recs + processed; i < fl->files.used; i++, flp++) {
+ rpm_ino_t fileid = flp - fl->files.recs;
+
+ /* Merge duplicate entries. */
+@@ -1190,7 +1200,8 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
+ (void) rpmDoDigest(digestalgo, flp->diskPath, 1,
+ (unsigned char *)buf);
+ headerPutString(h, RPMTAG_FILEDIGESTS, buf);
+-
++ snprintf(file_digest, sizeof(file_digest), "%s", buf);
++
+ buf[0] = '\0';
+ if (S_ISLNK(flp->fl_mode)) {
+ ssize_t llen = readlink(flp->diskPath, buf, BUFSIZ-1);
+@@ -1230,7 +1241,33 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
+ flp->flags &= PARSEATTR_MASK;
+
+ headerPutUint32(h, RPMTAG_FILEFLAGS, &(flp->flags) ,1);
++
++ if (!processed && check_fileList_bin_pkg && S_ISREG(flp->fl_mode) &&
++ !(flp->flags & RPMFILE_GHOST)) {
++ appendStringBuf(check_fileList_bin_pkg, "path=");
++ appendStringBuf(check_fileList_bin_pkg, flp->diskPath);
++ snprintf(file_info, sizeof(file_info),
++ "|digestalgopgp=%d|digest=%s|mode=%d"
++ "|uname=%s|gname=%s|caps=%s\n",
++ digestalgo, file_digest, flp->fl_mode,
++ rpmstrPoolStr(fl->pool, flp->uname),
++ rpmstrPoolStr(fl->pool, flp->gname), flp->caps &&
++ strlen(flp->caps) ? flp->caps : "");
++ appendStringBuf(check_fileList_bin_pkg, file_info);
++ }
++ }
++
++ if (!processed) {
++ if (genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0) {
++ fl->processingFailed = 1;
++ } else if (i < fl->files.used) {
++ pkg->dpaths = xrealloc(pkg->dpaths,
++ (fl->files.used + 1) * sizeof(*pkg->dpaths));
++ processed = i;
++ goto process_files;
++ }
+ }
++
+ pkg->dpaths[npaths] = NULL;
+
+ if (totalFileSize < UINT32_MAX) {
+@@ -1343,8 +1380,8 @@ static int validFilename(const char *fn)
+ * @param statp file stat (possibly NULL)
+ * @return RPMRC_OK on success
+ */
+-static rpmRC addFile(FileList fl, const char * diskPath,
+- struct stat * statp)
++static rpmRC addFile_common(FileList fl, const char * diskPath,
++ struct stat * statp, int digest_list)
+ {
+ size_t plen = strlen(diskPath);
+ char buf[plen + 1];
+@@ -1355,6 +1392,10 @@ static rpmRC addFile(FileList fl, const char * diskPath,
+ gid_t fileGid;
+ const char *fileUname;
+ const char *fileGname;
++ char realPath[PATH_MAX];
++ int digest_list_prefix = 0;
++ struct stat st;
++ int exclude = 0;
+ rpmRC rc = RPMRC_FAIL; /* assume failure */
+
+ /* Strip trailing slash. The special case of '/' path is handled below. */
+@@ -1390,6 +1431,33 @@ static rpmRC addFile(FileList fl, const char * diskPath,
+ if (*cpioPath == '\0')
+ cpioPath = "/";
+
++ snprintf(realPath, sizeof(realPath), "%s", diskPath);
++ rpmCleanPath(realPath);
++
++ digest_list_prefix = (!strncmp(realPath, digest_list_dir,
++ strlen(digest_list_dir)));
++
++ if ((!digest_list && digest_list_prefix) ||
++ (digest_list && !digest_list_prefix)) {
++ rc = RPMRC_OK;
++ goto exit;
++ }
++
++ if (digest_list) {
++ if (strncmp(cpioPath, DIGEST_LIST_DIR, sizeof(DIGEST_LIST_DIR) - 1)) {
++ rc = RPMRC_OK;
++ goto exit;
++ }
++
++ cpioPath += sizeof(DIGEST_LIST_DIR) - 1;
++
++ snprintf(realPath, sizeof(realPath), "%.*s%s",
++ (int)(strlen(digest_list_dir) - sizeof(DIGEST_LIST_DIR) + 1),
++ digest_list_dir, cpioPath);
++ if (!stat(realPath, &st))
++ exclude = 1;
++ }
++
+ /*
+ * Unless recursing, we dont have stat() info at hand. Handle the
+ * various cases, preserving historical behavior wrt %dev():
+@@ -1527,6 +1595,8 @@ static rpmRC addFile(FileList fl, const char * diskPath,
+ }
+
+ flp->flags = fl->cur.attrFlags;
++ if (exclude)
++ flp->flags |= RPMFILE_EXCLUDE;
+ flp->specdFlags = fl->cur.specdFlags;
+ flp->verifyFlags = fl->cur.verifyFlags;
+
+@@ -1547,6 +1617,32 @@ exit:
+ return rc;
+ }
+
++/**
++ * Add a file to the package manifest.
++ * @param fl package file tree walk data
++ * @param diskPath path to file
++ * @param statp file stat (possibly NULL)
++ * @return RPMRC_OK on success
++ */
++static rpmRC addFile(FileList fl, const char * diskPath,
++ struct stat * statp)
++{
++ return addFile_common(fl, diskPath, statp, 0);
++}
++
++/**
++ * Add a digest list to the package manifest.
++ * @param fl package file tree walk data
++ * @param diskPath path to digest list
++ * @param statp file stat (possibly NULL)
++ * @return RPMRC_OK on success
++ */
++static rpmRC addDigestList(FileList fl, const char * diskPath,
++ struct stat * statp)
++{
++ return addFile_common(fl, diskPath, statp, 1);
++}
++
+ /**
+ * Add directory (and all of its files) to the package manifest.
+ * @param fl package file tree walk data
+@@ -2556,6 +2652,58 @@ static void addPackageFileList (struct FileList_s *fl, Package pkg,
+ argvFree(fileNames);
+ }
+
++/**
++ * Generate digest lists list for current binary package.
++ * @header package header
++ * @fl file list
++ * @param fileList packaged file list
++ * @return -1 if skipped, 0 on OK, 1 on error
++ */
++static int genDigestList(Header header, FileList fl, StringBuf fileList)
++{
++ const char *errorString;
++ char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
++ char *binRpm = headerFormat(header, binFormat, &errorString);
++ static char * av_brp[] = { "%{?__brp_digest_list}", DIGEST_LIST_DIR + 1, NULL, NULL };
++ StringBuf sb_stdout = NULL;
++ int rc = -1;
++ char * s = rpmExpand(av_brp[0], NULL);
++
++ if (!(s && *s))
++ goto exit;
++
++ av_brp[2] = strchr(binRpm, '/') + 1;
++ rpmlog(RPMLOG_NOTICE, _("Generating digest list: %s\n"), s);
++
++ rc = rpmfcExec(av_brp, fileList, &sb_stdout, 0, binRpm);
++ if (sb_stdout && getStringBuf(sb_stdout)) {
++ const char * t = getStringBuf(sb_stdout), *ptr;
++ char *digest_list_path;
++
++ while((ptr = strchr(t, '\n'))) {
++ digest_list_path = strndup(t, ptr - t);
++ if (!digest_list_path) {
++ rc = -1;
++ goto exit;
++ }
++ FileEntryFree(&fl->cur);
++ resetPackageFilesDefaults(fl, fl->pkgFlags);
++ rc = addDigestList(fl, digest_list_path, NULL);
++ free(digest_list_path);
++ if (rc != RPMRC_OK)
++ break;
++
++ t = ptr + 1;
++ }
++ }
++exit:
++ free(binFormat);
++ free(binRpm);
++ free(s);
++ freeStringBuf(sb_stdout);
++ return rc;
++}
++
+ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
+ Package pkg, int didInstall, int test)
+ {
+@@ -2569,6 +2717,10 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
+ if (readFilesManifest(spec, pkg, *fp))
+ return RPMRC_FAIL;
+ }
++
++ /* Init the buffer containing the list of packaged files */
++ check_fileList_bin_pkg = newStringBuf();
++
+ /* Init the file list structure */
+ memset(&fl, 0, sizeof(fl));
+
+@@ -2630,6 +2782,7 @@ exit:
+ FileListFree(&fl);
+ specialDirFree(specialDoc);
+ specialDirFree(specialLic);
++ freeStringBuf(check_fileList_bin_pkg);
+ return fl.processingFailed ? RPMRC_FAIL : RPMRC_OK;
+ }
+
+@@ -3092,6 +3245,7 @@ static void addPackageDeps(Package from, Package to, enum rpmTag_e tag)
+ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
+ int didInstall, int test)
+ {
++ struct stat st;
+ Package pkg;
+ rpmRC rc = RPMRC_OK;
+ char *buildroot;
+@@ -3108,7 +3262,14 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
+ check_fileList = newStringBuf();
+ genSourceRpmName(spec);
+ buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL);
+-
++
++ digest_list_dir = rpmGenPath(buildroot, DIGEST_LIST_DIR, NULL);
++ if (!digest_list_dir)
++ goto exit;
++
++ if (!stat(digest_list_dir, &st))
++ rpmlog(RPMLOG_NOTICE, _("Ignoring files in: %s\n"), digest_list_dir);
++
+ if (rpmExpandNumeric("%{?_debuginfo_subpackages}")) {
+ maindbg = findDebuginfoPackage(spec);
+ if (maindbg) {
+@@ -3214,6 +3375,7 @@ exit:
+ check_fileList = freeStringBuf(check_fileList);
+ _free(buildroot);
+ _free(uniquearch);
+-
++ _free(digest_list_dir);
++
+ return rc;
+ }
+--
+2.27.GIT
+
diff --git a/Remove-digest-list-from-the-kernel-during-package-re.patch b/Remove-digest-list-from-the-kernel-during-package-re.patch
new file mode 100644
index 0000000..2bd6caa
--- /dev/null
+++ b/Remove-digest-list-from-the-kernel-during-package-re.patch
@@ -0,0 +1,106 @@
+From 0f088c5c9efa8ab877455bc273d7e536c763f824 Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Thu, 11 Mar 2021 11:59:45 +0100
+Subject: [PATCH] Remove digest list from the kernel during package
+ reinstallation
+
+Signed-off-by: luhuaxin <luhuaxin1@huawei.com>
+---
+ plugins/digest_list.c | 36 +++++++++++++++++-------------------
+ 1 file changed, 17 insertions(+), 19 deletions(-)
+
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+index ca77282..63f8f1c 100644
+--- a/plugins/digest_list.c
++++ b/plugins/digest_list.c
+@@ -27,9 +27,6 @@
+ #define DIGEST_LIST_DEFAULT_PATH "/etc/ima/digest_lists"
+ #define RPM_PARSER "/usr/libexec/rpm_parser"
+
+-#define DIGEST_LIST_OP_ADD 0
+-#define DIGEST_LIST_OP_DEL 1
+-
+ enum hash_algo {
+ HASH_ALGO_MD4,
+ HASH_ALGO_MD5,
+@@ -372,12 +369,13 @@ out:
+ return ret;
+ }
+
+-static int process_digest_list(rpmte te, int parser)
++static int process_digest_list(rpmte te, int parser, int pre)
+ {
+ char *path = NULL, *path_sig = NULL;
+ int digest_list_signed = 0;
+ struct stat st;
+ ssize_t size;
++ int type = rpmteType(te);
+ struct __user_cap_header_struct cap_header_data;
+ cap_user_header_t cap_header = &cap_header_data;
+ struct __user_cap_data_struct cap_data_data;
+@@ -431,15 +429,7 @@ static int process_digest_list(rpmte te, int parser)
+
+ size = lgetxattr(path, XATTR_NAME_IMA, NULL, 0);
+
+- /* Don't upload again if digest list was already processed */
+- if ((rpmteType(te) == TR_ADDED && size > 0) ||
+- (rpmteType(te) == TR_REMOVED && size < 0)) {
+- rpmlog(RPMLOG_DEBUG, "digest_list: '%s' already processed, "
+- "nothing to do\n", path);
+- goto out;
+- }
+-
+- if (rpmteType(te) == TR_ADDED) {
++ if (type == TR_ADDED && !pre && size < 0) {
+ if (!digest_list_signed) {
+ /* Write RPM header to the disk */
+ ret = write_rpm_digest_list(te, path);
+@@ -472,12 +462,18 @@ static int process_digest_list(rpmte te, int parser)
+ ret = RPMRC_FAIL;
+ goto out;
+ }
++ } else if (type == TR_ADDED && pre) {
++ if (size < 0)
++ goto out;
++
++ /* rpm is overwriting the digest list, remove from the kernel */
++ type = TR_REMOVED;
+ }
+
+ /* Upload digest list to securityfs */
+- upload_digest_list(path, rpmteType(te), digest_list_signed);
++ upload_digest_list(path, type, digest_list_signed);
+
+- if (rpmteType(te) == TR_REMOVED) {
++ if (type == TR_REMOVED) {
+ if (!digest_list_signed) {
+ unlink(path);
+ goto out;
+@@ -552,8 +548,10 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
+ if (!pre && res != RPMRC_OK)
+ return res;
+
+- if ((pre && action != FA_ERASE) ||
+- (!pre && action != FA_CREATE))
++ if (!pre && rpmteType(cur_te) != TR_ADDED)
++ return RPMRC_OK;
++
++ if (pre && action == FA_SKIP)
+ return RPMRC_OK;
+
+ if (strncmp(path, DIGEST_LIST_DEFAULT_PATH,
+@@ -564,9 +562,9 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
+ if (!pre && --digest_list_counter)
+ return RPMRC_OK;
+
+- process_digest_list(cur_te, 0);
++ process_digest_list(cur_te, 0, pre);
+ if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
+- process_digest_list(cur_te, 1);
++ process_digest_list(cur_te, 1, pre);
+
+ return RPMRC_OK;
+ }
+--
+2.33.0
+
diff --git a/Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch b/Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch
new file mode 100644
index 0000000..920a285
--- /dev/null
+++ b/Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch
@@ -0,0 +1,38 @@
+From eee654b9652fb9387018f9653431a11401a354fd Mon Sep 17 00:00:00 2001
+From: openeuler-basic <shenyangyang4@huawei.com>
+Date: Thu, 9 Jan 2020 19:16:58 +0800
+Subject: [PATCH] Unbundle config site and add RPM LD FLAGS macro
+
+---
+ macros.in | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/macros.in b/macros.in
+index fe9803a..4027493 100644
+--- a/macros.in
++++ b/macros.in
+@@ -794,10 +794,11 @@ package or when debugging this package.\
+ RPM_SOURCE_DIR=\"%{u2p:%{_sourcedir}}\"\
+ RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\
+ RPM_OPT_FLAGS=\"%{optflags}\"\
++ RPM_LD_FLAGS=\"%{?build_ldflags}\"\
+ RPM_ARCH=\"%{_arch}\"\
+ RPM_OS=\"%{_os}\"\
+ RPM_BUILD_NCPUS=\"%{_smp_build_ncpus}\"\
+- export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS\
++ export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS RPM_OPT_FLAGS\
+ RPM_DOC_DIR=\"%{_docdir}\"\
+ export RPM_DOC_DIR\
+ RPM_PACKAGE_NAME=\"%{NAME}\"\
+@@ -813,6 +814,8 @@ package or when debugging this package.\
+ export CLASSPATH}\
+ PKG_CONFIG_PATH=\"${PKG_CONFIG_PATH}:%{_libdir}/pkgconfig:%{_datadir}/pkgconfig\"\
+ export PKG_CONFIG_PATH\
++ CONFIG_SITE=${CONFIG_SITE:-NONE}\
++ export CONFIG_SITE\
+ \
+ %[%{verbose}?"set -x":""]\
+ umask 022\
+--
+1.8.3.1
+
diff --git a/add-dist-to-release-by-default.patch b/add-dist-to-release-by-default.patch
new file mode 100644
index 0000000..36c8226
--- /dev/null
+++ b/add-dist-to-release-by-default.patch
@@ -0,0 +1,37 @@
+From af9a2347cd725a8dbb6045d7d3e9661d524af110 Mon Sep 17 00:00:00 2001
+From: openEuler Buildteam <buildteam@openeuler.org>
+Date: Wed, 4 Mar 2020 16:12:58 +0800
+Subject: [PATCH] add dist to release by default
+
+---
+ build/parsePreamble.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/build/parsePreamble.c b/build/parsePreamble.c
+index b0a17c8..cac899a 100644
+--- a/build/parsePreamble.c
++++ b/build/parsePreamble.c
+@@ -808,6 +808,11 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
+ case RPMTAG_VERSION:
+ case RPMTAG_RELEASE:
+ SINGLE_TOKEN_ONLY;
++ if (tag == RPMTAG_RELEASE) {
++ char *dist = rpmExpand("%{?dist}",NULL);
++ rasprintf(&field,"%s%s",field,dist);
++ free(dist);
++ }
+ if (rpmCharCheck(spec, field, ALLOWED_CHARS_VERREL))
+ goto exit;
+ headerPutString(pkg->header, tag, field);
+@@ -987,6 +992,8 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
+ }
+ rc = RPMRC_OK;
+ exit:
++ if (tag == RPMTAG_RELEASE)
++ free(field);
+ return rc;
+ }
+
+--
+1.8.3.1
+
diff --git a/backport-Actually-return-an-error-in-parseScript-if-parsing-f.patch b/backport-Actually-return-an-error-in-parseScript-if-parsing-f.patch
new file mode 100644
index 0000000..e6732d0
--- /dev/null
+++ b/backport-Actually-return-an-error-in-parseScript-if-parsing-f.patch
@@ -0,0 +1,48 @@
+From 911a4f253c7213a8570028a7dc2a20b045de8e9e Mon Sep 17 00:00:00 2001
+From: Fabian Vogt <fvogt@suse.de>
+Date: Mon, 26 Jun 2023 16:28:07 +0200
+Subject: [PATCH] Actually return an error in parseScript if parsing fails
+
+The return value is stored in the "res" variable which is set to the return
+value of parseLines early in the function. Past that point, any "goto exit;"
+caused the function to return success. This was introduced by 52ce88851abb
+("Port parseScript() to use parseLines(), no functional changes"). To fix it,
+reintroduce the nextPart variable.
+---
+ build/parseScript.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/build/parseScript.c b/build/parseScript.c
+index f8b693ac6..6f3dc2fe8 100644
+--- a/build/parseScript.c
++++ b/build/parseScript.c
+@@ -95,7 +95,7 @@ int parseScript(rpmSpec spec, int parsePart)
+ int index;
+ char * reqargs = NULL;
+
+- int res = PART_ERROR; /* assume failure */
++ int nextPart, res = PART_ERROR; /* assume failure */
+ int rc, argc;
+ int arg;
+ const char **argv = NULL;
+@@ -367,7 +367,7 @@ int parseScript(rpmSpec spec, int parsePart)
+ goto exit;
+ }
+
+- if ((res = parseLines(spec, STRIP_NOTHING, NULL, &sb)) == PART_ERROR)
++ if ((nextPart = parseLines(spec, STRIP_NOTHING, NULL, &sb)) == PART_ERROR)
+ goto exit;
+
+ if (sb) {
+@@ -479,6 +479,8 @@ int parseScript(rpmSpec spec, int parsePart)
+ }
+ }
+
++ res = nextPart;
++
+ exit:
+ free(reqargs);
+ freeStringBuf(sb);
+--
+2.27.0
+
diff --git a/backport-Add-a-hashed-flag-to-pgpPrtSubtype.patch b/backport-Add-a-hashed-flag-to-pgpPrtSubtype.patch
new file mode 100644
index 0000000..6912082
--- /dev/null
+++ b/backport-Add-a-hashed-flag-to-pgpPrtSubtype.patch
@@ -0,0 +1,55 @@
+From 55849d2d6e16096dbd30fd3a5c751f13bb03484b Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Sun, 27 Mar 2022 12:04:46 -0400
+Subject: [PATCH] Add a hashed flag to pgpPrtSubtype()
+
+This is needed for key usage flags parsing, as key usage flags outside
+of the hashed region must be ignored. For now, just use it to
+unconditionally ignore unhashed creation time subpackets.
+---
+ rpmio/rpmpgp.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 59c80d7..9b8503e 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -437,7 +437,7 @@ int pgpSignatureType(pgpDigParams _digp)
+ }
+
+ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
+- pgpDigParams _digp)
++ pgpDigParams _digp, int hashed)
+ {
+ const uint8_t *p = h;
+ size_t plen = 0, i;
+@@ -474,6 +474,8 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
+ pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
+ break;
+ case PGPSUBTYPE_SIG_CREATE_TIME: /* signature creation time */
++ if (!hashed)
++ break; /* RFC 4880 §5.2.3.4 creation time MUST be hashed */
+ if (plen-1 != sizeof(_digp->time))
+ break; /* other lengths not understood */
+ if (_digp->saved & PGPDIG_SIG_HAS_CREATION_TIME)
+@@ -666,7 +668,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ _digp->hashlen = sizeof(*v) + plen;
+ _digp->hash = memcpy(xmalloc(_digp->hashlen), v, _digp->hashlen);
+ }
+- if (pgpPrtSubType(p, plen, v->sigtype, _digp))
++ if (pgpPrtSubType(p, plen, v->sigtype, _digp, 1))
+ return 1;
+ p += plen;
+
+@@ -680,7 +682,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ if ((p + plen) > hend)
+ return 1;
+
+- if (pgpPrtSubType(p, plen, v->sigtype, _digp))
++ if (pgpPrtSubType(p, plen, v->sigtype, _digp, 0))
+ return 1;
+ p += plen;
+
+--
+1.8.3.1
+
diff --git a/backport-Add-a-test-for-special-device-node-installation.patch b/backport-Add-a-test-for-special-device-node-installation.patch
new file mode 100644
index 0000000..8fd8ff9
--- /dev/null
+++ b/backport-Add-a-test-for-special-device-node-installation.patch
@@ -0,0 +1,79 @@
+From 5dcc399cd21f607f13eb092a3abfc8b8daa59d4c Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 13 Jan 2023 10:44:28 +0200
+Subject: [PATCH] Add a test for special device node installation
+
+This is a bit theoretical as it does not work for regular users or in
+containers which are the typical scenarios for running the test-suite.
+---
+ tests/atlocal.in | 6 ++++++
+ tests/data/SPECS/dev.spec | 14 ++++++++++++++
+ tests/rpmi.at | 17 +++++++++++++++++
+ 3 files changed, 37 insertions(+)
+ create mode 100644 tests/data/SPECS/dev.spec
+
+diff --git a/tests/atlocal.in b/tests/atlocal.in
+index c3189d3..1fb08d4 100644
+--- a/tests/atlocal.in
++++ b/tests/atlocal.in
+@@ -49,6 +49,12 @@ if grep -q '#define WITH_CAP 1' "${abs_top_builddir}/config.h"; then
+ else
+ CAP_DISABLED=true;
+ fi
++if mknod foodev c 123 123; then
++ MKNOD_DISABLED=false
++ rm -f foodev
++else
++ MKNOD_DISABLED=true
++fi
+
+ function setup_env()
+ {
+diff --git a/tests/data/SPECS/dev.spec b/tests/data/SPECS/dev.spec
+new file mode 100644
+index 000000000..d784fe114
+--- /dev/null
++++ b/tests/data/SPECS/dev.spec
+@@ -0,0 +1,14 @@
++Name: dev
++Version: 1.0
++Release: 1
++Group: Testing
++License: GPL
++Summary: Testing dev behavior
++BuildArch: noarch
++
++%description
++%{summary}
++
++%files
++%dev(c 11 22) /test-char
++%dev(b 33 44) /test-block
+diff --git a/tests/rpmi.at b/tests/rpmi.at
+index a2389de..f439e46 100644
+--- a/tests/rpmi.at
++++ b/tests/rpmi.at
+@@ -888,3 +888,20 @@ runroot rpm -Vv --nouser --nogroup fifo
+ ],
+ [])
+ AT_CLEANUP
++
++AT_SETUP([rpm -U dev])
++AT_KEYWORDS([install])
++AT_SKIP_IF([$MKNOD_DISABLED])
++AT_CHECK([
++RPMDB_INIT
++
++runroot rpmbuild -bb --quiet /data/SPECS/dev.spec
++runroot rpm -U --ignoreos /build/RPMS/noarch/dev-1.0-1.noarch.rpm
++runroot rpm -Vv --nouser --nogroup dev
++],
++[0],
++[......... /test-block
++......... /test-char
++],
++[])
++AT_CLEANUP
+--
+2.27.0
+
diff --git a/backport-Add-optional-callback-on-directory-changes-during-rp.patch b/backport-Add-optional-callback-on-directory-changes-during-rp.patch
new file mode 100644
index 0000000..53765d4
--- /dev/null
+++ b/backport-Add-optional-callback-on-directory-changes-during-rp.patch
@@ -0,0 +1,105 @@
+From fb13f7fd9eff012cb7b9dbf94ac5381c69404055 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 9 Feb 2022 14:47:14 +0200
+Subject: [PATCH] Add optional callback on directory changes during rpmfi
+ iteration
+
+Internal only for now in case we need to fiddle with the API some more,
+but no reason this couldn't be made public later.
+---
+ lib/rpmfi.c | 24 +++++++++++++++++++++++-
+ lib/rpmfi_internal.h | 17 +++++++++++++++++
+ 2 files changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/lib/rpmfi.c b/lib/rpmfi.c
+index 4673fbb..e8e7d08 100644
+--- a/lib/rpmfi.c
++++ b/lib/rpmfi.c
+@@ -55,6 +55,9 @@ struct rpmfi_s {
+ int intervalStart; /*!< Start of iterating interval. */
+ int intervalEnd; /*!< End of iterating interval. */
+
++ rpmfiChdirCb onChdir; /*!< Callback for directory changes */
++ void *onChdirData; /*!< Caller private callback data */
++
+ rpmfiles files; /*!< File info set */
+ rpmcpio_t archive; /*!< Archive with payload */
+ unsigned char * found; /*!< Bit field of files found in the archive */
+@@ -312,6 +312,17 @@ int rpmfiDI(rpmfi fi)
+ }
+ #endif
+
++int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data)
++{
++ int rc = -1;
++ if (fi != NULL) {
++ fi->onChdir = cb;
++ fi->onChdirData = data;
++ rc = 0;
++ }
++ return rc;
++}
++
+ int rpmfiFX(rpmfi fi)
+ {
+ return (fi != NULL ? fi->i : -1);
+@@ -313,9 +327,17 @@ int rpmfiSetFX(rpmfi fi, int fx)
+ int i = -1;
+
+ if (fi != NULL && fx >= 0 && fx < rpmfilesFC(fi->files)) {
++ int dx = fi->j;
++ i = fi->i;
+ fi->i = fx;
+ fi->j = rpmfilesDI(fi->files, fi->i);
+ i = fi->i;
++
++ if (fi->j != dx && fi->onChdir) {
++ int chrc = fi->onChdir(fi, fi->onChdirData);
++ if (chrc < 0)
++ i = chrc;
++ }
+ }
+ return i;
+ }
+@@ -1780,9 +1802,9 @@ static rpmfi initIter(rpmfiles files, int itype, int link)
+ if (files && itype>=0 && itype<=RPMFILEITERMAX) {
+ fi = xcalloc(1, sizeof(*fi));
+ fi->i = -1;
++ fi->j = -1;
+ fi->files = link ? rpmfilesLink(files) : files;
+ fi->next = nextfuncs[itype];
+- fi->i = -1;
+ if (itype == RPMFI_ITER_BACK) {
+ fi->i = rpmfilesFC(fi->files);
+ } else if (itype >=RPMFI_ITER_READ_ARCHIVE
+diff --git a/lib/rpmfi_internal.h b/lib/rpmfi_internal.h
+index dccc6ccb..37f1d45 100644
+--- a/lib/rpmfi_internal.h
++++ b/lib/rpmfi_internal.h
+@@ -14,6 +14,23 @@ extern "C" {
+ #endif
+
+ /** \ingroup rpmfi
++ * Callback on file iterator directory changes
++ * @param fi file info
++ * @param data caller private callback data
++ * @return 0 on success, < 0 on error (to stop iteration)
++ */
++typedef int (*rpmfiChdirCb)(rpmfi fi, void *data);
++
++/** \ingroup rpmfi
++ * Set a callback for directory changes during iteration.
++ * @param fi file info
++ * @param cb callback function
++ * @param data caller private callback data
++ * @return string pool handle (weak reference)
++ */
++int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data);
++
++/** \ingroup rpmfi
+ * Return file info set string pool handle
+ * @param fi file info
+ * @return string pool handle (weak reference)
+--
+1.8.3.1
+
diff --git a/backport-Avoid-double-frees-if-EVP_PKEY_assign_RSA-fails.patch b/backport-Avoid-double-frees-if-EVP_PKEY_assign_RSA-fails.patch
new file mode 100644
index 0000000..7b63d29
--- /dev/null
+++ b/backport-Avoid-double-frees-if-EVP_PKEY_assign_RSA-fails.patch
@@ -0,0 +1,95 @@
+From 0a91d1f62d5b6e1cac4d0a7c2ac9f75faad50534 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Fri, 9 Apr 2021 13:34:12 -0400
+Subject: [PATCH] Avoid double frees if EVP_PKEY_assign_RSA fails
+
+Previously, the bignums would be left as dangling and double-freed.
+---
+ rpmio/digest_openssl.c | 32 +++++++++++++++++---------------
+ 1 file changed, 17 insertions(+), 15 deletions(-)
+
+diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c
+index 20c272d..02f34a9 100644
+--- a/rpmio/digest_openssl.c
++++ b/rpmio/digest_openssl.c
+@@ -292,8 +292,8 @@ struct pgpDigKeyRSA_s {
+
+ BIGNUM *n; /* Common Modulus */
+ BIGNUM *e; /* Public Exponent */
+-
+ EVP_PKEY *evp_pkey; /* Fully constructed key */
++ unsigned char immutable; /* if set, this key cannot be mutated */
+ };
+
+ static int constructRSASigningKey(struct pgpDigKeyRSA_s *key)
+@@ -301,33 +301,34 @@ static int constructRSASigningKey(struct pgpDigKeyRSA_s *key)
+ if (key->evp_pkey) {
+ /* We've already constructed it, so just reuse it */
+ return 1;
+- }
++ } else if (key->immutable)
++ return 0;
++ key->immutable = 1;
+
+ /* Create the RSA key */
+ RSA *rsa = RSA_new();
+ if (!rsa) return 0;
+
+- if (!RSA_set0_key(rsa, key->n, key->e, NULL)) {
+- RSA_free(rsa);
+- return 0;
+- }
++ if (RSA_set0_key(rsa, key->n, key->e, NULL) <= 0)
++ goto exit;
++ key->n = key->e = NULL;
+
+ /* Create an EVP_PKEY container to abstract the key-type. */
+- key->evp_pkey = EVP_PKEY_new();
+- if (!key->evp_pkey) {
+- RSA_free(rsa);
+- return 0;
+- }
++ if (!(key->evp_pkey = EVP_PKEY_new()))
++ goto exit;
+
+ /* Assign the RSA key to the EVP_PKEY structure.
+ This will take over memory management of the RSA key */
+ if (!EVP_PKEY_assign_RSA(key->evp_pkey, rsa)) {
+ EVP_PKEY_free(key->evp_pkey);
+ key->evp_pkey = NULL;
+- RSA_free(rsa);
++ goto exit;
+ }
+
+ return 1;
++exit:
++ RSA_free(rsa);
++ return 0;
+ }
+
+ static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
+@@ -335,9 +336,10 @@ static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
+ size_t mlen = pgpMpiLen(p) - 2;
+ struct pgpDigKeyRSA_s *key = pgpkey->data;
+
+- if (!key) {
++ if (!key)
+ key = pgpkey->data = xcalloc(1, sizeof(*key));
+- }
++ else if (key->immutable)
++ return 1;
+
+ switch (num) {
+ case 0:
+@@ -347,7 +349,7 @@ static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
+ return 1;
+ }
+
+- key->nbytes = mlen;
++ key->nbytes = mlen;
+ /* Create a BIGNUM from the pointer.
+ Note: this assumes big-endian data as required by PGP */
+ key->n = BN_bin2bn(p+2, mlen, NULL);
+--
+1.8.3.1
+
diff --git a/backport-Avoid-reading-out-of-bounds-of-the-i18ntable.patch b/backport-Avoid-reading-out-of-bounds-of-the-i18ntable.patch
new file mode 100644
index 0000000..d237fa5
--- /dev/null
+++ b/backport-Avoid-reading-out-of-bounds-of-the-i18ntable.patch
@@ -0,0 +1,29 @@
+From db8fc1057e38839adc04e263fe255ce86cab9fa7 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Sat, 12 Feb 2022 13:46:28 -0500
+Subject: [PATCH] Avoid reading out of bounds of the i18ntable
+
+If the i18ntable was smaller than the i18nstring entry an out of bounds
+read could result. This should not happen in a valid package, but even
+if RPM rejected such packages during load, this situation could still
+result as a result of usage of the RPM API.
+---
+ lib/header.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/header.c b/lib/header.c
+index 098ea5d..c939006 100644
+--- a/lib/header.c
++++ b/lib/header.c
+@@ -1311,7 +1311,7 @@ static int copyI18NEntry(Header h, indexEntry entry, rpmtd td,
+
+ /* For each entry in the header ... */
+ for (langNum = 0, t = table->data, ed = entry->data;
+- langNum < entry->info.count;
++ langNum < entry->info.count && langNum < table->info.count;
+ langNum++, t += strlen(t) + 1, ed += strlen(ed) + 1) {
+
+ int match = headerMatchLocale(t, l, le);
+--
+1.8.3.1
+
diff --git a/backport-Avoid-unneded-MPI-reparsing.patch b/backport-Avoid-unneded-MPI-reparsing.patch
new file mode 100644
index 0000000..a3bf260
--- /dev/null
+++ b/backport-Avoid-unneded-MPI-reparsing.patch
@@ -0,0 +1,39 @@
+From 8948ec79f6c300e91319469ba72b9bd3480fe686 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Sun, 27 Mar 2022 12:54:36 -0400
+Subject: [PATCH] Avoid unneded MPI reparsing
+
+Modify pgpPrtSig() to ignore the MPIs of a signature if its `tag`
+parameter is 0. The only caller that sets `tag` to 0 is
+pgpPrtParamSubkeys() (via parseSubkeySig()), which does not actually
+check any cryptographic signatures. The subkey binding signature has
+been checked earlier in pgpPrtParams().
+---
+ rpmio/rpmpgp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 22ac9c8..2b93661 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -637,7 +637,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+
+ p = ((uint8_t *)v) + sizeof(*v);
+ _digp->data = p;
+- rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
++ rc = tag ? pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp) : 0;
+ } break;
+ case 4:
+ { pgpPktSigV4 v = (pgpPktSigV4)h;
+@@ -700,7 +700,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ return 1;
+
+ _digp->data = p;
+- rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
++ rc = tag ? pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp) : 0;
+ } break;
+ default:
+ rpmlog(RPMLOG_WARNING, _("Unsupported version of signature: V%d\n"), version);
+--
+1.8.3.1
+
diff --git a/backport-Bury-rpmio-FD-use-to-fsmUnpack.patch b/backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
new file mode 100644
index 0000000..c735909
--- /dev/null
+++ b/backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
@@ -0,0 +1,129 @@
+From bbc270d78fb361bd78eac9a9117070caeb537d4a Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 14 Feb 2022 12:35:58 +0200
+Subject: [PATCH] Bury rpmio FD use to fsmUnpack()
+
+fsmUnpack() is the only place in FSM that needs to deal with rpmio FD
+types, everywhere else they are nothing but a hindrance that need to
+be converted to OS level descriptors for use. Better deal with OS
+level descriptors to begin with.
+---
+ lib/fsm.c | 37 ++++++++++++++++---------------------
+ 1 file changed, 16 insertions(+), 21 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index 13b1142..b019f57 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -110,14 +110,14 @@ static int fsmSetFCaps(const char *path, const char *captxt)
+ return rc;
+ }
+
+-static int fsmClose(FD_t *wfdp)
++static int fsmClose(int *wfdp)
+ {
+ int rc = 0;
+- if (wfdp && *wfdp) {
++ if (wfdp && *wfdp >= 0) {
+ int myerrno = errno;
+ static int oneshot = 0;
+ static int flush_io = 0;
+- int fdno = Fileno(*wfdp);
++ int fdno = *wfdp;
+
+ if (!oneshot) {
+ flush_io = (rpmExpandNumeric("%{?_flush_io}") > 0);
+@@ -126,61 +126,56 @@ static int fsmClose(FD_t *wfdp)
+ if (flush_io) {
+ fsync(fdno);
+ }
+- if (Fclose(*wfdp))
++ if (close(fdno))
+ rc = RPMERR_CLOSE_FAILED;
+
+ if (_fsm_debug) {
+ rpmlog(RPMLOG_DEBUG, " %8s ([%d]) %s\n", __func__,
+ fdno, (rc < 0 ? strerror(errno) : ""));
+ }
+- *wfdp = NULL;
++ *wfdp = -1;
+ errno = myerrno;
+ }
+ return rc;
+ }
+
+-static int fsmOpen(FD_t *wfdp, int dirfd, const char *dest)
++static int fsmOpen(int *wfdp, int dirfd, const char *dest)
+ {
+ int rc = 0;
+ /* Create the file with 0200 permissions (write by owner). */
+ int fd = openat(dirfd, dest, O_WRONLY|O_EXCL|O_CREAT, 0200);
+
+- if (fd >= 0) {
+- *wfdp = fdDup(fd);
+- close(fd);
+- }
+-
+- if (fd < 0 || Ferror(*wfdp))
++ if (fd < 0)
+ rc = RPMERR_OPEN_FAILED;
+
+ if (_fsm_debug) {
+ rpmlog(RPMLOG_DEBUG, " %8s (%s [%d]) %s\n", __func__,
+- dest, Fileno(*wfdp), (rc < 0 ? strerror(errno) : ""));
++ dest, fd, (rc < 0 ? strerror(errno) : ""));
+ }
+-
+- if (rc)
+- fsmClose(wfdp);
++ *wfdp = fd;
+
+ return rc;
+ }
+
+-static int fsmUnpack(rpmfi fi, FD_t fd, rpmpsm psm, int nodigest)
++static int fsmUnpack(rpmfi fi, int fdno, rpmpsm psm, int nodigest)
+ {
++ FD_t fd = fdDup(fdno);
+ int rc = rpmfiArchiveReadToFilePsm(fi, fd, nodigest, psm);
+ if (_fsm_debug) {
+ rpmlog(RPMLOG_DEBUG, " %8s (%s %" PRIu64 " bytes [%d]) %s\n", __func__,
+ rpmfiFN(fi), rpmfiFSize(fi), Fileno(fd),
+ (rc < 0 ? strerror(errno) : ""));
+ }
++ Fclose(fd);
+ return rc;
+ }
+
+ static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ rpmpsm psm, int nodigest,
+- struct filedata_s ** firstlink, FD_t *firstlinkfile)
++ struct filedata_s ** firstlink, int *firstlinkfile)
+ {
+ int rc = 0;
+- FD_t fd = NULL;
++ int fd = -1;
+
+ if (*firstlink == NULL) {
+ /* First encounter, open file for writing */
+@@ -206,7 +201,7 @@ static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ if (*firstlink) {
+ fp->setmeta = 1;
+ *firstlink = NULL;
+- *firstlinkfile = NULL;
++ *firstlinkfile = -1;
+ }
+ }
+
+@@ -811,7 +806,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ int fc = rpmfilesFC(files);
+ int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
+ int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
+- FD_t firstlinkfile = NULL;
++ int firstlinkfile = -1;
+ char *tid = NULL;
+ struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
+ struct filedata_s *firstlink = NULL;
+--
+1.8.3.1
+
diff --git a/backport-CVE-2021-35937-CVE-2021-35939.patch b/backport-CVE-2021-35937-CVE-2021-35939.patch
new file mode 100644
index 0000000..b5f994a
--- /dev/null
+++ b/backport-CVE-2021-35937-CVE-2021-35939.patch
@@ -0,0 +1,281 @@
+From 96ec957e281220f8e137a2d5eb23b83a6377d556 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 10 Feb 2022 14:32:43 +0200
+Subject: [PATCH] Validate intermediate symlinks during installation,
+ CVE-2021-35939
+
+Whenever directory changes during unpacking, walk the entire tree from
+starting from / and validate any symlinks crossed, fail the install
+on invalid links.
+
+This is the first of step of many towards securing our file operations
+against local tamperers and besides plugging that one CVE, paves the way
+for the next step by adding the necessary directory fd tracking.
+This also bumps the rpm OS requirements to a whole new level by requiring
+the *at() family of calls from POSIX-1.2008.
+
+This necessarily does a whole lot of huffing and puffing we previously
+did not do. It should be possible to cache secure (ie root-owned)
+directory structures to avoid validating everything a million times
+but for now, just keeping things simple.
+---
+ INSTALL | 2 +
+ configure.ac | 3 +-
+ lib/fsm.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
+ 3 files changed, 142 insertions(+), 7 deletions(-)
+
+diff --git a/INSTALL b/INSTALL
+index 677ef88..961a160 100644
+--- a/INSTALL
++++ b/INSTALL
+@@ -103,6 +103,8 @@ option to configure). For GCC, OpenMP 4.5 is fully supported since GCC 6.1,
+ which is available from
+ http://www.gnu.org/
+
++Rpm requires a POSIX.1-2008 level operating system.
++
+ To compile RPM:
+ --------------
+
+diff --git a/configure.ac b/configure.ac
+index 3ee3407..0099e5f 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -580,7 +580,8 @@ AC_CHECK_FUNCS([secure_getenv __secure_getenv])
+
+ AC_CHECK_FUNCS(
+ [mkstemp getcwd basename dirname realpath setenv unsetenv regcomp lchown \
+- utimes getline localtime_r statvfs getaddrinfo ],
++ utimes getline localtime_r statvfs getaddrinfo \
++ openat mkdirat fstatat ],
+ [], [AC_MSG_ERROR([function required by rpm])])
+
+ AC_LIBOBJ(fnmatch)
+diff --git a/lib/fsm.c b/lib/fsm.c
+index 9118983..b6b152a 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -8,6 +8,7 @@
+ #include <inttypes.h>
+ #include <utime.h>
+ #include <errno.h>
++#include <fcntl.h>
+ #if WITH_CAP
+ #include <sys/capability.h>
+ #endif
+@@ -20,6 +21,7 @@
+ #include "rpmio/rpmio_internal.h" /* fdInit/FiniDigest */
+ #include "lib/fsm.h"
+ #include "lib/rpmte_internal.h" /* XXX rpmfs */
++#include "lib/rpmfi_internal.h" /* rpmfiSetOnChdir */
+ #include "lib/rpmplugins.h" /* rpm plugins hooks */
+ #include "lib/rpmug.h"
+
+@@ -406,17 +408,118 @@ static int fsmRmdir(const char *path)
+ return rc;
+ }
+
+-static int fsmMkdir(const char *path, mode_t mode)
++static int fsmMkdir(int dirfd, const char *path, mode_t mode)
+ {
+- int rc = mkdir(path, (mode & 07777));
++ int rc = mkdirat(dirfd, path, (mode & 07777));
+ if (_fsm_debug)
+- rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", __func__,
+- path, (unsigned)(mode & 07777),
++ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%04o) %s\n", __func__,
++ dirfd, path, (unsigned)(mode & 07777),
+ (rc < 0 ? strerror(errno) : ""));
+ if (rc < 0) rc = RPMERR_MKDIR_FAILED;
+ return rc;
+ }
+
++static int fsmOpenat(int dirfd, const char *path, int flags)
++{
++ struct stat lsb, sb;
++ int sflags = flags | O_NOFOLLOW;
++ int fd = openat(dirfd, path, sflags);
++
++ /*
++ * Only ever follow symlinks by root or target owner. Since we can't
++ * open the symlink itself, the order matters: we stat the link *after*
++ * opening the target, and if the link ownership changed between the calls
++ * it could've only been the link owner or root.
++ */
++ if (fd < 0 && errno == ELOOP && flags != sflags) {
++ int ffd = openat(dirfd, path, flags);
++ if (ffd >= 0 && fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) {
++ if (fstat(ffd, &sb) == 0) {
++ if (lsb.st_uid == 0 || lsb.st_uid == sb.st_uid) {
++ fd = ffd;
++ } else {
++ close(ffd);
++ }
++ }
++ }
++ }
++ return fd;
++}
++
++static int fsmDoMkDir(rpmPlugins plugins, int dirfd, const char *dn,
++ int owned, mode_t mode)
++{
++ int rc;
++ rpmFsmOp op = (FA_CREATE);
++ if (!owned)
++ op |= FAF_UNOWNED;
++
++ /* Run fsm file pre hook for all plugins */
++ rc = rpmpluginsCallFsmFilePre(plugins, NULL, dn, mode, op);
++
++ if (!rc)
++ rc = fsmMkdir(dirfd, dn, mode);
++
++ if (!rc) {
++ rc = rpmpluginsCallFsmFilePrepare(plugins, NULL, dn, dn, mode, op);
++ }
++
++ /* Run fsm file post hook for all plugins */
++ rpmpluginsCallFsmFilePost(plugins, NULL, dn, mode, op, rc);
++
++ if (!rc) {
++ rpmlog(RPMLOG_DEBUG,
++ "%s directory created with perms %04o\n",
++ dn, (unsigned)(mode & 07777));
++ }
++
++ return rc;
++}
++
++static int ensureDir(rpmPlugins plugins, const char *p, int owned, int create)
++{
++ char *path = xstrdup(p);
++ char *dp = path;
++ char *sp = NULL, *bn;
++ int oflags = O_RDONLY;
++
++ int dirfd = fsmOpenat(-1, "/", oflags);
++ int fd = dirfd; /* special case of "/" */
++
++ while ((bn = strtok_r(dp, "/", &sp)) != NULL) {
++ struct stat sb;
++ fd = fsmOpenat(dirfd, bn, oflags);
++
++ if (fd < 0 && errno == ENOENT && create) {
++ mode_t mode = S_IFDIR | (_dirPerms & 07777);
++ if (fsmDoMkDir(plugins, dirfd, bn, owned, mode) == 0) {
++ fd = fsmOpenat(dirfd, bn, oflags|O_NOFOLLOW);
++ }
++ }
++
++ if (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
++ close(fd);
++ errno = ENOTDIR;
++ fd = -1;
++ }
++
++ close(dirfd);
++ if (fd >= 0) {
++ dirfd = fd;
++ } else {
++ dirfd = -1;
++ rpmlog(RPMLOG_ERR, _("failed to open dir %s of %s: %s\n"),
++ bn, p, strerror(errno));
++ break;
++ }
++
++ dp = NULL;
++ }
++
++ free(path);
++ return dirfd;
++}
++
+ static int fsmMkfifo(const char *path, mode_t mode)
+ {
+ int rc = mkfifo(path, (mode & 07777));
+@@ -507,7 +610,7 @@ static int fsmMkdirs(rpmfiles files, rpmfs fs, rpmPlugins plugins)
+ rc = rpmpluginsCallFsmFilePre(plugins, NULL, dn, mode, op);
+
+ if (!rc)
+- rc = fsmMkdir(dn, mode);
++ rc = fsmMkdir(-1, dn, mode);
+
+ if (!rc) {
+ rc = rpmpluginsCallFsmFilePrepare(plugins, NULL, dn, dn,
+@@ -874,6 +977,21 @@ static void setFileState(rpmfs fs, int i)
+ }
+ }
+
++struct diriter_s {
++ int dirfd;
++};
++
++static int onChdir(rpmfi fi, void *data)
++{
++ struct diriter_s *di = data;
++
++ if (di->dirfd >= 0) {
++ close(di->dirfd);
++ di->dirfd = -1;
++ }
++ return 0;
++}
++
+ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ rpmpsm psm, char ** failedFile)
+ {
+@@ -890,6 +1008,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ char *tid = NULL;
+ struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
+ struct filedata_s *firstlink = NULL;
++ struct diriter_s di = { -1 };
+
+ /* transaction id used for temporary path suffix while installing */
+ rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
+@@ -932,6 +1051,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ rc = RPMERR_BAD_MAGIC;
+ goto exit;
+ }
++ rpmfiSetOnChdir(fi, onChdir, &di);
+
+ /* Detect and create directories not explicitly in package. */
+ if (!rc)
+@@ -1063,6 +1063,16 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ if (!fp->suffix) {
+ rc = fsmBackup(fi, fp->action);
+ }
++
++ if (di.dirfd == -1) {
++ di.dirfd = ensureDir(plugins, rpmfiDN(fi), 0,
++ (fp->action == FA_CREATE));
++ if (di.dirfd == -1) {
++ rc = RPMERR_OPEN_FAILED;
++ break;
++ }
++ }
++
+ /* Assume file does't exist when tmp suffix is in use */
+ if (!fp->suffix) {
+ rc = fsmVerify(fp->fpath, fi);
+@@ -980,7 +1110,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ mode_t mode = fp->sb.st_mode;
+ mode &= ~07777;
+ mode |= 00700;
+- rc = fsmMkdir(fp->fpath, mode);
++ rc = fsmMkdir(di.dirfd, fp->fpath, mode);
+ }
+ } else if (S_ISLNK(fp->sb.st_mode)) {
+ if (rc == RPMERR_ENOENT) {
+@@ -1022,6 +1152,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ fp->stage = FILE_UNPACK;
+ }
+ fi = rpmfiFree(fi);
++ close(di.dirfd);
++ di.dirfd = -1;
+
+ if (!rc && fx < 0 && fx != RPMERR_ITER_END)
+ rc = fx;
+--
+1.8.3.1
+
diff --git a/backport-CVE-2021-35938.patch b/backport-CVE-2021-35938.patch
new file mode 100644
index 0000000..4e5b3d4
--- /dev/null
+++ b/backport-CVE-2021-35938.patch
@@ -0,0 +1,40 @@
+From 25a435e90844ea98fe5eb7bef22c1aecf3a9c033 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 14 Feb 2022 14:29:33 +0200
+Subject: [PATCH] Set file metadata via fd-based ops for everything but
+ symlinks
+
+Regular file ops are fd-based already, for the rest we need to open them
+manually. Files with temporary suffix must never be followed, for
+directories (and pre-existing FA_TOUCHed files) use the rpm symlink
+"root or target owner allowed" rule wrt following.
+
+This mostly fixes CVE-2021-35938, but as we're not yet using dirfd-based
+operatiosn for everything there are corner cases left undone. And then
+there's the plugin API which needs updating for all this.
+---
+ lib/fsm.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index 913e9de..6f781c6 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -1133,6 +1133,14 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ rc = RPMERR_UNKNOWN_FILETYPE;
+ }
+
++ if (!rc && fd == -1 && !S_ISLNK(fp->sb.st_mode)) {
++ /* Only follow safe symlinks, and never on temporary files */
++ fd = fsmOpenat(di.dirfd, fp->fpath,
++ fp->suffix ? AT_SYMLINK_NOFOLLOW : 0);
++ if (fd < 0)
++ rc = RPMERR_OPEN_FAILED;
++ }
++
+ if (fd != firstlinkfile)
+ fsmClose(&fd);
+ }
+--
+1.8.3.1
+
diff --git a/backport-Check-file-iterator-for-being-NULL-consistently.patch b/backport-Check-file-iterator-for-being-NULL-consistently.patch
new file mode 100644
index 0000000..ecc32bb
--- /dev/null
+++ b/backport-Check-file-iterator-for-being-NULL-consistently.patch
@@ -0,0 +1,67 @@
+From 470498bd5a51f8d98ae8e721beea58ef81c19a51 Mon Sep 17 00:00:00 2001
+From: Florian Festi <ffesti@redhat.com>
+Date: Wed, 22 Sep 2021 16:10:53 +0200
+Subject: [PATCH] Check file iterator for being NULL consistently
+
+No point in allowing NULL only for one of the arguments.
+
+Thanks to ex0z3 (https://github.com/ex0z3) for reporting!
+
+Resolves: #1782
+---
+ lib/rpmfi.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/lib/rpmfi.c b/lib/rpmfi.c
+index c6c9699..b67680c 100644
+--- a/lib/rpmfi.c
++++ b/lib/rpmfi.c
+@@ -735,7 +735,7 @@ uint32_t rpmfilesFLinks(rpmfiles fi, int ix, const int ** files)
+
+ uint32_t rpmfiFLinks(rpmfi fi, const int ** files)
+ {
+- return rpmfilesFLinks(fi->files, fi ? fi->i : -1, files);
++ return rpmfilesFLinks(fi ? fi->files : NULL, fi ? fi->i : -1, files);
+ }
+
+ uint32_t rpmfilesFNlink(rpmfiles fi, int ix)
+@@ -1948,22 +1948,22 @@ const char * rpmfiOFN(rpmfi fi)
+
+ const unsigned char * rpmfiFDigest(rpmfi fi, int *algo, size_t *len)
+ {
+- return rpmfilesFDigest(fi->files, fi ? fi->i : -1, algo, len);
++ return rpmfilesFDigest(fi ? fi->files : NULL, fi ? fi->i : -1, algo, len);
+ }
+
+ const unsigned char * rpmfiFSignature(rpmfi fi, size_t *len)
+ {
+- return rpmfilesFSignature(fi->files, fi ? fi->i : -1, len);
++ return rpmfilesFSignature(fi ? fi->files : NULL, fi ? fi->i : -1, len);
+ }
+
+ const unsigned char * rpmfiVSignature(rpmfi fi, size_t *len, uint16_t *algo)
+ {
+- return rpmfilesVSignature(fi->files, fi ? fi->i : -1, len, algo);
++ return rpmfilesVSignature(fi ? fi->files : NULL, fi ? fi->i : -1, len, algo);
+ }
+
+ uint32_t rpmfiFDepends(rpmfi fi, const uint32_t ** fddictp)
+ {
+- return rpmfilesFDepends(fi->files, fi ? fi->i : -1, fddictp);
++ return rpmfilesFDepends(fi ? fi->files : NULL, fi ? fi->i : -1, fddictp);
+ }
+
+ int rpmfiStat(rpmfi fi, int flags, struct stat *sb)
+@@ -1983,7 +1983,8 @@ int rpmfiStat(rpmfi fi, int flags, struct stat *sb)
+
+ int rpmfiCompare(const rpmfi afi, const rpmfi bfi)
+ {
+- return rpmfilesCompare(afi->files, afi ? afi->i : -1, bfi->files, bfi ? bfi->i : -1);
++ return rpmfilesCompare(afi ? afi->files : NULL, afi ? afi->i : -1,
++ bfi ? bfi->files : NULL, bfi ? bfi->i : -1);
+ }
+
+ rpmVerifyAttrs rpmfiVerify(rpmfi fi, rpmVerifyAttrs omitMask)
+--
+1.8.3.1
+
diff --git a/backport-Check-inside-root-when-querying-for-files.patch b/backport-Check-inside-root-when-querying-for-files.patch
new file mode 100644
index 0000000..3759486
--- /dev/null
+++ b/backport-Check-inside-root-when-querying-for-files.patch
@@ -0,0 +1,38 @@
+From 3e820eaa4c8cb94a63338366cbf014dc5264eba2 Mon Sep 17 00:00:00 2001
+From: Florian Festi <ffesti@redhat.com>
+Date: Tue, 25 Jul 2023 12:08:42 +0200
+Subject: [PATCH] Check inside --root when querying for files
+
+rpm -qf checks if the argument actually exists if it can't be found in
+the rpmdb and gives different messages based on that.
+
+This was done without taking the root dir into account leading to wrong
+messages if the file only exists in the root dir but not outside.
+
+Resolves: #2576
+---
+ lib/query.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/lib/query.c b/lib/query.c
+index e816241b7..dc2dc910b 100644
+--- a/lib/query.c
++++ b/lib/query.c
+@@ -470,11 +470,13 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
+
+ if (mi == NULL) {
+ struct stat sb;
+- if (lstat(fn, &sb) != 0)
++ char * full_fn = rpmGetPath(rpmtsRootDir(ts), fn, NULL);
++ if (lstat(full_fn, &sb) != 0)
+ rpmlog(RPMLOG_ERR, _("file %s: %s\n"), fn, strerror(errno));
+ else
+ rpmlog(RPMLOG_NOTICE,
+ _("file %s is not owned by any package\n"), fn);
++ free(full_fn);
+ }
+
+ free(fn);
+--
+2.27.0
+
diff --git a/backport-Check-that-the-CRC-length-is-correct.patch b/backport-Check-that-the-CRC-length-is-correct.patch
new file mode 100644
index 0000000..8506a45
--- /dev/null
+++ b/backport-Check-that-the-CRC-length-is-correct.patch
@@ -0,0 +1,27 @@
+From 1f03aba8b2881a5717af97065038fb056e02a2b3 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Thu, 3 Feb 2022 20:42:02 -0500
+Subject: [PATCH] Check that the CRC length is correct
+
+Also fix a memory leak in an error path.
+---
+ rpmio/rpmpgp.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 015c15a..d1966d3 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1444,7 +1444,8 @@ static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
+
+ crcdec = NULL;
+ crclen = 0;
+- if (rpmBase64Decode(crcenc, (void **)&crcdec, &crclen) != 0) {
++ if (rpmBase64Decode(crcenc, (void **)&crcdec, &crclen) != 0 || crclen != 3) {
++ crcdec = _free(crcdec);
+ ec = PGPARMOR_ERR_CRC_DECODE;
+ goto exit;
+ }
+--
+1.8.3.1
+
diff --git a/backport-Close-file-before-replacing-signed.patch b/backport-Close-file-before-replacing-signed.patch
new file mode 100644
index 0000000..33fd5a3
--- /dev/null
+++ b/backport-Close-file-before-replacing-signed.patch
@@ -0,0 +1,27 @@
+From 9b4c50dd67c337f2d3c927cdd01ae4433bb08b61 Mon Sep 17 00:00:00 2001
+From: Evgeniy Taishev <e.taishev@omp.ru>
+Date: Mon, 17 Jan 2022 22:07:13 +0300
+Subject: [PATCH] Close file before replacing signed
+
+---
+ sign/rpmgensig.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
+index e88f9b7..b8c68ce 100644
+--- a/sign/rpmgensig.c
++++ b/sign/rpmgensig.c
+@@ -695,6 +695,10 @@ static int rpmSign(const char *rpm, int deleting, int flags)
+ if (copyFile(&fd, rpm, &ofd, trpm) == 0) {
+ struct stat st;
+
++ /* File must be closed before deletion due to different file locking in some file systems*/
++ if (fd) (void) closeFile(&fd);
++ if (ofd) (void) closeFile(&ofd);
++
+ /* Move final target into place, restore file permissions. */
+ if (stat(rpm, &st) == 0 && unlink(rpm) == 0 &&
+ rename(trpm, rpm) == 0 && chmod(rpm, st.st_mode) == 0) {
+--
+1.8.3.1
+
diff --git a/backport-Consolidate-skipped-hardlink-with-content-case-with-.patch b/backport-Consolidate-skipped-hardlink-with-content-case-with-.patch
new file mode 100644
index 0000000..e992dca
--- /dev/null
+++ b/backport-Consolidate-skipped-hardlink-with-content-case-with-.patch
@@ -0,0 +1,56 @@
+From cc22fc694d30a64862f0b16d137deaab5416382d Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 11 Feb 2022 13:05:45 +0200
+Subject: [PATCH] Consolidate skipped hardlink with content case with the
+ others
+
+Handling this in a separate clause makes the logic much clearer and
+(in theory at least) lets us handle hardlinks to any content, not
+just regular files.
+---
+ lib/fsm.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index ec6ee2c..82610c7 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -832,9 +832,18 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
+ struct filedata_s *fp = &fdata[fx];
+
++ /*
++ * Tricksy case: this file is a being skipped, but it's part of
++ * a hardlinked set and has the actual content linked with it.
++ * Write the content to the first non-skipped file of the set
++ * instead.
++ */
++ if (fp->skip && firstlink && rpmfiArchiveHasContent(fi))
++ fp = firstlink;
++
+ if (!fp->skip) {
+ /* Directories replacing something need early backup */
+- if (!fp->suffix) {
++ if (!fp->suffix && fp != firstlink) {
+ rc = fsmBackup(fi, fp->action);
+ }
+
+@@ -904,15 +913,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ if (!IS_DEV_LOG(fp->fpath))
+ rc = RPMERR_UNKNOWN_FILETYPE;
+ }
+- } else if (firstlink && rpmfiArchiveHasContent(fi)) {
+- /*
+- * Tricksy case: this file is a being skipped, but it's part of
+- * a hardlinked set and has the actual content linked with it.
+- * Write the content to the first non-skipped file of the set
+- * instead.
+- */
+- rc = fsmMkfile(fi, firstlink, files, psm, nodigest,
+- &firstlink, &firstlinkfile);
+ }
+
+ /* Notify on success. */
+--
+1.8.3.1
+
diff --git a/backport-Convert-the-file-creation-steps-the-at-family-of-cal.patch b/backport-Convert-the-file-creation-steps-the-at-family-of-cal.patch
new file mode 100644
index 0000000..1b4de6f
--- /dev/null
+++ b/backport-Convert-the-file-creation-steps-the-at-family-of-cal.patch
@@ -0,0 +1,189 @@
+From b599e28112ce5cee98b9ffa7bd96886ec5155e9c Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 11 Feb 2022 15:35:16 +0200
+Subject: [PATCH] Convert the file creation steps the *at() family of calls
+
+Supposedly no functional changes here, we just need all these things
+converted before we can swap over to relative paths.
+---
+ configure.ac | 2 +-
+ lib/fsm.c | 59 ++++++++++++++++++++++++++++++-----------------------------
+ 2 files changed, 31 insertions(+), 30 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 0099e5f..ac90037 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -581,7 +581,7 @@ AC_CHECK_FUNCS([secure_getenv __secure_getenv])
+ AC_CHECK_FUNCS(
+ [mkstemp getcwd basename dirname realpath setenv unsetenv regcomp lchown \
+ utimes getline localtime_r statvfs getaddrinfo \
+- openat mkdirat fstatat ],
++ openat mkdirat fstatat linkat symlinkat mkfifoat mknodat ],
+ [], [AC_MSG_ERROR([function required by rpm])])
+
+ AC_LIBOBJ(fnmatch)
+diff --git a/lib/fsm.c b/lib/fsm.c
+index ae1bd3f..8443954 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -214,13 +214,13 @@ const char * dnlNextIterator(DNLI_t dnli)
+ return dn;
+ }
+
+-static int fsmLink(const char *opath, const char *path)
++static int fsmLink(int odirfd, const char *opath, int dirfd, const char *path)
+ {
+- int rc = link(opath, path);
++ int rc = linkat(odirfd, opath, dirfd, path, 0);
+
+ if (_fsm_debug) {
+- rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", __func__,
+- opath, path, (rc < 0 ? strerror(errno) : ""));
++ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, %d %s) %s\n", __func__,
++ odirfd, opath, dirfd, path, (rc < 0 ? strerror(errno) : ""));
+ }
+
+ if (rc < 0)
+@@ -139,17 +139,18 @@ static int fsmClose(FD_t *wfdp)
+ return rc;
+ }
+
+-static int fsmOpen(FD_t *wfdp, const char *dest)
++static int fsmOpen(FD_t *wfdp, int dirfd, const char *dest)
+ {
+ int rc = 0;
+ /* Create the file with 0200 permissions (write by owner). */
+- {
+- mode_t old_umask = umask(0577);
+- *wfdp = Fopen(dest, "wx.ufdio");
+- umask(old_umask);
++ int fd = openat(dirfd, dest, O_WRONLY|O_EXCL|O_CREAT, 0200);
++
++ if (fd >= 0) {
++ *wfdp = fdDup(fd);
++ close(fd);
+ }
+
+- if (Ferror(*wfdp))
++ if (fd < 0 || Ferror(*wfdp))
+ rc = RPMERR_OPEN_FAILED;
+
+ if (_fsm_debug) {
+@@ -174,7 +175,7 @@ static int fsmUnpack(rpmfi fi, FD_t fd, rpmpsm psm, int nodigest)
+ return rc;
+ }
+
+-static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
++static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ rpmpsm psm, int nodigest,
+ struct filedata_s ** firstlink, FD_t *firstlinkfile)
+ {
+@@ -183,7 +184,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
+
+ if (*firstlink == NULL) {
+ /* First encounter, open file for writing */
+- rc = fsmOpen(&fd, fp->fpath);
++ rc = fsmOpen(&fd, dirfd, fp->fpath);
+ /* If it's a part of a hardlinked set, the content may come later */
+ if (fp->sb.st_nlink > 1) {
+ *firstlink = fp;
+@@ -192,7 +193,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ } else {
+ /* Create hard links for others and avoid redundant metadata setting */
+ if (*firstlink != fp) {
+- rc = fsmLink((*firstlink)->fpath, fp->fpath);
++ rc = fsmLink(dirfd, (*firstlink)->fpath, dirfd, fp->fpath);
+ }
+ fd = *firstlinkfile;
+ }
+@@ -382,13 +383,13 @@ static int ensureDir(rpmPlugins plugins, const char *p, int owned, int create)
+ return dirfd;
+ }
+
+-static int fsmMkfifo(const char *path, mode_t mode)
++static int fsmMkfifo(int dirfd, const char *path, mode_t mode)
+ {
+- int rc = mkfifo(path, (mode & 07777));
++ int rc = mkfifoat(dirfd, path, (mode & 07777));
+
+ if (_fsm_debug) {
+- rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n",
+- __func__, path, (unsigned)(mode & 07777),
++ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%04o) %s\n",
++ __func__, dirfd, path, (unsigned)(mode & 07777),
+ (rc < 0 ? strerror(errno) : ""));
+ }
+
+@@ -398,14 +399,14 @@ static int fsmMkfifo(const char *path, mode_t mode)
+ return rc;
+ }
+
+-static int fsmMknod(const char *path, mode_t mode, dev_t dev)
++static int fsmMknod(int dirfd, const char *path, mode_t mode, dev_t dev)
+ {
+ /* FIX: check S_IFIFO or dev != 0 */
+- int rc = mknod(path, (mode & ~07777), dev);
++ int rc = mknodat(dirfd, path, (mode & ~07777), dev);
+
+ if (_fsm_debug) {
+- rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n",
+- __func__, path, (unsigned)(mode & ~07777),
++ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%o, 0x%x) %s\n",
++ __func__, dirfd, path, (unsigned)(mode & ~07777),
+ (unsigned)dev, (rc < 0 ? strerror(errno) : ""));
+ }
+
+@@ -440,13 +441,13 @@ static void fsmDebug(const char *fpath, rpmFileAction action,
+ (fpath ? fpath : ""));
+ }
+
+-static int fsmSymlink(const char *opath, const char *path)
++static int fsmSymlink(const char *opath, int dirfd, const char *path)
+ {
+- int rc = symlink(opath, path);
++ int rc = symlinkat(opath, dirfd, path);
+
+ if (_fsm_debug) {
+- rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", __func__,
+- opath, path, (rc < 0 ? strerror(errno) : ""));
++ rpmlog(RPMLOG_DEBUG, " %8s (%s, %d %s) %s\n", __func__,
++ opath, dirfd, path, (rc < 0 ? strerror(errno) : ""));
+ }
+
+ if (rc < 0)
+@@ -884,7 +885,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+
+ if (S_ISREG(fp->sb.st_mode)) {
+ if (rc == RPMERR_ENOENT) {
+- rc = fsmMkfile(fi, fp, files, psm, nodigest,
++ rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
+ &firstlink, &firstlinkfile);
+ }
+ } else if (S_ISDIR(fp->sb.st_mode)) {
+@@ -896,19 +897,19 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ }
+ } else if (S_ISLNK(fp->sb.st_mode)) {
+ if (rc == RPMERR_ENOENT) {
+- rc = fsmSymlink(rpmfiFLink(fi), fp->fpath);
++ rc = fsmSymlink(rpmfiFLink(fi), di.dirfd, fp->fpath);
+ }
+ } else if (S_ISFIFO(fp->sb.st_mode)) {
+ /* This mimics cpio S_ISSOCK() behavior but probably isn't right */
+ if (rc == RPMERR_ENOENT) {
+- rc = fsmMkfifo(fp->fpath, 0000);
++ rc = fsmMkfifo(di.dirfd, fp->fpath, 0000);
+ }
+ } else if (S_ISCHR(fp->sb.st_mode) ||
+ S_ISBLK(fp->sb.st_mode) ||
+ S_ISSOCK(fp->sb.st_mode))
+ {
+ if (rc == RPMERR_ENOENT) {
+- rc = fsmMknod(fp->fpath, fp->sb.st_mode, fp->sb.st_rdev);
++ rc = fsmMknod(di.dirfd, fp->fpath, fp->sb.st_mode, fp->sb.st_rdev);
+ }
+ } else {
+ /* XXX Special case /dev/log, which shouldn't be packaged anyways */
+--
+1.8.3.1
+
diff --git a/backport-Fix-BANames-leak-in-handlePreambleTag.patch b/backport-Fix-BANames-leak-in-handlePreambleTag.patch
new file mode 100644
index 0000000..417980f
--- /dev/null
+++ b/backport-Fix-BANames-leak-in-handlePreambleTag.patch
@@ -0,0 +1,26 @@
+From 7fcdfd3b40f69af6a1d4980683859eef05f39b4e Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Fri, 25 Nov 2022 16:48:34 +0800
+Subject: [PATCH 1/5] Fix BANames leak in handlePreambleTag
+
+The "BANames" is alloced from popParseArgvString but not freed
+when spec->packages != pkg. Fix it.
+---
+ build/parsePreamble.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/build/parsePreamble.c b/build/parsePreamble.c
+index 119551cf6..c4d137cf7 100644
+--- a/build/parsePreamble.c
++++ b/build/parsePreamble.c
+@@ -961,6 +961,7 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
+ BANames = _free(BANames);
+ goto exit;
+ }
++ BANames = _free(BANames);
+ headerPutString(pkg->header, RPMTAG_ARCH, "noarch");
+ }
+ if (!BACount)
+--
+2.27.0
+
diff --git a/backport-Fix-Header-leak-when-running-rpm2cpio.patch b/backport-Fix-Header-leak-when-running-rpm2cpio.patch
new file mode 100644
index 0000000..395234f
--- /dev/null
+++ b/backport-Fix-Header-leak-when-running-rpm2cpio.patch
@@ -0,0 +1,29 @@
+From cf27c6f4963dcf27302d0f4fa39d7787dd03f942 Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Fri, 25 Nov 2022 17:18:33 +0800
+Subject: [PATCH] Fix Header leak when running rpm2cpio
+
+Header "h" is alloced in rpmReadPackageFile but not freed when
+running rpm2cpio. Fix it. Remove redundant whitespace between
+the Fclose()'s too while at it for logical cleanup grouping.
+---
+ rpm2cpio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rpm2cpio.c b/rpm2cpio.c
+index fcc3b3079..940d6ce38 100644
+--- a/rpm2cpio.c
++++ b/rpm2cpio.c
+@@ -96,8 +96,8 @@ int main(int argc, char *argv[])
+ */
+ rc = (ufdCopy(gzdi, fdo) >= payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
+
++ headerFree(h);
+ Fclose(fdo);
+-
+ Fclose(gzdi); /* XXX gzdi == fdi */
+
+ return rc;
+--
+2.33.0
+
diff --git a/backport-Fix-OpenPGP-key-ID-parsing-regression.patch b/backport-Fix-OpenPGP-key-ID-parsing-regression.patch
new file mode 100644
index 0000000..b6189f9
--- /dev/null
+++ b/backport-Fix-OpenPGP-key-ID-parsing-regression.patch
@@ -0,0 +1,28 @@
+From 7f830132fe717d4b31c035bb3d08379451e3cd81 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Thu, 14 Apr 2022 15:38:11 -0400
+Subject: [PATCH] Fix OpenPGP key ID parsing regression
+
+This fixes a regression in 598a771d8b4f4f480d4990ccf59b978d537201dd,
+which caused RPM to parse key flags from a hashed key ID subpacket. As
+a result, RPM would wrongly reject a signature that had both key ID and
+key usage flags subpackets in the hashed section.
+---
+ rpmio/rpmpgp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 93c1be2..ea3905b 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -323,6 +323,7 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
+ _digp->saved |= PGPDIG_SAVED_ID;
+ memcpy(_digp->signid, p+1, sizeof(_digp->signid));
+ }
++ break;
+ case PGPSUBTYPE_KEY_FLAGS: /* Key usage flags */
+ /* Subpackets in the unhashed section cannot be trusted */
+ if (!hashed)
+--
+1.8.3.1
+
diff --git a/backport-Fix-__cplusplus-misspelled-as-_cplusplus.patch b/backport-Fix-__cplusplus-misspelled-as-_cplusplus.patch
new file mode 100644
index 0000000..26e5cb8
--- /dev/null
+++ b/backport-Fix-__cplusplus-misspelled-as-_cplusplus.patch
@@ -0,0 +1,39 @@
+From 989d7c593c7ab12e17ea8f486856bafac6a1ae37 Mon Sep 17 00:00:00 2001
+From: Peter Pentchev <roam@ringlet.net>
+Date: Sat, 27 Nov 2021 00:43:41 +0200
+Subject: [PATCH] Fix __cplusplus misspelled as _cplusplus.
+
+---
+ sign/rpmsignfiles.h | 2 +-
+ sign/rpmsignverity.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sign/rpmsignfiles.h b/sign/rpmsignfiles.h
+index 2ff623c..a21a006 100644
+--- a/sign/rpmsignfiles.h
++++ b/sign/rpmsignfiles.h
+@@ -19,7 +19,7 @@ extern "C" {
+ RPM_GNUC_INTERNAL
+ rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass);
+
+-#ifdef _cplusplus
++#ifdef __cplusplus
+ }
+ #endif
+
+diff --git a/sign/rpmsignverity.h b/sign/rpmsignverity.h
+index d869e8d..16e6c98 100644
+--- a/sign/rpmsignverity.h
++++ b/sign/rpmsignverity.h
+@@ -29,7 +29,7 @@ RPM_GNUC_INTERNAL
+ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
+ char *keypass, char *cert, uint16_t algo);
+
+-#ifdef _cplusplus
++#ifdef __cplusplus
+ }
+ #endif
+
+--
+1.8.3.1
+
diff --git a/backport-Fix-a-copy-paste-help-description-of-whatconflicts-R.patch b/backport-Fix-a-copy-paste-help-description-of-whatconflicts-R.patch
new file mode 100644
index 0000000..ad4d1e7
--- /dev/null
+++ b/backport-Fix-a-copy-paste-help-description-of-whatconflicts-R.patch
@@ -0,0 +1,26 @@
+From 03525592c944957f3b7b200b7daeb9f615cdcde7 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 23 May 2023 12:46:22 +0300
+Subject: [PATCH] Fix a copy-paste --help description of --whatconflicts
+ (RhBug:2208661)
+
+---
+ lib/poptQV.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/poptQV.c b/lib/poptQV.c
+index ac8e8975d..8bd91c652 100644
+--- a/lib/poptQV.c
++++ b/lib/poptQV.c
+@@ -108,7 +108,7 @@ struct poptOption rpmQVSourcePoptTable[] = {
+ { "verify", 'V', POPT_ARGFLAG_DOC_HIDDEN, NULL, 'V',
+ N_("rpm verify mode"), NULL },
+ { "whatconflicts", '\0', 0, 0, POPT_WHATCONFLICTS,
+- N_("query/verify the package(s) which require a dependency"), "CAPABILITY" },
++ N_("query/verify the package(s) which conflict with a dependency"), "CAPABILITY" },
+ { "whatrequires", '\0', 0, 0, POPT_WHATREQUIRES,
+ N_("query/verify the package(s) which require a dependency"), "CAPABILITY" },
+ { "whatobsoletes", '\0', 0, 0, POPT_WHATOBSOLETES,
+--
+2.27.0
+
diff --git a/backport-Fix-a-memleak-in-ndb-from-opened-but-not-closed-dbis.patch b/backport-Fix-a-memleak-in-ndb-from-opened-but-not-closed-dbis.patch
new file mode 100644
index 0000000..baeb339
--- /dev/null
+++ b/backport-Fix-a-memleak-in-ndb-from-opened-but-not-closed-dbis.patch
@@ -0,0 +1,26 @@
+From 5c5cd9f30b31f0255a484f7d2e3f9cfacc0ec3bf Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 15 Dec 2021 10:01:41 +0200
+Subject: [PATCH] Fix a memleak in ndb from opened but not closed dbis.
+
+Fixes: #1861
+---
+ lib/backend/ndb/glue.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
+index 7ba3056..d528ebc 100644
+--- a/lib/backend/ndb/glue.c
++++ b/lib/backend/ndb/glue.c
+@@ -77,7 +77,7 @@ static int ndb_Close(dbiIndex dbi, unsigned int flags)
+ }
+ if (rdb->db_dbenv)
+ closeEnv(rdb);
+- dbi->dbi_db = 0;
++ dbiFree(dbi);
+ return 0;
+ }
+
+--
+1.8.3.1
+
diff --git a/backport-Fix-a-segfault-on-a-non-stringable-argument-to-macro.patch b/backport-Fix-a-segfault-on-a-non-stringable-argument-to-macro.patch
new file mode 100644
index 0000000..541c6c3
--- /dev/null
+++ b/backport-Fix-a-segfault-on-a-non-stringable-argument-to-macro.patch
@@ -0,0 +1,58 @@
+From 856ddc334174fd37fe4ce81bc9f9f11a08cf6c81 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 17 Mar 2023 12:53:42 +0200
+Subject: [PATCH] Fix a segfault on a non-stringable argument to macro call
+ from Lua
+
+When natively calling a parametric macro from Lua, with the arguments
+inside a table, we can't assume lua_tostring() always succeeds as it
+can fail eg on a table. Report the error instead of crashing in argvAdd(),
+and add a test as well.
+---
+ rpmio/rpmlua.c | 9 +++++++--
+ tests/rpmmacro.at | 9 +++++++++
+ 2 files changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c
+index 6c42af792..0e3685713 100644
+--- a/rpmio/rpmlua.c
++++ b/rpmio/rpmlua.c
+@@ -1178,8 +1178,13 @@ static int mc_call(lua_State *L)
+
+ for (int i = 1; i <= nitem; i++) {
+ lua_rawgeti(L, 1, i);
+- argvAdd(&argv, lua_tostring(L, -1));
+- lua_pop(L, 1);
++ const char *s= lua_tostring(L, -1);
++ if (s) {
++ argvAdd(&argv, s);
++ lua_pop(L, 1);
++ } else {
++ luaL_argerror(L, i, "cannot convert to string");
++ }
+ }
+
+ if (rpmExpandThisMacro(*mc, name, argv, &buf, 0) >= 0) {
+diff --git a/tests/rpmmacro.at b/tests/rpmmacro.at
+index 55b7d5fa5..22d873e81 100644
+--- a/tests/rpmmacro.at
++++ b/tests/rpmmacro.at
+@@ -713,6 +713,15 @@ nil
+ 1:%{?aaa} 2:%{yyy}
+ that
+ ])
++
++AT_CHECK([[
++runroot rpm \
++ --eval "%{lua:macros.defined({1,2,{}})}"
++]],
++[1],
++[],
++[[error: lua script failed: [string "<lua>"]:1: bad argument #3 to 'defined' (cannot convert to string)
++]])
+ AT_CLEANUP
+
+ AT_SETUP([lua macros recursion])
+--
+2.27.0
+
diff --git a/backport-Fix-changelog-parsing-affecting-caller-timezone-stat.patch b/backport-Fix-changelog-parsing-affecting-caller-timezone-stat.patch
new file mode 100644
index 0000000..4b236e8
--- /dev/null
+++ b/backport-Fix-changelog-parsing-affecting-caller-timezone-stat.patch
@@ -0,0 +1,30 @@
+From 1a7de551a74d73f01eb40cb744c1dbba5faeb651 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 30 May 2022 14:24:45 +0300
+Subject: [PATCH] Fix changelog parsing affecting caller timezone state
+
+We meddle with TZ environ which then propagates to other values through
+mktime() implicitly calling tzset(), but that other data doesn't get
+reset by just restoring the TZ variable. Restore initial state by explicitly
+call tzset() after we're done with it.
+
+Fixes: #1821
+---
+ build/parseChangelog.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/build/parseChangelog.c b/build/parseChangelog.c
+index 65c0952..c59786f 100644
+--- a/build/parseChangelog.c
++++ b/build/parseChangelog.c
+@@ -175,6 +175,7 @@ static int dateToTimet(const char * datestr, time_t * secs, int * date_words)
+ setenv("TZ", tz, 1);
+ free(tz);
+ }
++ tzset();
+
+ if (*secs == -1) goto exit;
+
+--
+1.8.3.1
+
diff --git a/backport-Fix-eiu-sourceURL-info-leak-in-rpmInstall.patch b/backport-Fix-eiu-sourceURL-info-leak-in-rpmInstall.patch
new file mode 100644
index 0000000..bcddb75
--- /dev/null
+++ b/backport-Fix-eiu-sourceURL-info-leak-in-rpmInstall.patch
@@ -0,0 +1,31 @@
+From 084c64d5ea0e1a309d3b57dc95926eb1536d0a7a Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Thu, 24 Nov 2022 11:43:28 +0800
+Subject: [PATCH 1/3] Fix eiu->sourceURL info leak in rpmInstall()
+
+When installing source rpms, eiu->sourceURL info is leaked.
+---
+ lib/rpminstall.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/lib/rpminstall.c b/lib/rpminstall.c
+index 097599681..eb68deb4d 100644
+--- a/lib/rpminstall.c
++++ b/lib/rpminstall.c
+@@ -672,8 +672,13 @@ exit:
+ eiu->pkgURL[i] = _free(eiu->pkgURL[i]);
+ }
+ }
++ if (eiu->sourceURL != NULL) {
++ for (i = 0; i < eiu->numSRPMS; i++)
++ eiu->sourceURL[i] = _free(eiu->sourceURL[i]);
++ }
+ eiu->pkgState = _free(eiu->pkgState);
+ eiu->pkgURL = _free(eiu->pkgURL);
++ eiu->sourceURL = _free(eiu->sourceURL);
+ eiu->argv = _free(eiu->argv);
+ rc = eiu->numFailed;
+ free(eiu);
+--
+2.33.0
+
diff --git a/backport-Fix-elf-leak-in-getElfColor.patch b/backport-Fix-elf-leak-in-getElfColor.patch
new file mode 100644
index 0000000..cf87488
--- /dev/null
+++ b/backport-Fix-elf-leak-in-getElfColor.patch
@@ -0,0 +1,28 @@
+From 01196e00beefc2ba6f7f0787350c5dd76891829a Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Fri, 25 Nov 2022 17:11:22 +0800
+Subject: [PATCH 3/5] Fix elf leak in getElfColor
+
+The "elf" is leaked in getElfColor when gelf_getehdr return fail.
+---
+ build/rpmfc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/build/rpmfc.c b/build/rpmfc.c
+index d35c148b9..06205469c 100644
+--- a/build/rpmfc.c
++++ b/build/rpmfc.c
+@@ -1145,8 +1145,9 @@ static uint32_t getElfColor(const char *fn)
+ color = RPMFC_ELF32;
+ break;
+ }
+- elf_end(elf);
+ }
++ if (elf)
++ elf_end(elf);
+ close(fd);
+ }
+ #endif
+--
+2.27.0
+
diff --git a/backport-Fix-file-leak-when-src-rpm-in-URL-format-is-used-for.patch b/backport-Fix-file-leak-when-src-rpm-in-URL-format-is-used-for.patch
new file mode 100644
index 0000000..de7f89f
--- /dev/null
+++ b/backport-Fix-file-leak-when-src-rpm-in-URL-format-is-used-for.patch
@@ -0,0 +1,33 @@
+From 0b34438ccc3fdcbdaa6226d2398df88cc7439603 Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Thu, 24 Nov 2022 17:16:46 +0800
+Subject: [PATCH 2/3] Fix file leak when src rpm in URL format is used for
+ installation
+
+%{_tmppath}/rpm-tmp.* is created by rpmMkTempFile() when src rpm in
+URL format is used for installation, which is leaked.
+---
+ lib/rpminstall.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/lib/rpminstall.c b/lib/rpminstall.c
+index eb68deb4d..b392cf1c3 100644
+--- a/lib/rpminstall.c
++++ b/lib/rpminstall.c
+@@ -673,8 +673,12 @@ exit:
+ }
+ }
+ if (eiu->sourceURL != NULL) {
+- for (i = 0; i < eiu->numSRPMS; i++)
++ for (i = 0; i < eiu->numSRPMS; i++) {
++ if (eiu->sourceURL[i] == NULL) continue;
++ if (eiu->pkgState[i] == 1)
++ (void) unlink(eiu->sourceURL[i]);
+ eiu->sourceURL[i] = _free(eiu->sourceURL[i]);
++ }
+ }
+ eiu->pkgState = _free(eiu->pkgState);
+ eiu->pkgURL = _free(eiu->pkgURL);
+--
+2.33.0
+
diff --git a/backport-Fix-fileleak-and-memleak-in-rpmInstall.patch b/backport-Fix-fileleak-and-memleak-in-rpmInstall.patch
new file mode 100644
index 0000000..fdf3c56
--- /dev/null
+++ b/backport-Fix-fileleak-and-memleak-in-rpmInstall.patch
@@ -0,0 +1,63 @@
+From f0f983b145583eeed618cf3cbc5d39bedd8af5a5 Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Mon, 28 Nov 2022 11:19:20 +0800
+Subject: [PATCH 2/3] Fix fileleak and memleak in rpmInstall
+
+The "*eiu->fnp" from "eiu->pkgURL[eiu->pkgx]" which is alloced. when
+Fopen or rpmReadPackageFile fails in tryReadHeader, "*eiu->fnp" is
+set to NULL but not freed. In addition, if "eiu->pkgState[eiu->pkgx]"
+is set, the file is leaked too. Fix it.
+
+Only resource free is added, no other logic change.
+---
+ lib/rpminstall.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/lib/rpminstall.c b/lib/rpminstall.c
+index b392cf1c3..90474fabf 100644
+--- a/lib/rpminstall.c
++++ b/lib/rpminstall.c
+@@ -355,7 +355,6 @@ static int tryReadHeader(rpmts ts, struct rpmEIU * eiu, Header * hdrp)
+ fd = NULL;
+ }
+ eiu->numFailed++;
+- *eiu->fnp = NULL;
+ return RPMRC_FAIL;
+ }
+
+@@ -371,7 +370,6 @@ static int tryReadHeader(rpmts ts, struct rpmEIU * eiu, Header * hdrp)
+ if (eiu->rpmrc == RPMRC_FAIL) {
+ rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), *eiu->fnp);
+ eiu->numFailed++;
+- *eiu->fnp = NULL;
+ }
+
+ return RPMRC_OK;
+@@ -554,8 +552,12 @@ restart:
+ rpmlog(RPMLOG_DEBUG, "============== %s\n", *eiu->fnp);
+ (void) urlPath(*eiu->fnp, &fileName);
+
+- if (tryReadHeader(ts, eiu, &h) == RPMRC_FAIL)
++ if (tryReadHeader(ts, eiu, &h) == RPMRC_FAIL) {
++ if (eiu->pkgState[eiu->fnp - eiu->pkgURL] == 1)
++ (void) unlink(*eiu->fnp);
++ *eiu->fnp = _free(*eiu->fnp);
+ continue;
++ }
+
+ if (eiu->rpmrc == RPMRC_NOTFOUND) {
+ rc = tryReadManifest(eiu);
+@@ -564,6 +566,10 @@ restart:
+ headerFree(h);
+ goto restart;
+ }
++ } else if (eiu->rpmrc == RPMRC_FAIL) {
++ if (eiu->pkgState[eiu->fnp - eiu->pkgURL] == 1)
++ (void) unlink(*eiu->fnp);
++ *eiu->fnp = _free(*eiu->fnp);
+ }
+
+ if (headerIsSource(h)) {
+--
+2.27.0
+
diff --git a/backport-Fix-fileleak-when-urlGetFile-fails-in-rpmInstall.patch b/backport-Fix-fileleak-when-urlGetFile-fails-in-rpmInstall.patch
new file mode 100644
index 0000000..7b5bb6e
--- /dev/null
+++ b/backport-Fix-fileleak-when-urlGetFile-fails-in-rpmInstall.patch
@@ -0,0 +1,30 @@
+From af81c95114bc2c01f005f15f17646a5188b5855d Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Mon, 28 Nov 2022 11:34:24 +0800
+Subject: [PATCH 3/3] Fix fileleak when urlGetFile fails in rpmInstall
+
+The "tfn" is created by calling rpmMkTempFile but not unlinked when
+urlGetFile fails in rpmInstall. Fix it.
+---
+ lib/rpminstall.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/lib/rpminstall.c b/lib/rpminstall.c
+index 90474fabf..c89ca30b5 100644
+--- a/lib/rpminstall.c
++++ b/lib/rpminstall.c
+@@ -520,7 +520,10 @@ restart:
+ _("skipping %s - transfer failed\n"), fileURL);
+ eiu->numFailed++;
+ eiu->pkgURL[eiu->pkgx] = NULL;
+- tfn = _free(tfn);
++ if (tfn) {
++ (void) unlink(tfn);
++ tfn = _free(tfn);
++ }
+ break;
+ }
+ eiu->pkgState[eiu->pkgx] = 1;
+--
+2.27.0
+
diff --git a/backport-Fix-h-blob-leak-when-installing-source-rpms.patch b/backport-Fix-h-blob-leak-when-installing-source-rpms.patch
new file mode 100644
index 0000000..a29f84e
--- /dev/null
+++ b/backport-Fix-h-blob-leak-when-installing-source-rpms.patch
@@ -0,0 +1,28 @@
+From 86c1d9738de58eb8f8844c5345baeb578ace9485 Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Thu, 24 Nov 2022 17:33:53 +0800
+Subject: [PATCH 3/3] Fix h->blob leak when installing source rpms
+
+When installing source rpms, "ei" is malloced and is saved in
+blob->ei by rpmReadPackageFile->rpmpkgRead->hdrblobRead, and then
+blob->ei is saved in h->blob by rpmReadPackageFile->hdrblobImport,
+which is leaked during installation.
+---
+ lib/header.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/header.c b/lib/header.c
+index 31d2fca30..004102dd2 100644
+--- a/lib/header.c
++++ b/lib/header.c
+@@ -241,6 +241,7 @@ Header headerFree(Header h)
+ }
+ h->index = _free(h->index);
+ }
++ h->blob = _free(h->blob);
+
+ h = _free(h);
+ return NULL;
+--
+2.33.0
+
diff --git a/backport-Fix-hash-context-leak.patch b/backport-Fix-hash-context-leak.patch
new file mode 100644
index 0000000..f8fda68
--- /dev/null
+++ b/backport-Fix-hash-context-leak.patch
@@ -0,0 +1,34 @@
+From 6e9531430d70fe80b67782ed57f1526aec9ed711 Mon Sep 17 00:00:00 2001
+From: Justus Winter <justus@sequoia-pgp.org>
+Date: Thu, 28 Oct 2021 13:32:22 +0200
+Subject: [PATCH] Fix hash context leak
+
+The hash context is duplicated unconditionally, but there is an
+execution path exiting the function without it being finalized.
+---
+ rpmio/rpmpgp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 861f670..1e4f667 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1310,6 +1310,7 @@ rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx)
+ }
+
+ rpmDigestFinal(ctx, (void **)&hash, &hashlen, 0);
++ ctx = NULL;
+
+ /* Compare leading 16 bits of digest for quick check. */
+ if (hash == NULL || memcmp(hash, sig->signhash16, 2) != 0)
+@@ -1333,6 +1334,7 @@ rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx)
+
+ exit:
+ free(hash);
++ rpmDigestFinal(ctx, NULL, NULL, 0);
+ return res;
+
+ }
+--
+1.8.3.1
+
diff --git a/backport-Fix-hashlen-overflow.patch b/backport-Fix-hashlen-overflow.patch
new file mode 100644
index 0000000..4717174
--- /dev/null
+++ b/backport-Fix-hashlen-overflow.patch
@@ -0,0 +1,46 @@
+From 3f142b210ae0c01e1b21c2c057b12db574386e7a Mon Sep 17 00:00:00 2001
+From: Justus Winter <justus@sequoia-pgp.org>
+Date: Wed, 27 Oct 2021 09:51:13 +0200
+Subject: [PATCH] Fix hashlen overflow
+
+struct pgpDigParams_s keeps a copy of the verbatim key material for
+hashing. The length of this data is kept in 'hashlen' which
+previously was a uint8_t. However, the size of the signature's hashed
+subpacket area can be up to 2^16 bytes, and one needs to hash some of
+the signature packet's fields on top of that.
+
+Hence, 'hashlen' must be at least a uint32_t.
+
+This overflow happens in practice as soon as the signature's hashed
+subpacket area contains an embedded signature. See section 11.1 of
+RFC4880:
+
+ Each Subkey packet MUST be followed by one Signature packet, which
+ should be a subkey binding signature issued by the top-level key.
+ For subkeys that can issue signatures, the subkey binding signature
+ MUST contain an Embedded Signature subpacket with a primary key
+ binding signature (0x19) issued by the subkey on the top-level key.
+
+While the embedded signature may be in the unhashed subpacket area
+because it is self-authenticating, it is more robust to put it in the
+hashed area.
+---
+ rpmio/digest.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rpmio/digest.h b/rpmio/digest.h
+index 690d176..3b72a28 100644
+--- a/rpmio/digest.h
++++ b/rpmio/digest.h
+@@ -33,7 +33,7 @@ struct pgpDigParams_s {
+
+ uint8_t hash_algo;
+ uint8_t sigtype;
+- uint8_t hashlen;
++ uint32_t hashlen;
+ uint8_t signhash16[2];
+ pgpKeyID_t signid;
+ uint8_t saved;
+--
+1.8.3.1
+
diff --git a/backport-Fix-header-leak-in-rpmInstall.patch b/backport-Fix-header-leak-in-rpmInstall.patch
new file mode 100644
index 0000000..67dc581
--- /dev/null
+++ b/backport-Fix-header-leak-in-rpmInstall.patch
@@ -0,0 +1,42 @@
+From 15a0c73f4698bc58fa2a633d46527c7813150f3a Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Thu, 24 Nov 2022 10:43:11 +0800
+Subject: [PATCH] Fix header leak in rpmInstall()
+
+When rpm installs a package, the header from tryReadHeader()
+in rpmInstall() is leaked in some cases.
+---
+ lib/rpminstall.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/lib/rpminstall.c b/lib/rpminstall.c
+index 9167dbdde..097599681 100644
+--- a/lib/rpminstall.c
++++ b/lib/rpminstall.c
+@@ -561,13 +561,14 @@ restart:
+ rc = tryReadManifest(eiu);
+ if (rc == RPMRC_OK) {
+ eiu->prevx++;
++ headerFree(h);
+ goto restart;
+ }
+ }
+
+ if (headerIsSource(h)) {
++ headerFree(h);
+ if (ia->installInterfaceFlags & INSTALL_FRESHEN) {
+- headerFree(h);
+ continue;
+ }
+ rpmlog(RPMLOG_DEBUG, "\tadded source package [%d]\n",
+@@ -592,6 +593,7 @@ restart:
+ rpmlog(RPMLOG_ERR, _("package %s is not relocatable\n"),
+ headerGetString(h, RPMTAG_NAME));
+ eiu->numFailed++;
++ headerFree(h);
+ goto exit;
+ }
+ }
+--
+2.33.0
+
diff --git a/backport-Fix-install-of-block-and-character-special-files-219.patch b/backport-Fix-install-of-block-and-character-special-files-219.patch
new file mode 100644
index 0000000..047b6d1
--- /dev/null
+++ b/backport-Fix-install-of-block-and-character-special-files-219.patch
@@ -0,0 +1,110 @@
+From 28c92fd54c93371c3062664d8a938438a2be88d6 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 13 Jan 2023 08:57:27 +0200
+Subject: [PATCH] Fix install of block and character special files (#2195,
+ #2275)
+
+While it's possible to open special files, they are, well, special and
+have "side-effects" also known as, ahem, semantics. Opening a device
+file in Unix means accessing that *device*, and FIFOs have their own
+semantics. In other words, for rpm's purposes, we should never EVER
+open these files as a part of the install / permission setting etc.
+Fix this major brainfart in 25a435e90844ea98fe5eb7bef22c1aecf3a9c033.
+
+OTOH this forces us back to the less secure path based operations for
+these files, which is what we were trying to avoid in the first place.
+There always was a tiny race between create + open for these (because
+there's no atomic way to create + open anything but regular files) but
+this opens up the window quite a bit.
+Nobody should be placing device nodes in user-owned directories but
+FIFO's may be a different story.
+
+We haven't had tests for device nodes because it requires privileges the
+test-suite usually doesn't have, not testing FIFOs I have no excuse for.
+Add that test now.
+
+Fixes: #2195, #2275
+---
+ lib/fsm.c | 4 +++-
+ tests/data/SPECS/fifo.spec | 16 ++++++++++++++++
+ tests/Makefile.am | 2 +-
+ tests/rpmi.at | 15 +++++++++++++++
+ 4 files changed, 35 insertions(+), 2 deletions(-)
+ create mode 100644 tests/data/SPECS/fifo.spec
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index e38155df7..052416641 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -1014,7 +1014,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ rc = RPMERR_UNKNOWN_FILETYPE;
+ }
+
+- if (!rc && fd == -1 && !S_ISLNK(fp->sb.st_mode)) {
++ /* Special files require path-based ops */
++ int mayopen = S_ISREG(fp->sb.st_mode) || S_ISDIR(fp->sb.st_mode);
++ if (!rc && fd == -1 && mayopen) {
+ /* Only follow safe symlinks, and never on temporary files */
+ fd = fsmOpenat(di.dirfd, fp->fpath,
+ fp->suffix ? AT_SYMLINK_NOFOLLOW : 0);
+diff --git a/tests/data/SPECS/fifo.spec b/tests/data/SPECS/fifo.spec
+new file mode 100644
+index 000000000..20b30b243
+--- /dev/null
++++ b/tests/data/SPECS/fifo.spec
+@@ -0,0 +1,16 @@
++Name: fifo
++Version: 1.0
++Release: 1
++Group: Testing
++License: GPL
++Summary: Testing fifo behavior
++BuildArch: noarch
++
++%description
++%{summary}
++
++%install
++mknod ${RPM_BUILD_ROOT}/test-fifo p
++
++%files
++/test-fifo
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 04fa1e5..1b12148 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -174,7 +174,7 @@ populate_testing:
+ for d in dev etc magic tmp var; do if [ ! -d testing/$${d} ]; then mkdir testing/$${d}; fi; done
+ for node in urandom stdin stderr stdout null full; do ln -s /dev/$${node} testing/dev/$${node}; done
+ for cf in hosts resolv.conf passwd shadow group gshadow mtab ; do [ -f /etc/$${cf} ] && ln -s /etc/$${cf} testing/etc/$${cf}; done
+- for prog in gzip cat patch tar sh ln chmod rm mkdir uname grep sed find file ionice mktemp nice cut sort diff touch install wc coreutils xargs; do p=`which $${prog}`; if [ "$${p}" != "" ]; then ln -s $${p} testing/$(bindir)/; fi; done
++ for prog in gzip cat patch tar sh ln chmod rm mkdir uname grep sed find file ionice mktemp nice cut sort diff touch install wc coreutils xargs mknod; do p=`which $${prog}`; if [ "$${p}" != "" ]; then ln -s $${p} testing/$(bindir)/; fi; done
+ for d in /proc /sys /selinux /etc/selinux; do if [ -d $${d} ]; then ln -s $${d} testing/$${d}; fi; done
+ (cd testing/magic && file -C)
+ chmod -R u-w testing/
+diff --git a/tests/rpmi.at b/tests/rpmi.at
+index ee35bdc..a2389de 100644
+--- a/tests/rpmi.at
++++ b/tests/rpmi.at
+@@ -873,3 +873,18 @@ runroot rpm -e hlinktest
+ ],
+ [])
+ AT_CLEANUP
++
++AT_SETUP([rpm -U fifo])
++AT_KEYWORDS([install])
++AT_CHECK([
++RPMDB_INIT
++
++runroot rpmbuild -bb --quiet /data/SPECS/fifo.spec
++runroot rpm -U --ignoreos /build/RPMS/noarch/fifo-1.0-1.noarch.rpm
++runroot rpm -Vv --nouser --nogroup fifo
++],
++[0],
++[......... /test-fifo
++],
++[])
++AT_CLEANUP
+--
+2.27.0
+
diff --git a/backport-Fix-memleak-when-fsmRename-failed-in-fsmCommit.patch b/backport-Fix-memleak-when-fsmRename-failed-in-fsmCommit.patch
new file mode 100644
index 0000000..889cf6e
--- /dev/null
+++ b/backport-Fix-memleak-when-fsmRename-failed-in-fsmCommit.patch
@@ -0,0 +1,28 @@
+From 688c4ad34d197055eb8f58fb4e45065af881598c Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Mon, 28 Nov 2022 11:10:19 +0800
+Subject: [PATCH 1/3] Fix memleak when fsmRename failed in fsmCommit
+
+The "dest" is alloced in fsmFsPath but not freed when fsmRename failed
+in fsmCommit. Fix it.
+---
+ lib/fsm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index 7987abbc9..e38155df7 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -782,7 +782,8 @@ static int fsmCommit(int dirfd, char **path, rpmfi fi, rpmFileAction action, con
+ }
+ free(*path);
+ *path = dest;
+- }
++ } else
++ free(dest);
+ }
+ }
+
+--
+2.27.0
+
diff --git a/backport-Fix-memleak-when-running-generate_buildrequires.patch b/backport-Fix-memleak-when-running-generate_buildrequires.patch
new file mode 100644
index 0000000..131cd7d
--- /dev/null
+++ b/backport-Fix-memleak-when-running-generate_buildrequires.patch
@@ -0,0 +1,27 @@
+From 3b0b9d491f5828a40c15b76b4a19ca00006cf81e Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Mon, 28 Nov 2022 11:02:47 +0800
+Subject: [PATCH 5/5] Fix memleak when running %generate_buildrequires
+
+The "output[i]" is alloced in argvSplit but not freed when running
+%generate_buildrequires. Fix it.
+---
+ build/build.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/build/build.c b/build/build.c
+index 4437f6c9c..34e01d5be 100644
+--- a/build/build.c
++++ b/build/build.c
+@@ -279,7 +279,7 @@ static int doBuildRequires(rpmSpec spec, int test)
+
+ exit:
+ freeStringBuf(sb_stdout);
+- free(output);
++ argvFree(output);
+ return rc;
+ }
+
+--
+2.27.0
+
diff --git a/backport-Fix-memory-leak-in-pgpPrtParams-1.patch b/backport-Fix-memory-leak-in-pgpPrtParams-1.patch
new file mode 100644
index 0000000..16e5cca
--- /dev/null
+++ b/backport-Fix-memory-leak-in-pgpPrtParams-1.patch
@@ -0,0 +1,25 @@
+From 10ac962bf2f71af927c8eaaea427135441663497 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Thu, 17 Mar 2022 03:16:59 -0400
+Subject: [PATCH] Fix memory leak in pgpPrtParams()
+
+Found by leak sanitizer on a fuzzed test case.
+---
+ rpmio/rpmpgp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index eb5701b..f9e2658 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1163,6 +1163,7 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
+ rc = (digp && (p == pend) && expect == 0) ? 0 : -1;
+
+ free(all);
++ selfsig = pgpDigParamsFree(selfsig);
+ if (ret && rc == 0) {
+ *ret = digp;
+ } else {
+--
+1.8.3.1
+
diff --git a/backport-Fix-memory-leak-in-pgpPrtParams.patch b/backport-Fix-memory-leak-in-pgpPrtParams.patch
new file mode 100644
index 0000000..72db05c
--- /dev/null
+++ b/backport-Fix-memory-leak-in-pgpPrtParams.patch
@@ -0,0 +1,38 @@
+From b6dffb6dc5ffa2ddc389743f0507876cab341315 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Fri, 7 Jan 2022 16:10:26 +0100
+Subject: [PATCH] Fix memory leak in pgpPrtParams()
+
+Make sure selfsig is freed in case we break out of the loop in this
+block.
+
+Note that the tests added with the binding validation commit bd36c5d do
+not cover this code path so valgrind won't show this.
+---
+ rpmio/rpmpgp.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 1e4f667..3560328 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1147,12 +1147,11 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
+
+ if (selfsig) {
+ /* subkeys must be followed by binding signature */
+- if (prevtag == PGPTAG_PUBLIC_SUBKEY) {
+- if (selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING)
+- break;
+- }
++ int xx = 1; /* assume failure */
+
+- int xx = pgpVerifySelf(digp, selfsig, all, i);
++ if (!(prevtag == PGPTAG_PUBLIC_SUBKEY &&
++ selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING))
++ xx = pgpVerifySelf(digp, selfsig, all, i);
+
+ selfsig = pgpDigParamsFree(selfsig);
+ if (xx)
+--
+1.8.3.1
+
diff --git a/backport-Fix-old-Python-ts.check-argument-order-regression.patch b/backport-Fix-old-Python-ts.check-argument-order-regression.patch
new file mode 100644
index 0000000..a9bcff6
--- /dev/null
+++ b/backport-Fix-old-Python-ts.check-argument-order-regression.patch
@@ -0,0 +1,32 @@
+From f0c158cbc8a50a776b44de2c0fe744c451155a41 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 4 Jan 2022 15:57:10 +0200
+Subject: [PATCH] Fix old Python ts.check() argument order regression
+
+Commit fab2debfe440d677dbd072c3cd73d2c99876e7a5 managed to mess up the
+order of the last two callback arguments, doh.
+
+Goes to show that nobody has missed this stuff in 12+ years, so it might
+be more merciful to put this thing out of its misery...
+
+Fixes: #1871
+---
+ python/rpm/transaction.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/python/rpm/transaction.py b/python/rpm/transaction.py
+index 991fd9a..ba39881 100644
+--- a/python/rpm/transaction.py
++++ b/python/rpm/transaction.py
+@@ -159,7 +159,7 @@ class TransactionSet(TransactionSetCore):
+ needver = ""
+
+ res.append(((n, v, r),
+- (needname, needver), needflags, sense, p.key))
++ (needname, needver), needflags, p.key, sense))
+
+ return res
+
+--
+1.8.3.1
+
diff --git a/backport-Fix-possible-NULL-pointer-dereference-in-rpmfcClassi.patch b/backport-Fix-possible-NULL-pointer-dereference-in-rpmfcClassi.patch
new file mode 100644
index 0000000..cb718a4
--- /dev/null
+++ b/backport-Fix-possible-NULL-pointer-dereference-in-rpmfcClassi.patch
@@ -0,0 +1,39 @@
+From 1c15d748d3536a21b6edbbf9254db76fefb4b275 Mon Sep 17 00:00:00 2001
+From: Dmitry Gerasimov <d.gerasimov@omp.ru>
+Date: Mon, 27 Dec 2021 12:27:57 +0300
+Subject: [PATCH] Fix possible NULL pointer dereference in rpmfcClassify
+
+Here is simplified overview of possible dereference:
+
+ if (fc == NULL) {
+ rpmlog(RPMLOG_ERR, _("Empty file classifier\n"));
+ goto exit;
+ }
+
+ // ...
+
+ exit:
+ rpmstrPoolFreeze(fc->cdict, 0);
+ ~~~~~~~~~
+
+This issue was found by Svace Static Analyzer.
+---
+ build/rpmfc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/build/rpmfc.c b/build/rpmfc.c
+index eb51a36..cf2c203 100644
+--- a/build/rpmfc.c
++++ b/build/rpmfc.c
+@@ -1168,7 +1168,7 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
+
+ if (fc == NULL) {
+ rpmlog(RPMLOG_ERR, _("Empty file classifier\n"));
+- goto exit;
++ return RPMRC_FAIL;
+ }
+
+ /* It is OK when we have no files to classify. */
+--
+1.8.3.1
+
diff --git a/backport-Fix-possible-descriptor-leak-in-fsmOpenat.patch b/backport-Fix-possible-descriptor-leak-in-fsmOpenat.patch
new file mode 100644
index 0000000..eca230e
--- /dev/null
+++ b/backport-Fix-possible-descriptor-leak-in-fsmOpenat.patch
@@ -0,0 +1,45 @@
+From af08077fb4c60dee516948ce7bf9bed91de62119 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 13 Sep 2022 10:26:05 +0300
+Subject: [PATCH] Fix possible descriptor leak in fsmOpenat()
+
+For the very unlikely case when openat() succeeded but fstatat()
+doesn't, the directory descriptor may be leaved opened. Rearrange
+the code a bit to ensure it'll always get closed when appropriate.
+
+Suggested-by: Pavel Kopylov <pkopylov@cloudlinux.com>
+Suggested-by: Dmitry Antipov <dantipov@cloudlinux.com>
+---
+ lib/fsm.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index e4ec07e..c9ab3e1 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -427,14 +427,16 @@ static int fsmOpenat(int dirfd, const char *path, int flags)
+ */
+ if (fd < 0 && errno == ELOOP && flags != sflags) {
+ int ffd = openat(dirfd, path, flags);
+- if (ffd >= 0 && fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) {
+- if (fstat(ffd, &sb) == 0) {
+- if (lsb.st_uid == 0 || lsb.st_uid == sb.st_uid) {
+- fd = ffd;
+- } else {
+- close(ffd);
++ if (ffd >= 0) {
++ if (fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) {
++ if (fstat(ffd, &sb) == 0) {
++ if (lsb.st_uid == 0 || lsb.st_uid == sb.st_uid) {
++ fd = ffd;
++ }
+ }
+ }
++ if (ffd != fd)
++ close(ffd);
+ }
+ }
+ return fd;
+--
+2.33.0
+
diff --git a/backport-Fix-possible-null-pointer-reference-in-ndb.patch b/backport-Fix-possible-null-pointer-reference-in-ndb.patch
new file mode 100644
index 0000000..b2aeb03
--- /dev/null
+++ b/backport-Fix-possible-null-pointer-reference-in-ndb.patch
@@ -0,0 +1,28 @@
+From 8ec9cfc81c3f8326a1c7ee5b795ef517cd48e6b4 Mon Sep 17 00:00:00 2001
+From: yuxiaojun <yuxiaojun1011@outlook.com>
+Date: Wed, 14 Jun 2023 11:23:24 +0800
+Subject: [PATCH] Fix possible null pointer reference in ndb
+
+slot1 and slot2 may be NULL
+
+Signed-off-by: yuxiaojun <yuxiaojun1011@outlook.com>
+---
+ lib/backend/ndb/rpmxdb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
+index 2c1f29842..d9c373cb0 100644
+--- a/lib/backend/ndb/rpmxdb.c
++++ b/lib/backend/ndb/rpmxdb.c
+@@ -755,7 +755,7 @@ static int moveblobstofront(rpmxdb xdb, struct xdb_slot *afterslot)
+ if (slot2 == xdb->slots)
+ slot2 = 0;
+ }
+- if (slot1->pagecnt < slot2->pagecnt) {
++ if (slot1 && slot2 && slot1->pagecnt < slot2->pagecnt) {
+ struct xdb_slot *tmp = slot1;
+ slot1 = slot2;
+ slot2 = tmp;
+--
+2.27.0
+
diff --git a/backport-Fix-prog-leak-in-parseScript.patch b/backport-Fix-prog-leak-in-parseScript.patch
new file mode 100644
index 0000000..fe0d786
--- /dev/null
+++ b/backport-Fix-prog-leak-in-parseScript.patch
@@ -0,0 +1,35 @@
+From c013821c0c9350b67d9f9a02848e1a7f87fa180b Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Fri, 25 Nov 2022 17:04:11 +0800
+Subject: [PATCH 2/5] Fix prog leak in parseScript
+
+The "prog" will be alloced when using "-p" options, which cause src
+"proc" leak. Add "origproc" to point to src "proc" to fix it.
+---
+ build/parseScript.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/build/parseScript.c b/build/parseScript.c
+index df7919238..f8b693ac6 100644
+--- a/build/parseScript.c
++++ b/build/parseScript.c
+@@ -102,6 +102,7 @@ int parseScript(rpmSpec spec, int parsePart)
+ poptContext optCon = NULL;
+ char *name = NULL;
+ char *prog = xstrdup("/bin/sh");
++ char *origprog = prog;
+ char *file = NULL;
+ int priority = 1000000;
+ struct poptOption optionsTable[] = {
+@@ -482,6 +483,8 @@ exit:
+ free(reqargs);
+ freeStringBuf(sb);
+ free(progArgv);
++ if (origprog != prog)
++ free(origprog);
+ free(prog);
+ free(name);
+ free(file);
+--
+2.27.0
+
diff --git a/backport-Fix-return-value-checks-in-OpenSSL-code.patch b/backport-Fix-return-value-checks-in-OpenSSL-code.patch
new file mode 100644
index 0000000..9ef25c7
--- /dev/null
+++ b/backport-Fix-return-value-checks-in-OpenSSL-code.patch
@@ -0,0 +1,131 @@
+From 1ddaeddffa52f02db198417ebf73cb6c5d432250 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Sun, 7 Feb 2021 16:46:31 -0500
+Subject: [PATCH] Fix return value checks in OpenSSL code
+
+According to `man 3ssl` the only successful return value for
+EVP_PKEY_verify_init() is 1, and EVP_PKEY_CTX_set_rsa_padding() and
+EVP_PKEY_CTX_set_signature_md() can both return 0 or a negative number
+on failure or any positive number on success. BN_bn2binpad() returns -1
+on error, but 0 (an empty key or signature) is also not valid.
+Therefore use != 1 to check the return value of EVP_PKEY_verify_init(),
+<= 0 to check the return values of the other three functions mentioned
+above. Also delete a bunch of cruft.
+---
+ rpmio/digest_openssl.c | 55 +++++++++++---------------------------------------
+ 1 file changed, 12 insertions(+), 43 deletions(-)
+
+diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c
+index 0cb781e..20c272d 100644
+--- a/rpmio/digest_openssl.c
++++ b/rpmio/digest_openssl.c
+@@ -450,7 +450,7 @@ static void pgpFreeSigRSA(pgpDigAlg pgpsig)
+ static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
+ uint8_t *hash, size_t hashlen, int hash_algo)
+ {
+- int rc, ret;
++ int rc = 1; /* assume failure */
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ struct pgpDigSigRSA_s *sig = pgpsig->data;
+
+@@ -458,53 +458,32 @@ static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
+
+ struct pgpDigKeyRSA_s *key = pgpkey->data;
+
+- if (!constructRSASigningKey(key)) {
+- rc = 1;
++ if (!constructRSASigningKey(key))
+ goto done;
+- }
+
+ pkey_ctx = EVP_PKEY_CTX_new(key->evp_pkey, NULL);
+- if (!pkey_ctx) {
+- rc = 1;
++ if (!pkey_ctx)
+ goto done;
+- }
+
+- ret = EVP_PKEY_verify_init(pkey_ctx);
+- if (ret < 0) {
+- rc = 1;
++ if (EVP_PKEY_verify_init(pkey_ctx) != 1)
+ goto done;
+- }
+
+- ret = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING);
+- if (ret < 0) {
+- rc = 1;
++ if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING) <= 0)
+ goto done;
+- }
+
+- ret = EVP_PKEY_CTX_set_signature_md(pkey_ctx, getEVPMD(hash_algo));
+- if (ret < 0) {
+- rc = 1;
++ if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, getEVPMD(hash_algo)) <= 0)
+ goto done;
+- }
+
+ int pkey_len = EVP_PKEY_size(key->evp_pkey);
+ padded_sig = xcalloc(1, pkey_len);
+- if (!BN_bn2binpad(sig->bn, padded_sig, pkey_len)) {
+- rc = 1;
++ if (BN_bn2binpad(sig->bn, padded_sig, pkey_len) <= 0)
+ goto done;
+- }
+
+- ret = EVP_PKEY_verify(pkey_ctx, padded_sig, pkey_len, hash, hashlen);
+- if (ret == 1)
++ if (EVP_PKEY_verify(pkey_ctx, padded_sig, pkey_len, hash, hashlen) == 1)
+ {
+ /* Success */
+ rc = 0;
+ }
+- else
+- {
+- /* Failure */
+- rc = 1;
+- }
+
+ done:
+ EVP_PKEY_CTX_free(pkey_ctx);
+@@ -735,32 +714,22 @@ static void pgpFreeSigDSA(pgpDigAlg pgpsig)
+ static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
+ uint8_t *hash, size_t hashlen, int hash_algo)
+ {
+- int rc, ret;
++ int rc = 1; /* assume failure */
+ struct pgpDigSigDSA_s *sig = pgpsig->data;
+
+ struct pgpDigKeyDSA_s *key = pgpkey->data;
+
+- if (!constructDSASigningKey(key)) {
+- rc = 1;
++ if (!constructDSASigningKey(key))
+ goto done;
+- }
+
+- if (!constructDSASignature(sig)) {
+- rc = 1;
++ if (!constructDSASignature(sig))
+ goto done;
+- }
+
+- ret = DSA_do_verify(hash, hashlen, sig->dsa_sig, key->dsa_key);
+- if (ret == 1)
++ if (DSA_do_verify(hash, hashlen, sig->dsa_sig, key->dsa_key) == 1)
+ {
+ /* Success */
+ rc = 0;
+ }
+- else
+- {
+- /* Failure */
+- rc = 1;
+- }
+
+ done:
+ return rc;
+--
+1.8.3.1
+
diff --git a/backport-Fix-rpm-lua-rpm_vercmp-error-message-if-second-argum.patch b/backport-Fix-rpm-lua-rpm_vercmp-error-message-if-second-argum.patch
new file mode 100644
index 0000000..f2be2bc
--- /dev/null
+++ b/backport-Fix-rpm-lua-rpm_vercmp-error-message-if-second-argum.patch
@@ -0,0 +1,26 @@
+From cf3150509ed7eb2407bdf1f5572cd613a30c2b86 Mon Sep 17 00:00:00 2001
+From: Vyacheslav Potoropin <vpotoropin@almalinux.org>
+Date: Thu, 25 Aug 2022 23:08:09 +0200
+Subject: [PATCH] Fix rpm lua rpm_vercmp error message if second argument is
+ broken
+
+---
+ rpmio/rpmlua.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c
+index 3f0bdeb3f..615146fab 100644
+--- a/rpmio/rpmlua.c
++++ b/rpmio/rpmlua.c
+@@ -491,7 +491,7 @@ static int rpm_vercmp(lua_State *L)
+ } else {
+ if (v1 == NULL)
+ luaL_argerror(L, 1, "invalid version ");
+- if (v1 == NULL)
++ if (v2 == NULL)
+ luaL_argerror(L, 2, "invalid version ");
+ }
+ rpmverFree(v1);
+--
+2.33.0
+
diff --git a/backport-Fix-rpmDigestBundleFinal-and-Update-return-code-on-i.patch b/backport-Fix-rpmDigestBundleFinal-and-Update-return-code-on-i.patch
new file mode 100644
index 0000000..b1dd56d
--- /dev/null
+++ b/backport-Fix-rpmDigestBundleFinal-and-Update-return-code-on-i.patch
@@ -0,0 +1,40 @@
+From 3a50688558f18cfb250b2e70bc34464a8e089d32 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 20 Jun 2023 09:34:47 +0300
+Subject: [PATCH] Fix rpmDigestBundleFinal() and Update() return code on
+ invalid arguments
+
+Discovered via #2548, these functions merrily return zero for success
+when passed NULL data. In rpm nothing bothers to check for their return
+codes but it doesn't mean it's the right thing to do
+---
+ rpmio/digest.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/rpmio/digest.c b/rpmio/digest.c
+index 1975fe6b9..9c679d820 100644
+--- a/rpmio/digest.c
++++ b/rpmio/digest.c
+@@ -77,8 +77,9 @@ int rpmDigestBundleAddID(rpmDigestBundle bundle, int algo, int id,
+ }
+ int rpmDigestBundleUpdate(rpmDigestBundle bundle, const void *data, size_t len)
+ {
+- int rc = 0;
++ int rc = -1;
+ if (bundle && data && len > 0) {
++ rc = 0;
+ for (int i = 0; i <= bundle->index_max; i++) {
+ if (bundle->ids[i] > 0)
+ rc += rpmDigestUpdate(bundle->digests[i], data, len);
+@@ -91,7 +92,7 @@ int rpmDigestBundleUpdate(rpmDigestBundle bundle, const void *data, size_t len)
+ int rpmDigestBundleFinal(rpmDigestBundle bundle, int id,
+ void ** datap, size_t * lenp, int asAscii)
+ {
+- int rc = 0;
++ int rc = -1;
+ int ix = findID(bundle, id);
+
+ if (ix >= 0) {
+--
+2.27.0
+
diff --git a/backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch b/backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch
new file mode 100644
index 0000000..58bd285
--- /dev/null
+++ b/backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch
@@ -0,0 +1,67 @@
+From dce44771b2a3325b3dc1ebfe41027df9910a39fd Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 11 Feb 2022 13:18:11 +0200
+Subject: [PATCH] Fix + sanitize the hardlink metadata setting logic
+
+Fix the initial setmeta value to something meaningful: we will never
+set metadata on skipped files, and hardlinks are handled with a special
+logic during install. They'd need different kind of special logic on
+FA_TOUCH so just play it safe and always apply metadata on those.
+
+Harlink metadata setting on install should happen on the *last* entry
+of hardlinked set that gets installed (wrt various skip scenarios)
+as otherwise creating those additional links affects the timestamp.
+Note in particular the "last file of..." case in fsmMkfile() where we
+the comment said just that, but set the metadata on the *first* file
+which would then be NULL'ed away.
+
+This all gets current masked by the fact that we do the metadata setting on
+a separate round, but that is about to change plus this makes the overall
+logic clearer anyhow.
+---
+ lib/fsm.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index 82610c7..d9cfe6f 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -193,7 +193,6 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ /* Create hard links for others and avoid redundant metadata setting */
+ if (*firstlink != fp) {
+ rc = fsmLink((*firstlink)->fpath, fp->fpath);
+- fp->setmeta = 0;
+ }
+ fd = *firstlinkfile;
+ }
+@@ -204,7 +203,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ rc = fsmUnpack(fi, fd, psm, nodigest);
+ /* Last file of hardlink set, ensure metadata gets set */
+ if (*firstlink) {
+- (*firstlink)->setmeta = 1;
++ fp->setmeta = 1;
+ *firstlink = NULL;
+ *firstlinkfile = NULL;
+ }
+@@ -797,7 +796,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ else
+ fp->action = rpmfsGetAction(fs, fx);
+ fp->skip = XFA_SKIPPING(fp->action);
+- fp->setmeta = 1;
+ if (XFA_CREATING(fp->action) && !S_ISDIR(rpmfiFMode(fi)))
+ fp->suffix = tid;
+ fp->fpath = fsmFsPath(fi, fp->suffix);
+@@ -805,6 +803,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ /* Remap file perms, owner, and group. */
+ rc = rpmfiStat(fi, 1, &fp->sb);
+
++ /* Hardlinks are tricky and handled elsewhere for install */
++ fp->setmeta = (fp->skip == 0) &&
++ (fp->sb.st_nlink == 1 || fp->action == FA_TOUCH);
++
+ setFileState(fs, fx);
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
+
+--
+1.8.3.1
+
diff --git a/backport-Fix-sbp-leak-when-running-rpmbuild-with-quiet.patch b/backport-Fix-sbp-leak-when-running-rpmbuild-with-quiet.patch
new file mode 100644
index 0000000..0c98b86
--- /dev/null
+++ b/backport-Fix-sbp-leak-when-running-rpmbuild-with-quiet.patch
@@ -0,0 +1,28 @@
+From 6130bd31038ff17a03fcac6ec7e41ac744163dde Mon Sep 17 00:00:00 2001
+From: xujing <xujing125@huawei.com>
+Date: Sat, 26 Nov 2022 11:39:48 +0800
+Subject: [PATCH 4/5] Fix *sbp leak when running rpmbuild with --quiet
+
+When running rpmbuild with --quiet, the "*sbp" may be alloced many
+times in buildSpec by calling doScript but only freed once. Fix it.
+---
+ build/build.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/build/build.c b/build/build.c
+index 9cd569b83..4437f6c9c 100644
+--- a/build/build.c
++++ b/build/build.c
+@@ -216,6 +216,9 @@ rpmRC doScript(rpmSpec spec, rpmBuildFlags what, const char *name,
+ buildCmd = rpmExpand(mCmd, " ", scriptName, NULL);
+ (void) poptParseArgvString(buildCmd, &argc, &argv);
+
++ if (sb_stdoutp && *sb_stdoutp)
++ *sb_stdoutp = freeStringBuf(*sb_stdoutp);
++
+ rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd);
+ if (rpmfcExec((ARGV_const_t)argv, NULL, sb_stdoutp, 1,
+ spec->buildSubdir)) {
+--
+2.27.0
+
diff --git a/backport-Fix-short-circuiting-of-version-strings-in-expressio.patch b/backport-Fix-short-circuiting-of-version-strings-in-expressio.patch
new file mode 100644
index 0000000..9effafb
--- /dev/null
+++ b/backport-Fix-short-circuiting-of-version-strings-in-expressio.patch
@@ -0,0 +1,50 @@
+From 321933f060896f721e361a1c8a8d3731bdcee827 Mon Sep 17 00:00:00 2001
+From: Michael Schroeder <mls@suse.de>
+Date: Wed, 22 Jun 2022 14:07:01 +0200
+Subject: [PATCH] Fix short circuiting of version strings in expressions
+
+We use an empty string when discarding a value due to short circuiting, but
+an empty string is not allowed for versions. So use "0" in that case.
+
+Fixes: #1883
+---
+ rpmio/expression.c | 2 +-
+ tests/rpmmacro.at | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/rpmio/expression.c b/rpmio/expression.c
+index a389a04..98a44bb 100644
+--- a/rpmio/expression.c
++++ b/rpmio/expression.c
+@@ -477,7 +477,7 @@ static int rdToken(ParseState state)
+ if (qtok == TOK_STRING) {
+ v = valueMakeString(temp);
+ } else {
+- v = valueMakeVersion(temp);
++ v = valueMakeVersion(state->flags & RPMEXPR_DISCARD ? "0" : temp);
+ free(temp); /* version doesn't take ownership of the string */
+ if (v == 0) {
+ exprErr(state, _("invalid version"), p+1);
+diff --git a/tests/rpmmacro.at b/tests/rpmmacro.at
+index d1490b4..c4376d4 100644
+--- a/tests/rpmmacro.at
++++ b/tests/rpmmacro.at
+@@ -533,6 +533,7 @@ runroot rpm \
+ --eval '%["%{aaa}"]' \
+ --eval '%[%{?ccc}]' \
+ --eval '%[v"1:2.3-4"]' \
++ --eval '%[v"0" && v"0"]' \
+ ]],
+ [0],
+ [4096
+@@ -542,6 +543,7 @@ runroot rpm \
+ 5
+ 0
+ 1:2.3-4
++0
+ ],
+ [])
+ AT_CLEANUP
+--
+1.8.3.1
+
diff --git a/backport-Fix-some-Lua-stack-leaks-in-our-initialization-code.patch b/backport-Fix-some-Lua-stack-leaks-in-our-initialization-code.patch
new file mode 100644
index 0000000..7166cce
--- /dev/null
+++ b/backport-Fix-some-Lua-stack-leaks-in-our-initialization-code.patch
@@ -0,0 +1,35 @@
+From 3aa1abc4cabaa77bd9d3d05064466990d7e68a59 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 18 Nov 2021 11:53:17 +0200
+Subject: [PATCH] Fix some Lua stack leaks in our initialization code
+
+---
+ rpmio/rpmlua.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c
+index 8459cd8..6ad9119 100644
+--- a/rpmio/rpmlua.c
++++ b/rpmio/rpmlua.c
+@@ -131,14 +131,18 @@ rpmlua rpmluaNew()
+
+ for (lib = extlibs; lib->name; lib++) {
+ luaL_requiref(L, lib->name, lib->func, 1);
++ lua_pop(L, 1);
+ }
+ lua_pushcfunction(L, rpm_print);
+ lua_setglobal(L, "print");
+
+ lua_getglobal(L, "os");
+ luaL_setfuncs(L, os_overrides, 0);
++ lua_pop(L, 1);
++
+ lua_getglobal(L, "posix");
+ luaL_setfuncs(L, posix_overrides, 0);
++ lua_pop(L, 1);
+
+ lua_getglobal(L, "package");
+ lua_pushfstring(L, "%s/%s", rpmConfigDir(), "/lua/?.lua");
+--
+1.8.3.1
+
diff --git a/backport-Fix-use-after-free-in-haveSignature.patch b/backport-Fix-use-after-free-in-haveSignature.patch
new file mode 100644
index 0000000..869d0d3
--- /dev/null
+++ b/backport-Fix-use-after-free-in-haveSignature.patch
@@ -0,0 +1,33 @@
+From ae3d2d234ae47ff85229d3fce97a266fa1aa5a61 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Fri, 7 Jan 2022 13:57:24 +0100
+Subject: [PATCH] Fix use-after-free in haveSignature()
+
+pgpPrtParams() may leave sig2 unchanged and if we're not in the very
+first iteration of the while() loop, we could pass a freed pointer to
+pgpDigParamsCmp(). Fix by setting it to NULL after freeing.
+
+Found by Coverity, after commit bd36c5d (subkey binding validation),
+although note that the commit didn't introduce this bug; it just seems
+to have been a false negative that got "fixed" by the changes in
+pgpPrtParams() in that commit.
+---
+ sign/rpmgensig.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
+index d8c84e9..e88f9b7 100644
+--- a/sign/rpmgensig.c
++++ b/sign/rpmgensig.c
+@@ -364,7 +364,7 @@ static int haveSignature(rpmtd sigtd, Header h)
+ pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2);
+ if (pgpDigParamsCmp(sig1, sig2) == 0)
+ rc = 1;
+- pgpDigParamsFree(sig2);
++ sig2 = pgpDigParamsFree(sig2);
+ }
+ pgpDigParamsFree(sig1);
+ rpmtdFreeData(&oldtd);
+--
+1.8.3.1
+
diff --git a/backport-Ignore-subkeys-that-cannot-be-used-for-signing.patch b/backport-Ignore-subkeys-that-cannot-be-used-for-signing.patch
new file mode 100644
index 0000000..bb6b95c
--- /dev/null
+++ b/backport-Ignore-subkeys-that-cannot-be-used-for-signing.patch
@@ -0,0 +1,104 @@
+From a9cca032a2b7c0c6bcacc6ab4ecd25c95cc75305 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Sun, 27 Mar 2022 12:49:07 -0400
+Subject: [PATCH] Ignore subkeys that cannot be used for signing
+
+This ensures that a signature is only accepted if the subkey that made
+it is actually allowed to sign. Test 265 verifies that RPM ignores
+subkeys that cannot sign.
+
+A subkey is considered to be capable of signing if, and only if, its
+subkey binding signature has a hashed key flags subpacket that contains
+the flag 0x02. RFC4880 requires that the subkey binding signature be
+v4, which this requirement enforces implicitly. RFC4880 also requires
+that primary key binding signatures be present and checked. This is not
+yet implemented, but may be implemented later.
+
+Fixes #1911.
+---
+ rpmio/rpmpgp.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
+ tests/rpmsigdig.at | 2 --
+ 2 files changed, 47 insertions(+), 3 deletions(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 66837b1..22ac9c8 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1133,6 +1133,31 @@ static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig,
+ return rc;
+ }
+
++static int parseSubkeySig(const struct pgpPkt *pkt, uint8_t tag,
++ pgpDigParams *params_p) {
++ pgpDigParams params = *params_p = NULL; /* assume failure */
++
++ if (pkt->tag != PGPTAG_SIGNATURE)
++ goto fail;
++
++ params = pgpDigParamsNew(tag);
++
++ if (pgpPrtSig(tag, pkt->body, pkt->blen, params))
++ goto fail;
++
++ if (params->sigtype != PGPSIGTYPE_SUBKEY_BINDING &&
++ params->sigtype != PGPSIGTYPE_SUBKEY_REVOKE)
++ {
++ goto fail;
++ }
++
++ *params_p = params;
++ return 0;
++fail:
++ pgpDigParamsFree(params);
++ return -1;
++}
++
+ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
+ pgpDigParams * ret)
+ {
+@@ -1238,7 +1263,28 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
+ pgpDigParamsFree(digps[count]);
+ continue;
+ }
+- count++;
++
++ pgpDigParams subkey_sig = NULL;
++ if (decodePkt(p, pend - p, &pkt) ||
++ parseSubkeySig(&pkt, 0, &subkey_sig))
++ {
++ pgpDigParamsFree(digps[count]);
++ break;
++ }
++
++ /* Is the subkey revoked or incapable of signing? */
++ int ignore = subkey_sig->sigtype != PGPSIGTYPE_SUBKEY_BINDING ||
++ !((subkey_sig->saved & PGPDIG_SIG_HAS_KEY_FLAGS) &&
++ (subkey_sig->key_flags & 0x02));
++ if (ignore) {
++ pgpDigParamsFree(digps[count]);
++ } else {
++ digps[count]->key_flags = subkey_sig->key_flags;
++ digps[count]->saved |= PGPDIG_SIG_HAS_KEY_FLAGS;
++ count++;
++ }
++ p += (pkt.body - pkt.head) + pkt.blen;
++ pgpDigParamsFree(subkey_sig);
+ }
+ }
+ rc = (p == pend) ? 0 : -1;
+diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
+index 5d781d8..ab9b473 100644
+--- a/tests/rpmsigdig.at
++++ b/tests/rpmsigdig.at
+@@ -247,8 +247,6 @@ UNW2iqnN3BA7guhOv6OMiROF1+I7Q5nWT63mQC7IgQ==
+ gpg(rpm.org RSA testkey <rsa@rpm.org>) = 4:4344591e1964c5fc-58e63918
+ gpg(1964c5fc) = 4:4344591e1964c5fc-58e63918
+ gpg(4344591e1964c5fc) = 4:4344591e1964c5fc-58e63918
+-gpg(f00650f8) = 4:185e6146f00650f8-58e63918
+-gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918
+ ],
+ [])
+ AT_CLEANUP
+--
+1.8.3.1
+
diff --git a/backport-Make-pgpPubkeyFingerprint-do-something-meaningful-ag.patch b/backport-Make-pgpPubkeyFingerprint-do-something-meaningful-ag.patch
new file mode 100644
index 0000000..8cac6e0
--- /dev/null
+++ b/backport-Make-pgpPubkeyFingerprint-do-something-meaningful-ag.patch
@@ -0,0 +1,64 @@
+From dc9e8169790eba18130fb96c13f56ecba6c9b346 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 6 Sep 2022 09:28:10 +0300
+Subject: [PATCH] Make pgpPubkeyFingerprint() do something meaningful again
+
+Commit 4bbeec134aab33e24f960be28a7b2198359c1f67 "fixed" an old
+terminology confusion about keyid vs fingerprint, but in the process
+broke pgpPubkeyFingerprint() for any external callers, as it now only
+feeds on decoded packets whereas before it did the decoding by itself.
+Add the decoding step back to the public function to make it usable outside
+rpmpgp_internal.c again, retrieving a fingerprint seems like an useful
+(public) API to have.
+
+This is kind of a regression fix in that prior to commit
+4bbeec134aab33e24f960be28a7b2198359c1f67 pgpPubkeyFingerprint() returned
+meaningful data to the outside caller and afterwards it didn't, however
+that commit broke the API anyhow so it's kinda complicated.
+Maybe we should just call it a bugfix and be done with it.
+
+Related to #1549
+---
+ rpmio/rpmpgp.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index d4dd4b89d..8d0d76869 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -650,7 +650,7 @@ static int pgpPrtUserID(pgpTag tag, const uint8_t *h, size_t hlen,
+ return 0;
+ }
+
+-int pgpPubkeyFingerprint(const uint8_t *h, size_t hlen,
++static int getPubkeyFingerprint(const uint8_t *h, size_t hlen,
+ uint8_t **fp, size_t *fplen)
+ {
+ int rc = -1; /* assume failure */
+@@ -717,11 +717,22 @@ int pgpPubkeyFingerprint(const uint8_t *h, size_t hlen,
+ return rc;
+ }
+
++int pgpPubkeyFingerprint(const uint8_t * pkt, size_t pktlen,
++ uint8_t **fp, size_t *fplen)
++{
++ struct pgpPkt p;
++
++ if (decodePkt(pkt, pktlen, &p))
++ return -1;
++
++ return getPubkeyFingerprint(p.body, p.blen, fp, fplen);
++}
++
+ static int getKeyID(const uint8_t *h, size_t hlen, pgpKeyID_t keyid)
+ {
+ uint8_t *fp = NULL;
+ size_t fplen = 0;
+- int rc = pgpPubkeyFingerprint(h, hlen, &fp, &fplen);
++ int rc = getPubkeyFingerprint(h, hlen, &fp, &fplen);
+ if (fp && fplen > 8) {
+ memcpy(keyid, (fp + (fplen-8)), 8);
+ free(fp);
+--
+2.33.0
+
diff --git a/backport-Make-rpmfiSetFX-return-code-meaningful.patch b/backport-Make-rpmfiSetFX-return-code-meaningful.patch
new file mode 100644
index 0000000..e1e475b
--- /dev/null
+++ b/backport-Make-rpmfiSetFX-return-code-meaningful.patch
@@ -0,0 +1,51 @@
+From 318efbaec80a90f1d9ac76d0cd433f6ea3c103fa Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 10 Feb 2022 10:07:06 +0200
+Subject: [PATCH] Make rpmfiSetFX() return code meaningful
+
+Up to now, rpmfiSetFX() has returned the previous file index on success,
+and -1 on error. Which seems okay on the outset, but on a just
+initialized iterator the file index is at -1 which means the returned
+-1 sometimes indicates an error and sometimes success. This is so broken
+that none of the callers even try to use it (grep for it). Which is
+lucky in the sense that it means we can change it.
+
+Simply return the newly set index on success and -1 on error, it may
+not be the greatest return code on earth but at least it's
+non-ambiguous.
+---
+ lib/rpmfi.c | 2 +-
+ lib/rpmfi.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/lib/rpmfi.c b/lib/rpmfi.c
+index 30e0738..4965aee 100644
+--- a/lib/rpmfi.c
++++ b/lib/rpmfi.c
+@@ -314,9 +314,9 @@ int rpmfiSetFX(rpmfi fi, int fx)
+ int i = -1;
+
+ if (fi != NULL && fx >= 0 && fx < rpmfilesFC(fi->files)) {
+- i = fi->i;
+ fi->i = fx;
+ fi->j = rpmfilesDI(fi->files, fi->i);
++ i = fi->i;
+ }
+ return i;
+ }
+diff --git a/lib/rpmfi.h b/lib/rpmfi.h
+index 989582b..52310c6 100644
+--- a/lib/rpmfi.h
++++ b/lib/rpmfi.h
+@@ -39,7 +39,7 @@ int rpmfiFX(rpmfi fi);
+ * Set current file index in file info set iterator.
+ * @param fi file info set iterator
+ * @param fx new file index
+- * @return current file index
++ * @return new file index, -1 on error
+ */
+ int rpmfiSetFX(rpmfi fi, int fx);
+
+--
+1.8.3.1
+
diff --git a/backport-Move-file-metadata-setting-back-to-unpack-stage.patch b/backport-Move-file-metadata-setting-back-to-unpack-stage.patch
new file mode 100644
index 0000000..ef9071e
--- /dev/null
+++ b/backport-Move-file-metadata-setting-back-to-unpack-stage.patch
@@ -0,0 +1,69 @@
+From da79e3c3ae7da8719f0bf87a1a60e046597b8240 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 11 Feb 2022 13:28:25 +0200
+Subject: [PATCH] Move file metadata setting back to unpack stage
+
+Commit a82251b44ee2d2802ee8aea1b3d89f88beee4bad moved metadata setting
+to a separate step because there are potential benefits to doing so, but
+the current downsides are worse: as long as we operate in potentially
+untrusted directories, we'd need to somehow verify the content is what we
+initially laid down to avoid possible privilege escalation from non-root
+owned directories.
+
+This commit does not fix that vulnerability, only makes the window much
+smaller and paves the way for the real fix(es) without introducing a
+second round of directory tree validation chase to the picture.
+---
+ lib/fsm.c | 22 +++++++---------------
+ 1 file changed, 7 insertions(+), 15 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index d9cfe6fa9..ae1bd3f48 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -880,7 +880,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+
+ /* When touching we don't need any of this... */
+ if (fp->action == FA_TOUCH)
+- continue;
++ goto setmeta;
+
+ if (S_ISREG(fp->sb.st_mode)) {
+ if (rc == RPMERR_ENOENT) {
+@@ -1143,6 +1143,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ rc = RPMERR_OPEN_FAILED;
+ }
+
++setmeta:
++ if (!rc && fp->setmeta) {
++ rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
++ &fp->sb, nofcaps);
++ }
++
+ if (fd != firstlinkfile)
+ fsmClose(&fd);
+ }
+@@ -931,20 +937,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ if (!rc && fx < 0 && fx != RPMERR_ITER_END)
+ rc = fx;
+
+- /* Set permissions, timestamps etc for non-hardlink entries */
+- fi = rpmfilesIter(files, RPMFI_ITER_FWD);
+- while (!rc && (fx = rpmfiNext(fi)) >= 0) {
+- struct filedata_s *fp = &fdata[fx];
+- if (!fp->skip && fp->setmeta) {
+- rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
+- &fp->sb, nofcaps);
+- }
+- if (rc)
+- *failedFile = xstrdup(fp->fpath);
+- fp->stage = FILE_PREP;
+- }
+- fi = rpmfiFree(fi);
+-
+ /* If all went well, commit files to final destination */
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
+--
+2.27.0
+
diff --git a/backport-Parse-key-usage-flags.patch b/backport-Parse-key-usage-flags.patch
new file mode 100644
index 0000000..3d20288
--- /dev/null
+++ b/backport-Parse-key-usage-flags.patch
@@ -0,0 +1,78 @@
+From 598a771d8b4f4f480d4990ccf59b978d537201dd Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Sun, 27 Mar 2022 12:07:34 -0400
+Subject: [PATCH] Parse key usage flags
+
+RPM needs to know if a subkey can be used for signing. Signatures made
+by a subkey that cannot be used for signing are invalid. Add a
+key_flags member to pgpDigParams_s to store this information, and a
+PGPDIG_SIG_HAS_KEY_FLAGS flag to indicate that it is valid. The key
+usage flags are reset for every signature. Key usage flags in the
+unhashed section are ignored. If there is more than one key usage flags
+subpacket in the hashed section, the signature is rejected.
+---
+ rpmio/digest.h | 2 ++
+ rpmio/rpmpgp.c | 13 ++++++++++++-
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/rpmio/digest.h b/rpmio/digest.h
+index ec7f339..6a326d2 100644
+--- a/rpmio/digest.h
++++ b/rpmio/digest.h
+@@ -28,6 +28,7 @@ struct pgpDigParams_s {
+ const uint8_t * data;
+ uint8_t tag;
+
++ uint8_t key_flags; /*!< key usage flags */
+ uint8_t version; /*!< version number. */
+ uint32_t time; /*!< key/signature creation time. */
+ uint8_t pubkey_algo; /*!< public key algorithm. */
+@@ -41,6 +42,7 @@ struct pgpDigParams_s {
+ #define PGPDIG_SAVED_TIME (1 << 0)
+ #define PGPDIG_SAVED_ID (1 << 1)
+ #define PGPDIG_SIG_HAS_CREATION_TIME (1 << 2)
++#define PGPDIG_SIG_HAS_KEY_FLAGS (1 << 3)
+
+ pgpDigAlg alg;
+ };
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 9b8503e..66837b1 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -500,6 +500,17 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
+ _digp->saved |= PGPDIG_SAVED_ID;
+ memcpy(_digp->signid, p+1, sizeof(_digp->signid));
+ }
++ case PGPSUBTYPE_KEY_FLAGS: /* Key usage flags */
++ /* Subpackets in the unhashed section cannot be trusted */
++ if (!hashed)
++ break;
++ /* Reject duplicate key usage flags */
++ if (_digp->saved & PGPDIG_SIG_HAS_KEY_FLAGS)
++ return 1;
++ impl = *p;
++ _digp->saved |= PGPDIG_SIG_HAS_KEY_FLAGS;
++ _digp->key_flags = plen >= 2 ? p[1] : 0;
++ break;
+ case PGPSUBTYPE_EXPORTABLE_CERT:
+ case PGPSUBTYPE_TRUST_SIG:
+ case PGPSUBTYPE_REGEX:
+@@ -510,7 +521,6 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
+ case PGPSUBTYPE_PREFER_KEYSERVER:
+ case PGPSUBTYPE_PRIMARY_USERID:
+ case PGPSUBTYPE_POLICY_URL:
+- case PGPSUBTYPE_KEY_FLAGS:
+ case PGPSUBTYPE_SIGNER_USERID:
+ case PGPSUBTYPE_REVOKE_REASON:
+ case PGPSUBTYPE_FEATURES:
+@@ -602,6 +612,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+
+ /* Reset the saved flags */
+ _digp->saved &= PGPDIG_SAVED_TIME | PGPDIG_SAVED_ID;
++ _digp->key_flags = 0;
+
+ if (pgpVersion(h, hlen, &version))
+ return rc;
+--
+1.8.3.1
+
diff --git a/backport-Prevent-NULL-deref-in-rpmfsGetStates.patch b/backport-Prevent-NULL-deref-in-rpmfsGetStates.patch
new file mode 100644
index 0000000..771f92e
--- /dev/null
+++ b/backport-Prevent-NULL-deref-in-rpmfsGetStates.patch
@@ -0,0 +1,25 @@
+From d747bf045ea20b0cb5813a83c13bdfb4ca424699 Mon Sep 17 00:00:00 2001
+From: Ludwig Nussel <ludwig.nussel@suse.de>
+Date: Mon, 14 Mar 2022 14:20:56 +0100
+Subject: [PATCH] Prevent NULL deref in rpmfsGetStates()
+
+---
+ lib/rpmfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/rpmfs.c b/lib/rpmfs.c
+index 84887a0..5f91cd2 100644
+--- a/lib/rpmfs.c
++++ b/lib/rpmfs.c
+@@ -98,7 +98,7 @@ rpmfileState rpmfsGetState(rpmfs fs, unsigned int ix)
+
+ rpm_fstate_t * rpmfsGetStates(rpmfs fs)
+ {
+- return fs->states;
++ return (fs != NULL) ? fs->states : NULL;
+ }
+
+ rpmFileAction rpmfsGetAction(rpmfs fs, unsigned int ix)
+--
+1.8.3.1
+
diff --git a/backport-Prevent-readelf-internet-access-during-rpaths-checki.patch b/backport-Prevent-readelf-internet-access-during-rpaths-checki.patch
new file mode 100644
index 0000000..c472084
--- /dev/null
+++ b/backport-Prevent-readelf-internet-access-during-rpaths-checki.patch
@@ -0,0 +1,32 @@
+From 3cec59812c8126088a51924c6aeea112ce9b545a Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 22 Jun 2022 13:22:00 +0300
+Subject: [PATCH] Prevent readelf internet access during rpaths checking
+ (RhBug:2079600)
+
+Recent binutils can do debug section lookups over the internet, but this
+is something we never want during rpmbuild (everything else aside, we're
+just building the thing so there wont be anything on the net anyhow).
+Disable the lookups by setting DEBUGINFOD_URLS to empty rather than
+using the specific option as this is compatible with any old version of
+readelf.
+---
+ scripts/check-rpaths-worker | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/check-rpaths-worker b/scripts/check-rpaths-worker
+index e32e823..26f74f0 100755
+--- a/scripts/check-rpaths-worker
++++ b/scripts/check-rpaths-worker
+@@ -94,7 +94,7 @@ function msg()
+
+ function check_rpath() {
+ pos=0
+- rpath=$(readelf -W -d "$1" 2>/dev/null | LANG=C grep -E "\((RPATH|RUNPATH)\).*:") || return 0
++ rpath=$(DEBUGINFOD_URLS="" readelf -W -d "$1" 2>/dev/null | LANG=C grep -E "\((RPATH|RUNPATH)\).*:") || return 0
+ rpath=$(echo "$rpath" | LANG=C sed -e "s!.*\(RPATH\|RUNPATH\).*: \[\(.*\)\]!\2!p;d")
+
+ tmp=aux:$rpath:/lib/aux || :
+--
+1.8.3.1
+
diff --git a/backport-Process-MPI-s-from-all-kinds-of-signatures.patch b/backport-Process-MPI-s-from-all-kinds-of-signatures.patch
new file mode 100644
index 0000000..457b406
--- /dev/null
+++ b/backport-Process-MPI-s-from-all-kinds-of-signatures.patch
@@ -0,0 +1,57 @@
+From b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 30 Sep 2021 09:51:10 +0300
+Subject: [PATCH] Process MPI's from all kinds of signatures
+
+No immediate effect but needed by the following commits.
+---
+ rpmio/rpmpgp.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index ee5c81e..340de5f 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -543,7 +543,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
+ return NULL;
+ }
+
+-static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
++static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo,
+ const uint8_t *p, const uint8_t *h, size_t hlen,
+ pgpDigParams sigp)
+ {
+@@ -556,10 +556,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
+ int mpil = pgpMpiLen(p);
+ if (pend - p < mpil)
+ break;
+- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
+- if (sigalg->setmpi(sigalg, i, p))
+- break;
+- }
++ if (sigalg->setmpi(sigalg, i, p))
++ break;
+ p += mpil;
+ }
+
+@@ -618,7 +618,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+
+ p = ((uint8_t *)v) + sizeof(*v);
+ _digp->data = p;
+- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
+ } break;
+ case 4:
+ { pgpPktSigV4 v = (pgpPktSigV4)h;
+@@ -678,7 +678,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ return 1;
+
+ _digp->data = p;
+- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
+ } break;
+ default:
+ rpmlog(RPMLOG_WARNING, _("Unsupported version of signature: V%d\n"), version);
+--
+1.8.3.1
+
diff --git a/backport-Refactor-pgpDigParams-construction-to-helper-functio.patch b/backport-Refactor-pgpDigParams-construction-to-helper-functio.patch
new file mode 100644
index 0000000..05287be
--- /dev/null
+++ b/backport-Refactor-pgpDigParams-construction-to-helper-functio.patch
@@ -0,0 +1,52 @@
+From 9f03f42e2614a68f589f9db8fe76287146522c0c Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 30 Sep 2021 09:56:20 +0300
+Subject: [PATCH] Refactor pgpDigParams construction to helper function
+
+No functional changes, just to reduce code duplication and needed by
+the following commits.
+---
+ rpmio/rpmpgp.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 340de5f..aad7c27 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1055,6 +1055,13 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype)
+ return algo;
+ }
+
++static pgpDigParams pgpDigParamsNew(uint8_t tag)
++{
++ pgpDigParams digp = xcalloc(1, sizeof(*digp));
++ digp->tag = tag;
++ return digp;
++}
++
+ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
+ pgpDigParams * ret)
+ {
+@@ -1072,8 +1079,7 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
+ if (pkttype && pkt.tag != pkttype) {
+ break;
+ } else {
+- digp = xcalloc(1, sizeof(*digp));
+- digp->tag = pkt.tag;
++ digp = pgpDigParamsNew(pkt.tag);
+ }
+ }
+
+@@ -1121,8 +1127,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
+ digps = xrealloc(digps, alloced * sizeof(*digps));
+ }
+
+- digps[count] = xcalloc(1, sizeof(**digps));
+- digps[count]->tag = PGPTAG_PUBLIC_SUBKEY;
++ digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY);
+ /* Copy UID from main key to subkey */
+ digps[count]->userid = xstrdup(mainkey->userid);
+
+--
+1.8.3.1
+
diff --git a/backport-Remove-obscure-check-for-package-build-time-from-reb.patch b/backport-Remove-obscure-check-for-package-build-time-from-reb.patch
new file mode 100644
index 0000000..2bd4c62
--- /dev/null
+++ b/backport-Remove-obscure-check-for-package-build-time-from-reb.patch
@@ -0,0 +1,41 @@
+From 6caf2a5f586838f6188dd6667a4df6d9c6ec0163 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 1 Jun 2023 09:45:01 +0300
+Subject: [PATCH] Remove obscure check for package build time from --rebuilddb
+ (#2527)
+
+Back in 1997, commit be0b90359bcd8156385178eb9b570c0538c0333f added a
+sanity check for --rebuilddb operation, skipping headers which lack
+some basic tags. Name, version and release are real requirements for
+packages, but checking for buildtime is odd, and plain wrong.
+Yes, we expect that to be present in packages built by rpm, but that's
+not used for any processing and certainly is not required for a package
+to be installable. And if it can be installed then it can't be
+right to throw it away when rebuilding, leaving untrackable orphan
+files in the process.
+
+It is also documented as informational and optional by LSB. While
+severely outdated, it is right on this account.
+
+Fixes: #2527
+---
+ lib/rpmdb.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/lib/rpmdb.c b/lib/rpmdb.c
+index b51e9f09e..361f04150 100644
+--- a/lib/rpmdb.c
++++ b/lib/rpmdb.c
+@@ -2470,8 +2470,7 @@ int rpmdbRebuild(const char * prefix, rpmts ts,
+ /* let's sanity check this record a bit, otherwise just skip it */
+ if (!(headerIsEntry(h, RPMTAG_NAME) &&
+ headerIsEntry(h, RPMTAG_VERSION) &&
+- headerIsEntry(h, RPMTAG_RELEASE) &&
+- headerIsEntry(h, RPMTAG_BUILDTIME)))
++ headerIsEntry(h, RPMTAG_RELEASE)))
+ {
+ rpmlog(RPMLOG_ERR,
+ _("header #%u in the database is bad -- skipping.\n"),
+--
+2.27.0
+
diff --git a/backport-Require-creation-time-to-be-unique-and-hashed.patch b/backport-Require-creation-time-to-be-unique-and-hashed.patch
new file mode 100644
index 0000000..5268282
--- /dev/null
+++ b/backport-Require-creation-time-to-be-unique-and-hashed.patch
@@ -0,0 +1,101 @@
+From 7e7266c9af883ce49b3516a5bd099d218e8e3fac Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Sun, 6 Feb 2022 15:52:48 -0500
+Subject: [PATCH] Require creation time to be unique and hashed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+According to RFC 4880 §5.2.3.4 the signature creation time MUST be a
+hashed subpacket. Enforce this requirement in RPM. Also set the saved
+flags to PGPDIG_SAVED_TIME | PGPDIG_SAVED_ID |
+PGPDIG_SAVED_CREATION_TIME for v3 signatures, and do not overwrite an
+already saved key ID with one taken from a v3 signature.
+---
+ rpmio/digest.h | 4 +++-
+ rpmio/rpmpgp.c | 29 +++++++++++++++++++----------
+ 2 files changed, 22 insertions(+), 11 deletions(-)
+
+diff --git a/rpmio/digest.h b/rpmio/digest.h
+index 3b72a28..ec7f339 100644
+--- a/rpmio/digest.h
++++ b/rpmio/digest.h
+@@ -36,9 +36,11 @@ struct pgpDigParams_s {
+ uint32_t hashlen;
+ uint8_t signhash16[2];
+ pgpKeyID_t signid;
+- uint8_t saved;
++ uint8_t saved; /*!< Various flags. `PGPDIG_SAVED_*` are never reset.
++ * `PGPDIG_SIG_HAS_*` are reset for each signature. */
+ #define PGPDIG_SAVED_TIME (1 << 0)
+ #define PGPDIG_SAVED_ID (1 << 1)
++#define PGPDIG_SIG_HAS_CREATION_TIME (1 << 2)
+
+ pgpDigAlg alg;
+ };
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index f9e2658..0200900 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -473,16 +473,16 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
+ for (i = 1; i < plen; i++)
+ pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
+ break;
+- case PGPSUBTYPE_SIG_CREATE_TIME:
++ case PGPSUBTYPE_SIG_CREATE_TIME: /* signature creation time */
++ if (plen-1 != sizeof(_digp->time))
++ break; /* other lengths not understood */
++ if (_digp->saved & PGPDIG_SIG_HAS_CREATION_TIME)
++ return 1; /* duplicate timestamps not allowed */
+ impl = *p;
+- if (!(_digp->saved & PGPDIG_SAVED_TIME) &&
+- (sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
+- {
+- if (plen-1 != sizeof(_digp->time))
+- break;
+- _digp->saved |= PGPDIG_SAVED_TIME;
++ if (!(_digp->saved & PGPDIG_SAVED_TIME))
+ _digp->time = pgpGrab(p+1, sizeof(_digp->time));
+- }
++ _digp->saved |= PGPDIG_SAVED_TIME | PGPDIG_SIG_HAS_CREATION_TIME;
++ break;
+ case PGPSUBTYPE_SIG_EXPIRE_TIME:
+ case PGPSUBTYPE_KEY_EXPIRE_TIME:
+ pgpPrtTime(" ", p+1, plen-1);
+@@ -598,6 +598,9 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ unsigned int plen;
+ int rc = 1;
+
++ /* Reset the saved flags */
++ _digp->saved &= PGPDIG_SAVED_TIME | PGPDIG_SAVED_ID;
++
+ if (pgpVersion(h, hlen, &version))
+ return rc;
+
+@@ -625,8 +628,11 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ _digp->hashlen = v->hashlen;
+ _digp->sigtype = v->sigtype;
+ _digp->hash = memcpy(xmalloc(v->hashlen), &v->sigtype, v->hashlen);
+- _digp->time = pgpGrab(v->time, sizeof(v->time));
+- memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
++ if (!(_digp->saved & PGPDIG_SAVED_TIME))
++ _digp->time = pgpGrab(v->time, sizeof(v->time));
++ if (!(_digp->saved & PGPDIG_SAVED_ID))
++ memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
++ _digp->saved = PGPDIG_SAVED_TIME | PGPDIG_SIG_HAS_CREATION_TIME | PGPDIG_SAVED_ID;
+ _digp->pubkey_algo = v->pubkey_algo;
+ _digp->hash_algo = v->hash_algo;
+ memcpy(_digp->signhash16, v->signhash16, sizeof(_digp->signhash16));
+@@ -664,6 +670,9 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
+ return 1;
+ p += plen;
+
++ if (!(_digp->saved & PGPDIG_SIG_HAS_CREATION_TIME))
++ return 1; /* RFC 4880 §5.2.3.4 creation time MUST be hashed */
++
+ if (pgpGet(p, 2, hend, &plen))
+ return 1;
+ p += 2;
+--
+1.8.3.1
+
diff --git a/backport-Return-descriptor-of-created-file-from-fsmMkfile.patch b/backport-Return-descriptor-of-created-file-from-fsmMkfile.patch
new file mode 100644
index 0000000..bb9bb16
--- /dev/null
+++ b/backport-Return-descriptor-of-created-file-from-fsmMkfile.patch
@@ -0,0 +1,65 @@
+From 693d828c035848585b500dfde6f4e58cfb8d4de4 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 14 Feb 2022 12:44:42 +0200
+Subject: [PATCH] Return descriptor of created file from fsmMkfile()
+
+This will be needed for using fd-based metadata operations.
+---
+ lib/fsm.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index b019f57..7c4796f 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -172,7 +172,8 @@ static int fsmUnpack(rpmfi fi, int fdno, rpmpsm psm, int nodigest)
+
+ static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ rpmpsm psm, int nodigest,
+- struct filedata_s ** firstlink, int *firstlinkfile)
++ struct filedata_s ** firstlink, int *firstlinkfile,
++ int *fdp)
+ {
+ int rc = 0;
+ int fd = -1;
+@@ -204,9 +205,7 @@ static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
+ *firstlinkfile = -1;
+ }
+ }
+-
+- if (fd != *firstlinkfile)
+- fsmClose(&fd);
++ *fdp = fd;
+
+ return rc;
+ }
+@@ -1065,6 +1065,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ fp = firstlink;
+
+ if (!fp->skip) {
++ int fd = -1;
+ /* Directories replacing something need early backup */
+ if (!fp->suffix && fp != firstlink) {
+ rc = fsmBackup(fi, fp->action);
+@@ -910,7 +910,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ if (S_ISREG(fp->sb.st_mode)) {
+ if (rc == RPMERR_ENOENT) {
+ rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
+- &firstlink, &firstlinkfile);
++ &firstlink, &firstlinkfile, &fd);
+ }
+ } else if (S_ISDIR(fp->sb.st_mode)) {
+ if (rc == RPMERR_ENOENT) {
+@@ -1131,6 +1132,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ if (!IS_DEV_LOG(fp->fpath))
+ rc = RPMERR_UNKNOWN_FILETYPE;
+ }
++
++ if (fd != firstlinkfile)
++ fsmClose(&fd);
+ }
+
+ /* Notify on success. */
+--
+1.8.3.1
+
diff --git a/backport-Revert-Explictly-skip-non-installed-files-on-erasur.patch b/backport-Revert-Explictly-skip-non-installed-files-on-erasur.patch
new file mode 100644
index 0000000..cb30a46
--- /dev/null
+++ b/backport-Revert-Explictly-skip-non-installed-files-on-erasur.patch
@@ -0,0 +1,32 @@
+From 26bb41e1cb7f7836302b3555cff8f20f9fc19188 Mon Sep 17 00:00:00 2001
+From: licunlong1 <licunlong1@huawei.com>
+Date: Thu, 21 Oct 2021 21:29:25 +0800
+Subject: [PATCH] don not skip abnormal files
+
+This reverts 2d52726bd55f008ea23262c2a3a31ae689cd2af4, as when removing
+the same file of different archs, if the file state is WRONGCOLOR, it
+sets the action to `skip`. This will result in some elf files left over.
+
+---
+ lib/transaction.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/lib/transaction.c b/lib/transaction.c
+index 55bc2d9..20cf680 100644
+--- a/lib/transaction.c
++++ b/lib/transaction.c
+@@ -689,10 +689,8 @@ assert(otherFi != NULL);
+ }
+ if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
+ break;
+- if (rpmfilesFState(fi, i) != RPMFILE_STATE_NORMAL) {
+- rpmfsSetAction(fs, i, FA_SKIP);
++ if (rpmfilesFState(fi, i) != RPMFILE_STATE_NORMAL)
+ break;
+- }
+
+ /* Pre-existing modified config files need to be saved. */
+ if (rpmfilesConfigConflict(fi, i)) {
+--
+1.8.3.1
+
diff --git a/backport-Simplify-rpm_print-fixing-a-Lua-stack-leak-as-a-bonu.patch b/backport-Simplify-rpm_print-fixing-a-Lua-stack-leak-as-a-bonu.patch
new file mode 100644
index 0000000..c0f0968
--- /dev/null
+++ b/backport-Simplify-rpm_print-fixing-a-Lua-stack-leak-as-a-bonu.patch
@@ -0,0 +1,39 @@
+From d41143cb5f6d88eb6e8bd999ad5ea2992bfb10f7 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 18 Nov 2021 13:38:20 +0200
+Subject: [PATCH] Simplify rpm_print(), fixing a Lua stack leak as a bonus
+
+Rather than laborously call tostring() in Lua, use the C-side equivalent
+of luaL_tostring(). This was new as of Lua 5.2, which explains why the
+original version from 2004 did things the hard way.
+
+Also fixes a stack leak from not popping "tostring" function after use.
+---
+ rpmio/rpmlua.c | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c
+index 6ad9119..7402307 100644
+--- a/rpmio/rpmlua.c
++++ b/rpmio/rpmlua.c
+@@ -688,16 +688,9 @@ static int rpm_print (lua_State *L)
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ if (!lua) return 0;
+- lua_getglobal(L, "tostring");
+ for (i = 1; i <= n; i++) {
+- const char *s;
+ size_t sl;
+- lua_pushvalue(L, -1); /* function to be called */
+- lua_pushvalue(L, i); /* value to print */
+- lua_call(L, 1, 1);
+- s = lua_tolstring(L, -1, &sl); /* get result */
+- if (s == NULL)
+- return luaL_error(L, "`tostring' must return a string to `print'");
++ const char *s = luaL_tolstring(L, i, &sl);
+ if (lua->printbuf) {
+ rpmluapb prbuf = lua->printbuf;
+ if (prbuf->used+sl+1 > prbuf->alloced) {
+--
+1.8.3.1
+
diff --git a/backport-Skip-recorded-symlinks-in-setperms-RhBug-1900662.patch b/backport-Skip-recorded-symlinks-in-setperms-RhBug-1900662.patch
new file mode 100644
index 0000000..1d09f82
--- /dev/null
+++ b/backport-Skip-recorded-symlinks-in-setperms-RhBug-1900662.patch
@@ -0,0 +1,40 @@
+From ed07a187734addfa16be9ee922398e4ff9859f53 Mon Sep 17 00:00:00 2001
+From: Michal Domonkos <mdomonko@redhat.com>
+Date: Tue, 7 Dec 2021 08:08:37 +0100
+Subject: [PATCH] Skip recorded symlinks in --setperms (RhBug:1900662)
+
+If a package contains a symlink in the buildroot which is declared as a
+ghost or config file but is a regular file or directory on the system
+where it's installed, a --setperms call will reset its permissions to
+those of a symlink (777 on Linux), which almost certainly is not the
+correct thing to do.
+
+To fix that, just skip files that were recorded as symlinks.
+
+This is a special case of a general issue in --setperms; since file
+permission semantics may change depending on the file type, to stay on
+the safe side, any (ghost or config) file whose type changes after
+installation should probably be skipped. However, symlinks are the most
+prominent case here, so let's just focus on that now and avoid adding
+too much cleverness to a popt alias (this got us into trouble not too
+long ago, see commits 38c2f6e and 0d83637). We may revisit this in the
+eventual C implementation.
+---
+ rpmpopt.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/rpmpopt.in b/rpmpopt.in
+index 27d2986..d5a6b14 100644
+--- a/rpmpopt.in
++++ b/rpmpopt.in
+@@ -44,6 +44,7 @@ rpm alias --scripts --qf '\
+ --POPTdesc=$"list install/erase scriptlets from package(s)"
+
+ rpm alias --setperms -q --qf '[\[ -L %{FILENAMES:shescape} \] || \
++ \[ -n %{FILELINKTOS:shescape} \] || \
+ ( \[ $((%{FILEFLAGS} & 2#1001000)) != 0 \] && \[ ! -e %{FILENAMES:shescape} \] ) || \
+ chmod %7{FILEMODES:octal} %{FILENAMES:shescape}\n]' \
+ --pipe "grep -v \(none\) | grep '^. -L ' | sed 's/chmod .../chmod /' | sh" \
+--
+1.8.3.1
+
diff --git a/backport-Switch-the-floating-point-type-in-rpmhook-from-float.patch b/backport-Switch-the-floating-point-type-in-rpmhook-from-float.patch
new file mode 100644
index 0000000..1b9a924
--- /dev/null
+++ b/backport-Switch-the-floating-point-type-in-rpmhook-from-float.patch
@@ -0,0 +1,57 @@
+From a34bf5bdf601d6d0ae5d28193090a29b9ef12600 Mon Sep 17 00:00:00 2001
+From: Michael Schroeder <mls@suse.de>
+Date: Mon, 22 Nov 2021 11:12:20 +0100
+Subject: [PATCH] Switch the floating point type in rpmhook from float to
+ double
+
+There's no real reason why it should be float. Plus, the test if
+the number is an integer does not work for big integers that
+do not fit into a float.
+---
+ rpmio/rpmhook.c | 2 +-
+ rpmio/rpmhook.h | 2 +-
+ rpmio/rpmlua.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/rpmio/rpmhook.c b/rpmio/rpmhook.c
+index 9fe2a21..1197983 100644
+--- a/rpmio/rpmhook.c
++++ b/rpmio/rpmhook.c
+@@ -187,7 +187,7 @@ static rpmhookArgs rpmhookArgsParse(const char *argt, va_list ap)
+ args->argv[i].i = va_arg(ap, int);
+ break;
+ case 'f':
+- args->argv[i].f = (float)va_arg(ap, double);
++ args->argv[i].f = va_arg(ap, double);
+ break;
+ case 'p':
+ args->argv[i].p = va_arg(ap, void *);
+diff --git a/rpmio/rpmhook.h b/rpmio/rpmhook.h
+index 52f5634..842c126 100644
+--- a/rpmio/rpmhook.h
++++ b/rpmio/rpmhook.h
+@@ -4,7 +4,7 @@
+ typedef union {
+ const char * s;
+ int i;
+- float f;
++ double f;
+ void * p;
+ } rpmhookArgv;
+
+diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c
+index fe2e513..c5bdf42 100644
+--- a/rpmio/rpmlua.c
++++ b/rpmio/rpmlua.c
+@@ -650,7 +650,7 @@ static int rpm_call(lua_State *L)
+ args->argv[i].p = NULL;
+ break;
+ case LUA_TNUMBER: {
+- float f = (float)lua_tonumber(L, i+1);
++ double f = (double)lua_tonumber(L, i+1);
+ if (f == (int)f) {
+ argt[i] = 'i';
+ args->argv[i].i = (int)f;
+--
+1.8.3.1
+
diff --git a/backport-Use-fd-based-ops-for-metadata-in-FA_TOUCH-mode-too-w.patch b/backport-Use-fd-based-ops-for-metadata-in-FA_TOUCH-mode-too-w.patch
new file mode 100644
index 0000000..c537632
--- /dev/null
+++ b/backport-Use-fd-based-ops-for-metadata-in-FA_TOUCH-mode-too-w.patch
@@ -0,0 +1,46 @@
+From 932013698149d43720cc321c8df2f99f51866e18 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 13 Jan 2023 10:00:37 +0200
+Subject: [PATCH] Use fd-based ops for metadata in FA_TOUCH mode too,
+when
+ possible
+
+Fixes another brainfart in commit 25a435e90844ea98fe5eb7bef22c1aecf3a9c033.
+---
+ lib/fsm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/lib/fsm.c b/lib/fsm.c
+index 54fea90..e6fac40 100644
+--- a/lib/fsm.c
++++ b/lib/fsm.c
+@@ -1002,6 +1002,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
+ int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
+ int firstlinkfile = -1;
++ int mayopen = 0;
+ char *tid = NULL;
+ struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
+ struct filedata_s *firstlink = NULL;
+@@ -1136,8 +1137,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ rc = RPMERR_UNKNOWN_FILETYPE;
+ }
+
++setmeta:
+ /* Special files require path-based ops */
+- int mayopen = S_ISREG(fp->sb.st_mode) || S_ISDIR(fp->sb.st_mode);
++ mayopen = S_ISREG(fp->sb.st_mode) || S_ISDIR(fp->sb.st_mode);
+ if (!rc && fd == -1 && mayopen) {
+ /* Only follow safe symlinks, and never on temporary files */
+ fd = fsmOpenat(di.dirfd, fp->fpath,
+@@ -1146,7 +1148,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
+ rc = RPMERR_OPEN_FAILED;
+ }
+
+-setmeta:
+ if (!rc && fp->setmeta) {
+ rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
+ &fp->sb, nofcaps);
+--
+2.27.0
+
diff --git a/backport-Use-proper-type-for-copyTagsFromMainDebug.patch b/backport-Use-proper-type-for-copyTagsFromMainDebug.patch
new file mode 100644
index 0000000..d60e6fb
--- /dev/null
+++ b/backport-Use-proper-type-for-copyTagsFromMainDebug.patch
@@ -0,0 +1,27 @@
+From 42694806bf73b07514554233d0d58d17a58cd863 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 9 Feb 2023 13:05:24 +0200
+Subject: [PATCH] Use proper type for copyTagsFromMainDebug
+
+The array contains a non-enum value (0), this is why headerCopyTags()
+uses rpmTagVal pointer, not rpmTag.
+---
+ build/files.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/build/files.c b/build/files.c
+index 666c66651..24b4d80bf 100644
+--- a/build/files.c
++++ b/build/files.c
+@@ -2858,7 +2858,7 @@ exit:
+ return rc;
+ }
+
+-static rpmTag copyTagsFromMainDebug[] = {
++static rpmTagVal copyTagsFromMainDebug[] = {
+ RPMTAG_ARCH,
+ RPMTAG_SUMMARY,
+ RPMTAG_DESCRIPTION,
+--
+2.27.0
+
diff --git a/backport-Use-root-as-default-UID_0_USER-and-UID_0_GROUP.patch b/backport-Use-root-as-default-UID_0_USER-and-UID_0_GROUP.patch
new file mode 100644
index 0000000..80b8790
--- /dev/null
+++ b/backport-Use-root-as-default-UID_0_USER-and-UID_0_GROUP.patch
@@ -0,0 +1,29 @@
+From 7b3a3f004f96ed3cb9cc377f7e64bfc88195dfc2 Mon Dec 13 16:41:34 2021
+From: From: Florian Festi <ffesti@redhat.com>
+Date: Mon, 13 Dec 2021 16:41:34 +0800
+Subject: [PATCH] Use root as default UID_0_USER and UID_0_GROUP
+
+If /etc/passwd or /etc/group was not available during building rpm itself
+these ended up empty. This affects builds done later on using rpmbuild.
+
+Resolves: #1838
+---
+ configure.ac | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/configure.ac b/configure.ac
+index cdaf2b6..8656043 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1050,6 +1050,8 @@ fi
+
+ user_with_uid0=$(awk -F: '$3==0 {print $1;exit}' /etc/passwd)
+ group_with_gid0=$(awk -F: '$3==0 {print $1;exit}' /etc/group)
++if test -z "$user_with_uid0" ; then user_with_uid0=root ; fi
++if test -z "$group_with_gid0" ; then group_with_gid0=root ; fi
+ AC_DEFINE_UNQUOTED([UID_0_USER],["$user_with_uid0"],[Get the user name having userid 0])
+ AC_DEFINE_UNQUOTED([GID_0_GROUP],["$group_with_gid0"],[Get the group name having groupid 0])
+
+--
+1.8.3.1
+
diff --git a/backport-Use-unsigned-integers-more-consistently-in-the-handl.patch b/backport-Use-unsigned-integers-more-consistently-in-the-handl.patch
new file mode 100644
index 0000000..af8b4b1
--- /dev/null
+++ b/backport-Use-unsigned-integers-more-consistently-in-the-handl.patch
@@ -0,0 +1,63 @@
+From 8e6108a5964c7289f3db70f3d188293276416528 Mon Sep 17 00:00:00 2001
+From: Daniel Alley <dalley@redhat.com>
+Date: Thu, 8 Dec 2022 09:40:00 -0500
+Subject: [PATCH] Use unsigned integers more consistently in the handling of
+ tag data
+
+Not a functional change, it just makes the code more clear and
+self-consistent.
+---
+ lib/header.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/lib/header.c b/lib/header.c
+index 004102dd2..72fb3d4fe 100644
+--- a/lib/header.c
++++ b/lib/header.c
+@@ -568,7 +568,7 @@ static int regionSwab(indexEntry entry, int il, int dl,
+ }
+ } break;
+ case RPM_INT32_TYPE:
+- { int32_t * it = ie.data;
++ { uint32_t * it = ie.data;
+ for (; ie.info.count > 0; ie.info.count--, it += 1) {
+ if (dataEnd && ((unsigned char *)it) >= dataEnd)
+ return -1;
+@@ -576,7 +576,7 @@ static int regionSwab(indexEntry entry, int il, int dl,
+ }
+ } break;
+ case RPM_INT16_TYPE:
+- { int16_t * it = ie.data;
++ { uint16_t * it = ie.data;
+ for (; ie.info.count > 0; ie.info.count--, it += 1) {
+ if (dataEnd && ((unsigned char *)it) >= dataEnd)
+ return -1;
+@@ -772,9 +772,9 @@ static void * doExport(const struct indexEntry_s *hindex, int indexUsed,
+ count = entry->info.count;
+ src = entry->data;
+ while (count--) {
+- *((int32_t *)te) = htonl(*((int32_t *)src));
+- te += sizeof(int32_t);
+- src += sizeof(int32_t);
++ *((uint32_t *)te) = htonl(*((uint32_t *)src));
++ te += sizeof(uint32_t);
++ src += sizeof(uint32_t);
+ }
+ break;
+
+@@ -782,9 +782,9 @@ static void * doExport(const struct indexEntry_s *hindex, int indexUsed,
+ count = entry->info.count;
+ src = entry->data;
+ while (count--) {
+- *((int16_t *)te) = htons(*((int16_t *)src));
+- te += sizeof(int16_t);
+- src += sizeof(int16_t);
++ *((uint16_t *)te) = htons(*((uint16_t *)src));
++ te += sizeof(uint16_t);
++ src += sizeof(uint16_t);
+ }
+ break;
+
+--
+2.33.0
+
diff --git a/backport-Validate-and-require-subkey-binding-signatures-on-PG.patch b/backport-Validate-and-require-subkey-binding-signatures-on-PG.patch
new file mode 100644
index 0000000..33c7402
--- /dev/null
+++ b/backport-Validate-and-require-subkey-binding-signatures-on-PG.patch
@@ -0,0 +1,327 @@
+From bd36c5dc9fb6d90c46fbfed8c2d67516fc571ec8 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 30 Sep 2021 09:59:30 +0300
+Subject: [PATCH] Validate and require subkey binding signatures on PGP public
+ keys
+
+All subkeys must be followed by a binding signature by the primary key
+as per the OpenPGP RFC, enforce the presence and validity in the parser.
+
+The implementation is as kludgey as they come to work around our
+simple-minded parser structure without touching API, to maximise
+backportability. Store all the raw packets internally as we decode them
+to be able to access previous elements at will, needed to validate ordering
+and access the actual data. Add testcases for manipulated keys whose
+import previously would succeed.
+
+Depends on the two previous commits:
+7b399fcb8f52566e6f3b4327197a85facd08db91 and
+236b802a4aa48711823a191d1b7f753c82a89ec5
+
+Fixes CVE-2021-3521.
+---
+ rpmio/rpmpgp.c | 98 +++++++++++++++++++++++--
+ tests/Makefile.am | 3 +
+ tests/data/keys/CVE-2021-3521-badbind.asc | 25 +++++++
+ tests/data/keys/CVE-2021-3521-nosubsig-last.asc | 25 +++++++
+ tests/data/keys/CVE-2021-3521-nosubsig.asc | 37 ++++++++++
+ tests/rpmsigdig.at | 28 +++++++
+ 6 files changed, 209 insertions(+), 7 deletions(-)
+ create mode 100644 tests/data/keys/CVE-2021-3521-badbind.asc
+ create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig-last.asc
+ create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig.asc
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index aad7c27..d70802a 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -1062,37 +1062,121 @@ static pgpDigParams pgpDigParamsNew(uint8_t tag)
+ return digp;
+ }
+
++static int hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt, int exptag)
++{
++ int rc = -1;
++ if (pkt->tag == exptag) {
++ uint8_t head[] = {
++ 0x99,
++ (pkt->blen >> 8),
++ (pkt->blen ),
++ };
++
++ rpmDigestUpdate(hash, head, 3);
++ rpmDigestUpdate(hash, pkt->body, pkt->blen);
++ rc = 0;
++ }
++ return rc;
++}
++
++static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig,
++ const struct pgpPkt *all, int i)
++{
++ int rc = -1;
++ DIGEST_CTX hash = NULL;
++
++ switch (selfsig->sigtype) {
++ case PGPSIGTYPE_SUBKEY_BINDING:
++ hash = rpmDigestInit(selfsig->hash_algo, 0);
++ if (hash) {
++ rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY);
++ if (!rc)
++ rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY);
++ }
++ break;
++ default:
++ /* ignore types we can't handle */
++ rc = 0;
++ break;
++ }
++
++ if (hash && rc == 0)
++ rc = pgpVerifySignature(key, selfsig, hash);
++
++ rpmDigestFinal(hash, NULL, NULL, 0);
++
++ return rc;
++}
++
+ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
+ pgpDigParams * ret)
+ {
+ const uint8_t *p = pkts;
+ const uint8_t *pend = pkts + pktlen;
+ pgpDigParams digp = NULL;
+- struct pgpPkt pkt;
++ pgpDigParams selfsig = NULL;
++ int i = 0;
++ int alloced = 16; /* plenty for normal cases */
++ struct pgpPkt *all = xmalloc(alloced * sizeof(*all));
+ int rc = -1; /* assume failure */
++ int expect = 0;
++ int prevtag = 0;
+
+ while (p < pend) {
+- if (decodePkt(p, (pend - p), &pkt))
++ struct pgpPkt *pkt = &all[i];
++ if (decodePkt(p, (pend - p), pkt))
+ break;
+
+ if (digp == NULL) {
+- if (pkttype && pkt.tag != pkttype) {
++ if (pkttype && pkt->tag != pkttype) {
+ break;
+ } else {
+- digp = pgpDigParamsNew(pkt.tag);
++ digp = pgpDigParamsNew(pkt->tag);
+ }
+ }
+
+- if (pgpPrtPkt(&pkt, digp))
++ if (expect) {
++ if (pkt->tag != expect)
++ break;
++ selfsig = pgpDigParamsNew(pkt->tag);
++ }
++
++ if (pgpPrtPkt(pkt, selfsig ? selfsig : digp))
+ break;
+
+- p += (pkt.body - pkt.head) + pkt.blen;
++ if (selfsig) {
++ /* subkeys must be followed by binding signature */
++ if (prevtag == PGPTAG_PUBLIC_SUBKEY) {
++ if (selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING)
++ break;
++ }
++
++ int xx = pgpVerifySelf(digp, selfsig, all, i);
++
++ selfsig = pgpDigParamsFree(selfsig);
++ if (xx)
++ break;
++ expect = 0;
++ }
++
++ if (pkt->tag == PGPTAG_PUBLIC_SUBKEY)
++ expect = PGPTAG_SIGNATURE;
++ prevtag = pkt->tag;
++
++ i++;
++ p += (pkt->body - pkt->head) + pkt->blen;
+ if (pkttype == PGPTAG_SIGNATURE)
+ break;
++
++ if (alloced <= i) {
++ alloced *= 2;
++ all = xrealloc(all, alloced * sizeof(*all));
++ }
+ }
+
+- rc = (digp && (p == pend)) ? 0 : -1;
++ rc = (digp && (p == pend) && expect == 0) ? 0 : -1;
+
++ free(all);
+ if (ret && rc == 0) {
+ *ret = digp;
+ } else {
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index b4a2e2e..bc535d2 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -108,6 +108,9 @@ EXTRA_DIST += data/SPECS/hello-config-buildid.spec
+ EXTRA_DIST += data/SPECS/hello-cd.spec
+ EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.pub
+ EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.secret
++EXTRA_DIST += data/keys/CVE-2021-3521-badbind.asc
++EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig.asc
++EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig-last.asc
+ EXTRA_DIST += data/macros.testfile
+ EXTRA_DIST += data/macros.debug
+ EXTRA_DIST += data/SOURCES/foo.c
+diff --git a/tests/data/keys/CVE-2021-3521-badbind.asc b/tests/data/keys/CVE-2021-3521-badbind.asc
+new file mode 100644
+index 0000000..aea00f9
+--- /dev/null
++++ b/tests/data/keys/CVE-2021-3521-badbind.asc
+@@ -0,0 +1,25 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Version: rpm-4.17.90 (NSS-3)
++
++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
+++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
++=WCfs
++-----END PGP PUBLIC KEY BLOCK-----
++
+diff --git a/tests/data/keys/CVE-2021-3521-nosubsig-last.asc b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
+new file mode 100644
+index 0000000..aea00f9
+--- /dev/null
++++ b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
+@@ -0,0 +1,25 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Version: rpm-4.17.90 (NSS-3)
++
++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
+++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
++=WCfs
++-----END PGP PUBLIC KEY BLOCK-----
++
+diff --git a/tests/data/keys/CVE-2021-3521-nosubsig.asc b/tests/data/keys/CVE-2021-3521-nosubsig.asc
+new file mode 100644
+index 0000000..3a2e741
+--- /dev/null
++++ b/tests/data/keys/CVE-2021-3521-nosubsig.asc
+@@ -0,0 +1,37 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Version: rpm-4.17.90 (NSS-3)
++
++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
+++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAG5AQ0EWOY5GAEIAKT68NmshdC4
++VcRhOhlXBvZq23NtskkKoPvW+ZlMuxbRDG48pGBtxhjOngriVUGceEWsXww5Q7En
++uRBYglkxkW34ENym0Ji6tsPYfhbbG+dZWKIL4vMIzPOIwlPrXrm558vgkdMM/ELZ
++8WIz3KtzvYubKUk2Qz+96lPXbwnlC/SBFRpBseJC5LoOb/5ZGdR/HeLz1JXiacHF
++v9Nr3cZWqg5yJbDNZKfASdZgC85v3kkvhTtzknl//5wqdAMexbuwiIh2xyxbO+B/
++qqzZFrVmu3sV2Tj5lLZ/9p1qAuEM7ULbixd/ld8yTmYvQ4bBlKv2bmzXtVfF+ymB
++Tm6BzyQEl/MAEQEAAYkBHwQYAQgACQUCWOY5GAIbDAAKCRBDRFkeGWTF/PANB/9j
++mifmj6z/EPe0PJFhrpISt9PjiUQCt0IPtiL5zKAkWjHePIzyi+0kCTBF6DDLFxos
++3vN4bWnVKT1kBhZAQlPqpJTg+m74JUYeDGCdNx9SK7oRllATqyu+5rncgxjWVPnQ
++zu/HRPlWJwcVFYEVXYL8xzfantwQTqefjmcRmBRdA2XJITK+hGWwAmrqAWx+q5xX
++Pa8wkNMxVzNS2rUKO9SoVuJ/wlUvfoShkJ/VJ5HDp3qzUqncADfdGN35TDzscngQ
++gHvnMwVBfYfSCABV1hNByoZcc/kxkrWMmsd/EnIyLd1Q1baKqc3cEDuC6E6/o4yJ
++E4XX4jtDmdZPreZALsiB
++=rRop
++-----END PGP PUBLIC KEY BLOCK-----
++
+diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
+index 0f8f2b4..c8b9f13 100644
+--- a/tests/rpmsigdig.at
++++ b/tests/rpmsigdig.at
+@@ -240,6 +240,34 @@ gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918
+ [])
+ AT_CLEANUP
+
++AT_SETUP([rpmkeys --import invalid keys])
++AT_KEYWORDS([rpmkeys import])
++RPMDB_INIT
++
++AT_CHECK([
++runroot rpmkeys --import /data/keys/CVE-2021-3521-badbind.asc
++],
++[1],
++[],
++[error: /data/keys/CVE-2021-3521-badbind.asc: key 1 import failed.]
++)
++AT_CHECK([
++runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig.asc
++],
++[1],
++[],
++[error: /data/keys/CVE-2021-3521-nosubsig.asc: key 1 import failed.]
++)
++
++AT_CHECK([
++runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig-last.asc
++],
++[1],
++[],
++[error: /data/keys/CVE-2021-3521-nosubsig-last.asc: key 1 import failed.]
++)
++AT_CLEANUP
++
+ # ------------------------------
+ # Test pre-built package verification
+ AT_SETUP([rpmkeys -K <signed> 1])
+--
+1.8.3.1
+
diff --git a/backport-bugfix-wrong-symlink-length-on-some-filesystems.patch b/backport-bugfix-wrong-symlink-length-on-some-filesystems.patch
new file mode 100644
index 0000000..e2052e3
--- /dev/null
+++ b/backport-bugfix-wrong-symlink-length-on-some-filesystems.patch
@@ -0,0 +1,44 @@
+From 4c301883a5a94a9a186a1bb1d45d234db4db7c88 Mon Sep 17 00:00:00 2001
+From: Dominik Neudert-Schulz <dominikns@bachtechnology.com>
+Date: Wed, 30 Jun 2021 14:13:46 +0200
+Subject: [PATCH] fix rpmbuild failure because of wrong symlink length on some
+ filesystems
+
+---
+ build/files.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/build/files.c b/build/files.c
+index f8153ad2b5..571b502e91 100644
+--- a/build/files.c
++++ b/build/files.c
+@@ -1363,6 +1363,8 @@ static rpmRC addFile(FileList fl, const char * diskPath,
+ {
+ size_t plen = strlen(diskPath);
+ char buf[plen + 1];
++ char linkPath[PATH_MAX];
++ ssize_t linkLen;
+ const char *cpioPath;
+ struct stat statbuf;
+ mode_t fileMode;
+@@ -1459,6 +1461,20 @@ static rpmRC addFile(FileList fl, const char * diskPath,
+ fileUid = statp->st_uid;
+ fileGid = statp->st_gid;
+
++ if (S_ISLNK(fileMode)) {
++ /* stat's man page states that statp->st_size should equal the length of
++ the pointed-to path. On some filesystem a wrong size is reported.
++ So, explicitly get the length here. */
++ linkLen = readlink(diskPath, linkPath, sizeof(linkPath));
++ if ((linkLen < 0) || (linkLen >= sizeof(linkPath))) {
++ rpmlog(RPMLOG_ERR,
++ "Symbolic link too long or corrupt: %s\n",
++ diskPath);
++ goto exit;
++ }
++ statp->st_size = linkLen;
++ }
++
+ /* Explicit %attr() always wins */
+ if (fl->cur.ar.ar_fmodestr) {
+ if (S_ISLNK(fileMode)) { \ No newline at end of file
diff --git a/backport-rpm2cpio.sh-Don-t-drop-newlines-from-header-sizes.patch b/backport-rpm2cpio.sh-Don-t-drop-newlines-from-header-sizes.patch
new file mode 100644
index 0000000..fbe4a78
--- /dev/null
+++ b/backport-rpm2cpio.sh-Don-t-drop-newlines-from-header-sizes.patch
@@ -0,0 +1,35 @@
+From a18a11924a715ace4b2d8e101688d164390cb188 Mon Sep 17 00:00:00 2001
+From: Florian Festi <ffesti@redhat.com>
+Date: Fri, 1 Jul 2022 14:44:11 +0200
+Subject: [PATCH] rpm2cpio.sh: Don't drop newlines from header sizes
+
+This script converts binary header sizes to decimal numbers. Shell is
+not that well suited for this task as it drops newlines at the end of
+command substitutions. Add a . character at the end and strip it right
+after that to avoid this problem.
+
+Resolves: rhbz#1983015
+---
+ scripts/rpm2cpio.sh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/scripts/rpm2cpio.sh b/scripts/rpm2cpio.sh
+index c1c505f..f77d5f8 100755
+--- a/scripts/rpm2cpio.sh
++++ b/scripts/rpm2cpio.sh
+@@ -27,7 +27,11 @@ calcsize() {
+
+ i=0
+ while [ $i -lt 8 ]; do
+- b="$(_dd $(($offset + $i)) bs=1 count=1)"
++ # add . to not loose \n
++ # strip \0 as it gets dropped with warning otherwise
++ b="$(_dd $(($offset + $i)) bs=1 count=1 | tr -d '\0' ; echo .)"
++ b=${b%.} # strip . again
++
+ [ -z "$b" ] &&
+ b="0" ||
+ b="$(exec printf '%u\n' "'$b")"
+--
+1.8.3.1
+
diff --git a/backport-rpm2cpio.sh-only-read-needed-bytes-of-file-magic.patch b/backport-rpm2cpio.sh-only-read-needed-bytes-of-file-magic.patch
new file mode 100644
index 0000000..490ec44
--- /dev/null
+++ b/backport-rpm2cpio.sh-only-read-needed-bytes-of-file-magic.patch
@@ -0,0 +1,27 @@
+From 8f922eb38a096640e586ba0eda96adc093b74fc4 Mon Sep 17 00:00:00 2001
+From: Florian Festi <ffesti@redhat.com>
+Date: Wed, 3 Aug 2022 17:19:02 +0200
+Subject: [PATCH] rpm2cpio.sh: only read needed bytes of file magic
+
+As we look at the first 4 bytes anyway there is no reason to read more.
+Reading more also hits a bug in bash on aarch64 (rhbz#2115206).
+---
+ scripts/rpm2cpio.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/rpm2cpio.sh b/scripts/rpm2cpio.sh
+index 74aeed8..cea0da2 100755
+--- a/scripts/rpm2cpio.sh
++++ b/scripts/rpm2cpio.sh
+@@ -43,7 +43,7 @@ calcsize() {
+ offset=$(($offset + $rsize))
+ }
+
+-case "$(_dd 0 bs=8 count=1 | tr -d '\0')" in
++case "$(_dd 0 bs=4 count=1 | tr -d '\0')" in
+ "$(printf '\355\253\356\333')"*) ;; # '\xed\xab\xee\xdb'
+ *) fatal "File doesn't look like rpm: $pkg" ;;
+ esac
+--
+1.8.3.1
+
diff --git a/backport-rpm2cpio.sh-strip-null-bytes-with-tr.patch b/backport-rpm2cpio.sh-strip-null-bytes-with-tr.patch
new file mode 100644
index 0000000..5cdef02
--- /dev/null
+++ b/backport-rpm2cpio.sh-strip-null-bytes-with-tr.patch
@@ -0,0 +1,35 @@
+From d499887c9261fdab4d03ea29316ea5e8fc646bd3 Mon Sep 17 00:00:00 2001
+From: Florian Festi <ffesti@redhat.com>
+Date: Fri, 1 Jul 2022 14:49:09 +0200
+Subject: [PATCH] rpm2cpio.sh: strip null bytes with tr
+
+to avoid warnings
+---
+ scripts/rpm2cpio.sh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/scripts/rpm2cpio.sh b/scripts/rpm2cpio.sh
+index f77d5f8..59e8bc5 100755
+--- a/scripts/rpm2cpio.sh
++++ b/scripts/rpm2cpio.sh
+@@ -43,7 +43,7 @@ calcsize() {
+ offset=$(($offset + $rsize))
+ }
+
+-case "$(_dd 0 bs=8 count=1)" in
++case "$(_dd 0 bs=8 count=1 | tr -d '\0')" in
+ "$(printf '\355\253\356\333')"*) ;; # '\xed\xab\xee\xdb'
+ *) fatal "File doesn't look like rpm: $pkg" ;;
+ esac
+@@ -54,7 +54,7 @@ sigsize=$rsize
+ calcsize $(($offset + (8 - ($sigsize % 8)) % 8))
+ hdrsize=$rsize
+
+-case "$(_dd $offset bs=3 count=1)" in
++case "$(_dd $offset bs=3 count=1 | tr -d '\0')" in
+ "$(printf '\102\132')"*) _dd $offset | bunzip2 ;; # '\x42\x5a'
+ "$(printf '\037\213')"*) _dd $offset | gunzip ;; # '\x1f\x8b'
+ "$(printf '\375\067')"*) _dd $offset | xzcat ;; # '\xfd\x37'
+--
+1.8.3.1
+
diff --git a/backport-rpmkeys-exit-non-zero-on-I-O-errors.patch b/backport-rpmkeys-exit-non-zero-on-I-O-errors.patch
new file mode 100644
index 0000000..ac18f35
--- /dev/null
+++ b/backport-rpmkeys-exit-non-zero-on-I-O-errors.patch
@@ -0,0 +1,53 @@
+From fc8386be36a32f8462a0d16a2dd3e5e18f7fbc2d Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Mon, 12 Apr 2021 11:30:51 -0400
+Subject: [PATCH] rpmkeys: exit non-zero on I/O errors
+
+If writing to stdout or stderr fails, rpmkeys should exit with a
+non-zero status code.
+---
+ rpmkeys.c | 4 ++++
+ tests/rpmsigdig.at | 13 +++++++++++++
+ 2 files changed, 17 insertions(+)
+
+diff --git a/rpmkeys.c b/rpmkeys.c
+index 542601c..2c304de 100644
+--- a/rpmkeys.c
++++ b/rpmkeys.c
+@@ -86,5 +86,9 @@ int main(int argc, char *argv[])
+ exit:
+ rpmtsFree(ts);
+ rpmcliFini(optCon);
++ fflush(stderr);
++ fflush(stdout);
++ if (ferror(stdout) || ferror(stderr))
++ return 255; /* I/O error */
+ return ec;
+ }
+diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
+index c8b9f13..429163e 100644
+--- a/tests/rpmsigdig.at
++++ b/tests/rpmsigdig.at
+@@ -24,6 +24,19 @@ runroot rpmkeys -Kv /data/RPMS/hello-2.0-1.x86_64.rpm /data/RPMS/hello-1.0-1.i38
+ [])
+ AT_CLEANUP
+
++# ------------------------------
++# Test rpmkeys write errors
++AT_SETUP([[rpmkeys -K no space left on stdout]])
++AT_KEYWORDS([rpmkeys digest])
++AT_CHECK([
++RPMDB_INIT[
++
++runroot rpmkeys -Kv /data/RPMS/hello-2.0-1.x86_64.rpm /data/RPMS/hello-1.0-1.i386.rpm >/dev/full
++]],255,,[[Error writing to log: No space left on device
++]])
++AT_CLEANUP
++
++
+ AT_SETUP([rpmkeys -Kv <reconstructed> 1])
+ AT_KEYWORDS([rpmkeys digest])
+ AT_CHECK([
+--
+1.8.3.1
+
diff --git a/backport-support-for-POSIX-getopt-behaviour.patch b/backport-support-for-POSIX-getopt-behaviour.patch
new file mode 100644
index 0000000..aa3c2c7
--- /dev/null
+++ b/backport-support-for-POSIX-getopt-behaviour.patch
@@ -0,0 +1,33 @@
+From 1f47b1cc0eddbb1921d81249a4bd604089c71495 Mon Sep 17 00:00:00 2001
+From: "(GalaxyMaster)" <galaxy4public@users.noreply.github.com>
+Date: Tue, 31 Jan 2023 18:24:55 +1100
+Subject: [PATCH] support for POSIX getopt() behaviour
+
+[POSIX defines optarg only for options with arguments](https://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html) and callback() is expecting optarg to be NULL for options without arguments, however, at least on musl optarg will carry a pointer to the argument of the previous option with argument. This commit makes the behaviour deterministic and expected.
+---
+ rpmio/rgetopt.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/rpmio/rgetopt.c b/rpmio/rgetopt.c
+index f789fa8fe..b14366a8a 100644
+--- a/rpmio/rgetopt.c
++++ b/rpmio/rgetopt.c
+@@ -28,6 +28,7 @@ int rgetopt(int argc, char * const argv[], const char *opts,
+ optind = 0;
+ #else
+ optind = 1;
++ optarg = NULL;
+ #endif
+
+ while ((c = getopt(argc, argv, opts)) != -1) {
+@@ -39,6 +40,7 @@ int rgetopt(int argc, char * const argv[], const char *opts,
+ rc = -1;
+ break;
+ }
++ optarg = NULL;
+ }
+ return (rc < 0) ? -optopt : optind;
+ }
+--
+2.27.0
+
diff --git a/backport-treat-0-as-valid-file-descriptor.patch b/backport-treat-0-as-valid-file-descriptor.patch
new file mode 100644
index 0000000..154e55a
--- /dev/null
+++ b/backport-treat-0-as-valid-file-descriptor.patch
@@ -0,0 +1,27 @@
+From be64821b908fdb1ff3c12530430d1cf046839e60 Mon Sep 17 00:00:00 2001
+From: licunlong <licunlong1@huawei.com>
+Date: Thu, 20 Jan 2022 19:59:44 +0800
+Subject: [PATCH] treat 0 as valid file descriptor The descriptor is openned in
+ rpmpkgOpen, and we treat 0 as valid file descriptor. Here we should do the
+ same or fail earlier.
+
+---
+ lib/backend/ndb/rpmpkg.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
+index 64d0493..0a041e4 100644
+--- a/lib/backend/ndb/rpmpkg.c
++++ b/lib/backend/ndb/rpmpkg.c
+@@ -734,7 +734,7 @@ static int rpmpkgAddSlotPage(rpmpkgdb pkgdb)
+
+ static int rpmpkgGetLock(rpmpkgdb pkgdb, int type)
+ {
+- if (!pkgdb->fd)
++ if (pkgdb->fd < 0)
+ return RPMRC_FAIL;
+ if (flock(pkgdb->fd, type))
+ return RPMRC_FAIL;
+--
+1.8.3.1
+
diff --git a/bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch b/bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch
new file mode 100644
index 0000000..c598126
--- /dev/null
+++ b/bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch
@@ -0,0 +1,80 @@
+diff -Nur rpm-4.14.2.old/installplatform rpm-4.14.2/installplatform
+--- rpm-4.14.2.old/installplatform 2017-08-10 16:08:07.113108701 +0800
++++ rpm-4.14.2/installplatform 2019-01-30 17:28:25.511000000 +0800
+@@ -180,6 +180,13 @@
+ CANONARCH=riscv64
+ CANONCOLOR=3
+ ;;
++ aarch64_ilp32)
++ ISANAME=aarch
++ ISABITS=32
++ CANONARCH=aarch64
++ CANONCOLOR=0
++ LIB=libilp32
++ ;;
+ noarch)
+ CANONARCH=noarch
+ CANONCOLOR=0
+diff -Nur rpm-4.14.2.old/rpmrc.in rpm-4.14.2/rpmrc.in
+--- rpm-4.14.2.old/rpmrc.in 2019-01-29 18:43:15.795000000 +0800
++++ rpm-4.14.2/rpmrc.in 2019-01-30 20:30:17.916000000 +0800
+@@ -99,7 +99,7 @@
+ optflags: sh4a -O2 -g -mieee
+
+ optflags: aarch64 -O2 -g
+-
++optflags: aarch64_ilp32 -O2 -g -mabi=ilp32
+ optflags: riscv64 -O2 -g
+
+ #############################################################
+@@ -149,7 +149,7 @@
+ archcolor: sh4 1
+
+ archcolor: aarch64 2
+-
++archcolor: aarch64_ilp32 1
+ archcolor: riscv64 2
+
+ #############################################################
+@@ -243,7 +243,7 @@
+ arch_canon: sh4a: sh4a 17
+ arch_canon: xtensa: xtensa 18
+ arch_canon: aarch64: aarch64 19
+-
++arch_canon: aarch64_ilp32: aarch64 19
+ arch_canon: mipsr6: mipsr6 20
+ arch_canon: mipsr6el: mipsr6el 20
+ arch_canon: mips64r6: mips64r6 21
+@@ -377,11 +377,11 @@
+ buildarchtranslate: sh4a: sh4
+
+ buildarchtranslate: aarch64: aarch64
+-
++buildarchtranslate: aarch64_ilp32: aarch64_ilp32
+ buildarchtranslate: riscv: riscv64
+ buildarchtranslate: riscv64: riscv64
+
+-#############################################################
++#########################################/####################
+ # Architecture compatibility
+
+ arch_compat: alphaev67: alphaev6
+@@ -485,7 +485,8 @@
+ arch_compat: sh4: noarch
+ arch_compat: sh4a: sh4
+
+-arch_compat: aarch64: noarch
++arch_compat: aarch64_ilp32: aarch64 noarch
++arch_compat: aarch64: aarch64_ilp32 noarch
+
+ arch_compat: riscv: noarch
+ arch_compat: riscv64: noarch
+@@ -522,7 +523,7 @@
+ buildarch_compat: ia64: noarch
+
+ buildarch_compat: aarch64: noarch
+-
++buildarch_compat: aarch64_ilp32: noarch
+ buildarch_compat: riscv: noarch
+ buildarch_compat: riscv64: noarch
+
diff --git a/bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch b/bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch
new file mode 100644
index 0000000..2379331
--- /dev/null
+++ b/bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch
@@ -0,0 +1,35 @@
+From c6699a7e90acfaa421830ce0fc12940335e40d7b Mon Sep 17 00:00:00 2001
+From: shanshishi <shanshishi@huawei.com>
+Date: Sun, 19 May 2019 16:49:45 +0800
+Subject: [PATCH] rpm: wait once get rpmlock fail
+
+reason: When executing the rpm command concurrently, it will block some
+times, because of lock is applied before.
+
+Signed-off-by: shanshishi <shanshishi@huawei.com>
+---
+ lib/rpmlock.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/lib/rpmlock.c b/lib/rpmlock.c
+index d693c4b..86e07b3 100644
+--- a/lib/rpmlock.c
++++ b/lib/rpmlock.c
+@@ -125,13 +125,10 @@ rpmlock rpmlockNew(const char *lock_path, const char *descr)
+ int rpmlockAcquire(rpmlock lock)
+ {
+ int locked = 0; /* assume failure */
+- int myerrno = errno;
+- int maywait = isatty(STDIN_FILENO); /* dont wait within scriptlets */
+- errno = myerrno;
+
+ if (lock) {
+ locked = rpmlock_acquire(lock, RPMLOCK_WRITE);
+- if (!locked && (lock->openmode & RPMLOCK_WRITE) && maywait) {
++ if (!locked && (lock->openmode & RPMLOCK_WRITE)) {
+ rpmlog(RPMLOG_WARNING, _("waiting for %s lock on %s\n"),
+ lock->descr, lock->path);
+ locked = rpmlock_acquire(lock, (RPMLOCK_WRITE|RPMLOCK_WAIT));
+--
+1.7.12.4
+
diff --git a/call-process_digest_list-after-files-are-added.patch b/call-process_digest_list-after-files-are-added.patch
new file mode 100644
index 0000000..4809b58
--- /dev/null
+++ b/call-process_digest_list-after-files-are-added.patch
@@ -0,0 +1,115 @@
+From 641ec5a50cb5057e02c4cfe7bd537a32fafdd665 Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Mon, 26 Oct 2020 12:10:31 +0800
+Subject: [PATCH] call process_digest_list after files are added
+
+Signed-off-by: Anakin Zhang <benjamin93@163.com>
+---
+ plugins/digest_list.c | 78 ++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 69 insertions(+), 9 deletions(-)
+
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+index 9fcb5c4..7213b41 100644
+--- a/plugins/digest_list.c
++++ b/plugins/digest_list.c
+@@ -479,28 +479,88 @@ out:
+ return ret;
+ }
+
++rpmte cur_te;
++int digest_list_counter;
++
+ static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
+ {
+- process_digest_list(te, 0);
+- if (!strcmp(rpmteN(te), "digest-list-tools"))
+- process_digest_list(te, 1);
++ Header rpm = rpmteHeader(te);
++ rpmtd dirnames;
++ int i;
++
++ digest_list_counter = 0;
++
++ dirnames = rpmtdNew();
++ headerGet(rpm, RPMTAG_DIRNAMES, dirnames, 0);
++
++ while ((i = rpmtdNext(dirnames)) >= 0) {
++ char *dirname = (char *) rpmtdGetString(dirnames);
++ if (!strncmp(dirname, DIGEST_LIST_DEFAULT_PATH,
++ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
++ digest_list_counter++;
++ }
+
++ rpmtdFree(dirnames);
++
++ cur_te = te;
+ return RPMRC_OK;
+ }
+
+-static rpmRC digest_list_psm_post(rpmPlugin plugin, rpmte te, int res)
++static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
++ const char* path, mode_t file_mode,
++ rpmFsmOp op, int pre, int res)
+ {
+- if (res != RPMRC_OK)
++ rpmFileAction action = XFO_ACTION(op);
++
++ if (!digest_list_counter)
++ return RPMRC_OK;
++
++ if (!cur_te)
++ return RPMRC_OK;
++
++ if (!pre && res != RPMRC_OK)
++ return res;
++
++ if ((pre && action != FA_ERASE) ||
++ (!pre && action != FA_CREATE))
+ return RPMRC_OK;
+
+- process_digest_list(te, 0);
+- if (!strcmp(rpmteN(te), "digest-list-tools"))
+- process_digest_list(te, 1);
++ if (digest_list_counter) {
++ if (!pre) {
++ if (!strncmp(path, DIGEST_LIST_DEFAULT_PATH,
++ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
++ digest_list_counter--;
++ } else {
++ digest_list_counter = 0;
++ }
++
++ if (digest_list_counter)
++ return RPMRC_OK;
++ }
++
++ process_digest_list(cur_te, 0);
++ if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
++ process_digest_list(cur_te, 1);
+
+ return RPMRC_OK;
+ }
+
++static rpmRC digest_list_file_pre(rpmPlugin plugin, rpmfi fi,
++ const char* path, mode_t file_mode,
++ rpmFsmOp op)
++{
++ return digest_list_file_common(plugin, fi, path, file_mode, op, 1, 0);
++}
++
++static rpmRC digest_list_file_post(rpmPlugin plugin, rpmfi fi,
++ const char* path, mode_t file_mode,
++ rpmFsmOp op, int res)
++{
++ return digest_list_file_common(plugin, fi, path, file_mode, op, 0, res);
++}
++
+ struct rpmPluginHooks_s digest_list_hooks = {
+ .psm_pre = digest_list_psm_pre,
+- .psm_post = digest_list_psm_post,
++ .fsm_file_pre = digest_list_file_pre,
++ .fsm_file_post = digest_list_file_post,
+ };
+--
+2.23.0
+
diff --git a/dont-remove-ima-xattr-of-parser-when-upgrading.patch b/dont-remove-ima-xattr-of-parser-when-upgrading.patch
new file mode 100644
index 0000000..b2e0424
--- /dev/null
+++ b/dont-remove-ima-xattr-of-parser-when-upgrading.patch
@@ -0,0 +1,35 @@
+From 2c27c71952ce3ac61afeabd3ef4e1d182574e905 Mon Sep 17 00:00:00 2001
+From: luhuaxin <luhuaxin1@huawei.com>
+Date: Tue, 15 Mar 2022 20:54:06 +0800
+Subject: [PATCH] dont remove ima xattr of parser when upgrading
+
+Signed-off-by: luhuaxin <luhuaxin1@huawei.com>
+---
+ plugins/digest_list.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+index 0692b5b..1d7ef92 100644
+--- a/plugins/digest_list.c
++++ b/plugins/digest_list.c
+@@ -576,9 +576,16 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
+ if (!pre && --digest_list_counter)
+ return RPMRC_OK;
+
++ rpmlog(RPMLOG_DEBUG, "process ima digest, pre: %d, action: %d, teType: %d\n",
++ pre, action, rpmteType(cur_te));
+ process_digest_list(cur_te, 0, pre);
+- if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
++ if (!strcmp(rpmteN(cur_te), "digest-list-tools")) {
++ if (pre && rpmteType(cur_te) == TR_REMOVED)
++ return RPMRC_OK;
++
++ rpmlog(RPMLOG_DEBUG, "process parser digest\n");
+ process_digest_list(cur_te, 1, pre);
++ }
+
+ return RPMRC_OK;
+ }
+--
+2.33.0
+
diff --git a/fix-lsetxattr-error-in-container.patch b/fix-lsetxattr-error-in-container.patch
new file mode 100644
index 0000000..c7cd4da
--- /dev/null
+++ b/fix-lsetxattr-error-in-container.patch
@@ -0,0 +1,64 @@
+From 848cad38da6c727c91f0fcb8052f9402de598737 Mon Sep 17 00:00:00 2001
+From: Zhang Tianxing <zhangtianxing3@huawei.com>
+Date: Mon, 13 Sep 2021 17:32:11 +0800
+Subject: [PATCH] fix lsetxattr error in container
+
+The digest list plugin in rpm will set security.ima xattr to IMA digest lists
+when installing or updating an rpm package. However, in a container without
+CAP_SYS_ADMIN, we'll get error messages when calling lsetxattr.
+
+This patch is to skip lsetxattr when CAP_SYS_ADMIN is missing.
+
+Signed-off-by: Zhang Tianxing <zhangtianxing3@huawei.com>
+---
+ plugins/digest_list.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/plugins/digest_list.c b/plugins/digest_list.c
+index 6bc9415..2d14463 100644
+--- a/plugins/digest_list.c
++++ b/plugins/digest_list.c
+@@ -12,6 +12,7 @@
+ #include <sys/stat.h>
+ #include <openssl/sha.h>
+ #include <sys/xattr.h>
++#include <sys/capability.h>
+ #include <linux/xattr.h>
+ #include <asm/byteorder.h>
+ #include <sys/wait.h>
+@@ -370,6 +371,10 @@ static int process_digest_list(rpmte te, int parser)
+ int digest_list_signed = 0;
+ struct stat st;
+ ssize_t size;
++ struct __user_cap_header_struct cap_header_data;
++ cap_user_header_t cap_header = &cap_header_data;
++ struct __user_cap_data_struct cap_data_data;
++ cap_user_data_t cap_data = &cap_data_data;
+ rpmRC ret = RPMRC_OK;
+
+ path = malloc(PATH_MAX);
+@@ -435,7 +440,21 @@ static int process_digest_list(rpmte te, int parser)
+ ret = RPMRC_FAIL;
+ goto out;
+ }
++ }
+
++ /* don't call lsetxattr without CAP_SYS_ADMIN */
++ cap_header->pid = getpid();
++ cap_header->version = _LINUX_CAPABILITY_VERSION_1;
++ if (capget(cap_header, cap_data) < 0) {
++ ret = -ENOENT;
++ goto out;
++ }
++ if (!(cap_data->effective & CAP_TO_MASK(CAP_SYS_ADMIN))) {
++ ret = -EPERM;
++ goto out;
++ }
++
++ if (!digest_list_signed) {
+ /* Write RPM header sig to security.ima */
+ ret = write_rpm_digest_list_ima_xattr(te, path);
+ } else {
+--
+2.27.0
+
diff --git a/get-in-use-of-ndb.patch b/get-in-use-of-ndb.patch
new file mode 100644
index 0000000..c3d31ff
--- /dev/null
+++ b/get-in-use-of-ndb.patch
@@ -0,0 +1,42 @@
+From 8ba0780a26429bbb474e23112627ebbaeb9abfee Mon Sep 17 00:00:00 2001
+From: renmingshuai <renmingshuai@huawei.com>
+Date: Mon, 29 Nov 2021 10:53:24 +0800
+Subject: [PATCH] get in use of ndb
+
+---
+ configure.ac | 4 ++--
+ macros.in | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 6b161dc..ab1c667 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -490,9 +490,9 @@ AM_CONDITIONAL([BDB_RO], [test "$enable_bdb_ro" = yes])
+ # Check for SQLITE support
+ AC_ARG_ENABLE([sqlite],
+ [AS_HELP_STRING([--enable-sqlite=@<:@yes/no/auto@:>@)],
+- [build with sqlite rpm database format support (default=yes)])],
++ [build with sqlite rpm database format support (default=auto)])],
+ [enable_sqlite="$enableval"],
+- [enable_sqlite=yes])
++ [enable_sqlite=auto])
+
+ AS_IF([test "x$enable_sqlite" != "xno"], [
+ PKG_CHECK_MODULES([SQLITE], [sqlite3 >= 3.22.0], [have_sqlite=yes], [have_sqlite=no])
+diff --git a/macros.in b/macros.in
+index 22f675c..3e81918 100644
+--- a/macros.in
++++ b/macros.in
+@@ -602,7 +602,7 @@ package or when debugging this package.\
+ # sqlite Sqlite database
+ # dummy dummy backend (no actual functionality)
+ #
+-%_db_backend sqlite
++%_db_backend ndb
+
+ #==============================================================================
+ # ---- GPG/PGP/PGP5 signature macros.
+--
+1.8.3.1
+
diff --git a/revert-always-execute-file-trigger-scriptlet-callbac.patch b/revert-always-execute-file-trigger-scriptlet-callbac.patch
new file mode 100644
index 0000000..c8fd59c
--- /dev/null
+++ b/revert-always-execute-file-trigger-scriptlet-callbac.patch
@@ -0,0 +1,26 @@
+From 9680c3f2f8ceeddced6e91048daeb9b93abf4c8d Mon Sep 17 00:00:00 2001
+From: openEuler Buildteam <buildteam@openeuler.org>
+Date: Wed, 25 Mar 2020 16:57:29 +0800
+Subject: [PATCH] revert always execute file trigger scriptlet callbacks with
+ owning header
+
+---
+ lib/rpmtriggers.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c
+index 285b2f0..b7c76e7 100644
+--- a/lib/rpmtriggers.c
++++ b/lib/rpmtriggers.c
+@@ -437,7 +437,7 @@ static int runHandleTriggersInPkg(rpmts ts, rpmte te, Header h,
+ inputFunc = (char *(*)(void *)) matchFilesNext;
+ rpmScriptSetNextFileFunc(script, inputFunc, mfi);
+
+- nerrors += runScript(ts, NULL, h, installPrefixes.data,
++ nerrors += runScript(ts, te, h, installPrefixes.data,
+ script, 0, -1);
+ rpmtdFreeData(&installPrefixes);
+ rpmScriptFree(script);
+--
+1.8.3.1
+
diff --git a/rpm-4.12.0-rpm2cpio-hack.patch b/rpm-4.12.0-rpm2cpio-hack.patch
new file mode 100644
index 0000000..38c7dbd
--- /dev/null
+++ b/rpm-4.12.0-rpm2cpio-hack.patch
@@ -0,0 +1,18 @@
+diff --git a/rpm2cpio.c b/rpm2cpio.c
+index 89ebdfa..ae999ff 100644
+--- a/rpm2cpio.c
++++ b/rpm2cpio.c
+@@ -84,7 +84,12 @@ int main(int argc, char *argv[])
+ exit(EXIT_FAILURE);
+ }
+
+- rc = (ufdCopy(gzdi, fdo) == payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
++ /*
++ * XXX HACK for #1142949: should be equality test, but archive size
++ * short by cpio trailer size in packages built with rpm 4.12.0
++ * and its pre-releases.
++ */
++ rc = (ufdCopy(gzdi, fdo) >= payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
+
+ Fclose(fdo);
+
diff --git a/rpm-Add-sw64-architecture.patch b/rpm-Add-sw64-architecture.patch
new file mode 100644
index 0000000..93b493b
--- /dev/null
+++ b/rpm-Add-sw64-architecture.patch
@@ -0,0 +1,172 @@
+From 3c8ac8643a0d7c3c3ce972c0a0685d9d1c9de9bc Mon Sep 17 00:00:00 2001
+From: wzx <wuzx1226@qq.com>
+Date: Thu, 27 Oct 2022 11:27:23 +0800
+Subject: [PATCH] Add sw64 architecture
+
+Add sw64 architecture in file config.guess config.sub installplatform lib/rpmrc.c macros.in rpmrc.in and tools/elfdeps.c to support sw64 architecture.
+
+Signed-off-by: wzx <wuzx1226@qq.com>
+---
+ build-aux/config.guess | 8 ++++++++
+ build-aux/config.sub | 1 +
+ installplatform | 6 ++++++
+ lib/rpmrc.c | 7 +++++++
+ macros.in | 1 +
+ rpmrc.in | 15 +++++++++++++++
+ tools/elfdeps.c | 1 +
+ 7 files changed, 39 insertions(+)
+
+diff --git a/build-aux/config.guess b/build-aux/config.guess
+index b33c9e8..69e3005 100755
+--- a/build-aux/config.guess
++++ b/build-aux/config.guess
+@@ -913,6 +913,14 @@ EOF
+ UNAME_MACHINE=aarch64_be
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
++ sw_64:Linux:*:*)
++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
++ sw) UNAME_MACHINE=sw_64 ;;
++ esac
++ objdump --private-headers /bin/sh | grep -q ld.so.1
++ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
++ echo "$UNAME_MACHINE"-sunway-linux-"$LIBC"
++ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+diff --git a/build-aux/config.sub b/build-aux/config.sub
+index b51fb8c..84a8688 100755
+--- a/build-aux/config.sub
++++ b/build-aux/config.sub
+@@ -1155,6 +1155,7 @@ case $cpu-$vendor in
+ case $cpu in
+ 1750a | 580 \
+ | a29k \
++ | sw_64 \
+ | aarch64 | aarch64_be \
+ | abacus \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+diff --git a/installplatform b/installplatform
+index ca490e0..2700199 100755
+--- a/installplatform
++++ b/installplatform
+@@ -108,6 +108,12 @@ for ARCH in noarch `grep ^arch_canon $RPMRC | cut -d: -f2`; do
+ CANONARCH=arm
+ CANONCOLOR=0
+ ;;
++ sw_64*)
++ ISANAME=sw_64
++ ISABITS=64
++ CANONARCH=sw_64
++ CANONCOLOR=0
++ ;;
+ alpha*)
+ ISANAME=alpha
+ ISABITS=64
+diff --git a/lib/rpmrc.c b/lib/rpmrc.c
+index 120777c..5d9507d 100644
+--- a/lib/rpmrc.c
++++ b/lib/rpmrc.c
+@@ -1268,6 +1268,13 @@ static void defaultMachine(rpmrcCtx ctx, const char ** arch, const char ** os)
+ }
+ # endif
+
++# if defined(__GNUC__) && defined(__sw_64__)
++ {
++ strcpy(un.machine, "sw_64sw6b");
++ }
++# endif
++
++
+ # if defined(__linux__) && defined(__i386__)
+ {
+ char mclass = (char) (RPMClass() | '0');
+diff --git a/macros.in b/macros.in
+index 4dbf5b6..6722a74 100644
+--- a/macros.in
++++ b/macros.in
+@@ -1107,6 +1107,7 @@ package or when debugging this package.\
+ #------------------------------------------------------------------------------
+ # arch macro for all supported Alpha processors
+ %alpha alpha alphaev56 alphaev6 alphaev67
++%sw_64 sw_64 sw_64sw6b
+
+ #------------------------------------------------------------------------------
+ # arch macro for all supported PowerPC 64 processors
+diff --git a/rpmrc.in b/rpmrc.in
+index 3a48af4..8d70f91 100644
+--- a/rpmrc.in
++++ b/rpmrc.in
+@@ -25,6 +25,9 @@ optflags: x86_64 -O2 -g
+ optflags: amd64 -O2 -g
+ optflags: ia32e -O2 -g
+
++optflags: sw_64 -O2 -g -mieee
++optflags: sw_64sw6b -O2 -g -mieee -mtune=sw6b
++
+ optflags: alpha -O2 -g -mieee
+ optflags: alphaev5 -O2 -g -mieee -mtune=ev5
+ optflags: alphaev56 -O2 -g -mieee -mtune=ev56
+@@ -112,6 +115,7 @@ optflags: riscv64 -O2 -g
+ archcolor: noarch 0
+ archcolor: i386 1
+ archcolor: alpha 2
++archcolor: sw_64 2
+ archcolor: sparc 1
+ archcolor: sparc64 2
+ archcolor: sparcv9 2
+@@ -176,6 +180,9 @@ arch_canon: amd64: amd64 1
+ arch_canon: ia32e: ia32e 1
+ arch_canon: em64t: em64t 1
+
++arch_canon: sw_64: sw_64 2
++arch_canon: sw_64sw6b: sw_64sw6b 2
++
+ arch_canon: alpha: alpha 2
+ arch_canon: alphaev5: alphaev5 2
+ arch_canon: alphaev56: alphaev56 2
+@@ -315,6 +322,9 @@ buildarchtranslate: i586: i386
+ buildarchtranslate: i486: i386
+ buildarchtranslate: i386: i386
+
++buildarchtranslate: sw_64: sw_64
++buildarchtranslate: sw_64sw6b: sw_64
++
+ buildarchtranslate: alphaev5: alpha
+ buildarchtranslate: alphaev56: alpha
+ buildarchtranslate: alphapca56: alpha
+@@ -401,6 +411,8 @@ buildarchtranslate: riscv64: riscv64
+
+ #########################################/####################
+ # Architecture compatibility
++arch_compat: sw_64sw6b: sw_64
++arch_compat: sw_64: axp noarch
+
+ arch_compat: alphaev67: alphaev6
+ arch_compat: alphaev6: alphapca56
+@@ -570,6 +582,9 @@ buildarch_compat: sparcv9: sparcv8
+ buildarch_compat: sparcv8: sparc
+ buildarch_compat: sparc: noarch
+
++buildarch_compat: sw_64sw6b: sw_64
++buildarch_compat: sw_64: noarch
++
+ buildarch_compat: alphaev67: alphaev6
+ buildarch_compat: alphaev6: alphapca56
+ buildarch_compat: alphapca56: alphaev56
+diff --git a/tools/elfdeps.c b/tools/elfdeps.c
+index d205935..590021b 100644
+--- a/tools/elfdeps.c
++++ b/tools/elfdeps.c
+@@ -85,6 +85,7 @@ static const char *mkmarker(GElf_Ehdr *ehdr)
+ if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) {
+ switch (ehdr->e_machine) {
+ case EM_ALPHA:
++ case EM_SW_64:
+ case EM_FAKE_ALPHA:
+ /* alpha doesn't traditionally have 64bit markers */
+ break;
+--
+2.33.0
+
diff --git a/rpm-selinux-plugin-check-context-file-exist.patch b/rpm-selinux-plugin-check-context-file-exist.patch
new file mode 100644
index 0000000..56d7982
--- /dev/null
+++ b/rpm-selinux-plugin-check-context-file-exist.patch
@@ -0,0 +1,26 @@
+From 55708fd5822a3e4bf5537002a648f32cb0a6e07e Mon Sep 17 00:00:00 2001
+From: luhuaxin <1539327763@qq.com>
+Date: Tue, 26 Oct 2021 18:39:46 +0800
+Subject: [PATCH] rpm selinux plugin check context file exist
+
+---
+ plugins/selinux.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/plugins/selinux.c b/plugins/selinux.c
+index 1254517..fb8b7a2 100644
+--- a/plugins/selinux.c
++++ b/plugins/selinux.c
+@@ -63,7 +63,8 @@ static rpmRC selinux_tsm_pre(rpmPlugin plugin, rpmts ts)
+ rpmRC rc = RPMRC_OK;
+
+ /* If SELinux isn't enabled on the system, dont mess with it */
+- if (!is_selinux_enabled()) {
++ if (!is_selinux_enabled() || selinux_file_context_path() == NULL ||
++ access(selinux_file_context_path(), F_OK)) {
+ rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
+ }
+
+--
+2.23.0
+
diff --git a/rpm.spec b/rpm.spec
new file mode 100644
index 0000000..a9f2f34
--- /dev/null
+++ b/rpm.spec
@@ -0,0 +1,733 @@
+Name: rpm
+Version: 4.17.0
+Release: 30
+Summary: RPM Package Manager
+License: GPLv2+
+URL: http://www.rpm.org/
+Source0: http://ftp.rpm.org/releases/rpm-4.17.x/%{name}-%{version}.tar.bz2
+
+Patch1: Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch
+Patch2: rpm-4.12.0-rpm2cpio-hack.patch
+Patch3: add-dist-to-release-by-default.patch
+Patch4: revert-always-execute-file-trigger-scriptlet-callbac.patch
+Patch5: bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch
+Patch6: bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch
+Patch7: Generate-digest-lists.patch
+Patch8: Add-digest-list-plugin.patch
+Patch9: Don-t-add-dist-to-release-if-it-is-already-there.patch
+Patch10: Generate-digest-lists-before-calling-genCpioListAndH.patch
+Patch11: call-process_digest_list-after-files-are-added.patch
+Patch12: fix-lsetxattr-error-in-container.patch
+Patch13: rpm-selinux-plugin-check-context-file-exist.patch
+Patch14: get-in-use-of-ndb.patch
+Patch15: still-in-use-of-python-scripts-from-old-version.patch
+Patch16: Add-loongarch-architecture-support.patch
+Patch17: Fix-digest_list_counter.patch
+Patch18: Check-rpm-parser.patch
+Patch19: Remove-digest-list-from-the-kernel-during-package-re.patch
+Patch20: Add-license-to-digest_list.c.patch
+Patch21: Avoid-generating-digest-lists-if-they-are-already-pa.patch
+Patch22: dont-remove-ima-xattr-of-parser-when-upgrading.patch
+Patch23: rpm-Add-sw64-architecture.patch
+Patch24: 0001-add-default-machine-name-to-support-loongarch.patch
+
+Patch6000: backport-Use-root-as-default-UID_0_USER-and-UID_0_GROUP.patch
+Patch6001: backport-Check-file-iterator-for-being-NULL-consistently.patch
+Patch6002: backport-Process-MPI-s-from-all-kinds-of-signatures.patch
+Patch6003: backport-Refactor-pgpDigParams-construction-to-helper-functio.patch
+Patch6004: backport-Validate-and-require-subkey-binding-signatures-on-PG.patch
+Patch6005: backport-Revert-Explictly-skip-non-installed-files-on-erasur.patch
+Patch6006: backport-Fix-hash-context-leak.patch
+Patch6007: backport-Fix-hashlen-overflow.patch
+Patch6008: backport-Fix-some-Lua-stack-leaks-in-our-initialization-code.patch
+Patch6009: backport-Simplify-rpm_print-fixing-a-Lua-stack-leak-as-a-bonu.patch
+Patch6010: backport-Switch-the-floating-point-type-in-rpmhook-from-float.patch
+Patch6011: backport-Fix-a-memleak-in-ndb-from-opened-but-not-closed-dbis.patch
+Patch6012: backport-Fix-possible-NULL-pointer-dereference-in-rpmfcClassi.patch
+Patch6013: backport-Fix-old-Python-ts.check-argument-order-regression.patch
+Patch6014: backport-Fix-memory-leak-in-pgpPrtParams.patch
+Patch6015: backport-Fix-use-after-free-in-haveSignature.patch
+Patch6016: backport-Close-file-before-replacing-signed.patch
+Patch6017: backport-Fix-__cplusplus-misspelled-as-_cplusplus.patch
+Patch6018: backport-treat-0-as-valid-file-descriptor.patch
+Patch6019: backport-Skip-recorded-symlinks-in-setperms-RhBug-1900662.patch
+Patch6020: backport-Check-that-the-CRC-length-is-correct.patch
+Patch6021: backport-Make-rpmfiSetFX-return-code-meaningful.patch
+Patch6022: backport-Avoid-reading-out-of-bounds-of-the-i18ntable.patch
+Patch6023: backport-rpmkeys-exit-non-zero-on-I-O-errors.patch
+
+Patch6024: backport-Prevent-NULL-deref-in-rpmfsGetStates.patch
+Patch6025: backport-Fix-memory-leak-in-pgpPrtParams-1.patch
+Patch6026: backport-Fix-return-value-checks-in-OpenSSL-code.patch
+Patch6027: backport-Avoid-double-frees-if-EVP_PKEY_assign_RSA-fails.patch
+Patch6028: backport-Require-creation-time-to-be-unique-and-hashed.patch
+Patch6029: backport-Add-a-hashed-flag-to-pgpPrtSubtype.patch
+Patch6030: backport-Parse-key-usage-flags.patch
+Patch6031: backport-Ignore-subkeys-that-cannot-be-used-for-signing.patch
+Patch6032: backport-Avoid-unneded-MPI-reparsing.patch
+Patch6033: backport-Fix-OpenPGP-key-ID-parsing-regression.patch
+Patch6034: backport-Fix-changelog-parsing-affecting-caller-timezone-stat.patch
+Patch6035: backport-rpm2cpio.sh-Don-t-drop-newlines-from-header-sizes.patch
+Patch6036: backport-Prevent-readelf-internet-access-during-rpaths-checki.patch
+Patch6037: backport-Fix-short-circuiting-of-version-strings-in-expressio.patch
+
+Patch6038: backport-Add-optional-callback-on-directory-changes-during-rp.patch
+Patch6039: backport-CVE-2021-35937-CVE-2021-35939.patch
+Patch6040: backport-Consolidate-skipped-hardlink-with-content-case-with-.patch
+Patch6041: backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch
+Patch6042: backport-Convert-the-file-creation-steps-the-at-family-of-cal.patch
+Patch6043: backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
+Patch6044: backport-Return-descriptor-of-created-file-from-fsmMkfile.patch
+Patch6045: backport-CVE-2021-35938.patch
+Patch6046: backport-rpm2cpio.sh-strip-null-bytes-with-tr.patch
+Patch6047: backport-rpm2cpio.sh-only-read-needed-bytes-of-file-magic.patch
+Patch6048: backport-Fix-rpm-lua-rpm_vercmp-error-message-if-second-argum.patch
+Patch6049: backport-Make-pgpPubkeyFingerprint-do-something-meaningful-ag.patch
+Patch6050: backport-Fix-possible-descriptor-leak-in-fsmOpenat.patch
+Patch6051: backport-Move-file-metadata-setting-back-to-unpack-stage.patch
+Patch6052: backport-Fix-header-leak-in-rpmInstall.patch
+Patch6053: backport-Fix-eiu-sourceURL-info-leak-in-rpmInstall.patch
+Patch6054: backport-Fix-h-blob-leak-when-installing-source-rpms.patch
+Patch6055: backport-Fix-Header-leak-when-running-rpm2cpio.patch
+Patch6056: backport-Use-unsigned-integers-more-consistently-in-the-handl.patch
+Patch6057: backport-Fix-file-leak-when-src-rpm-in-URL-format-is-used-for.patch
+Patch6058: backport-Fix-BANames-leak-in-handlePreambleTag.patch
+Patch6059: backport-Fix-prog-leak-in-parseScript.patch
+Patch6060: backport-Fix-elf-leak-in-getElfColor.patch
+Patch6061: backport-Fix-sbp-leak-when-running-rpmbuild-with-quiet.patch
+Patch6062: backport-Fix-memleak-when-running-generate_buildrequires.patch
+Patch6063: backport-Fix-memleak-when-fsmRename-failed-in-fsmCommit.patch
+Patch6064: backport-Fix-fileleak-and-memleak-in-rpmInstall.patch
+Patch6065: backport-Fix-fileleak-when-urlGetFile-fails-in-rpmInstall.patch
+
+Patch6066: backport-Fix-install-of-block-and-character-special-files-219.patch
+Patch6067: backport-Use-fd-based-ops-for-metadata-in-FA_TOUCH-mode-too-w.patch
+Patch6068: backport-Add-a-test-for-special-device-node-installation.patch
+Patch6069: backport-support-for-POSIX-getopt-behaviour.patch
+Patch6070: backport-Use-proper-type-for-copyTagsFromMainDebug.patch
+Patch6071: backport-Fix-a-copy-paste-help-description-of-whatconflicts-R.patch
+Patch6072: backport-Fix-a-segfault-on-a-non-stringable-argument-to-macro.patch
+
+Patch6073: backport-Remove-obscure-check-for-package-build-time-from-reb.patch
+Patch6074: backport-Fix-possible-null-pointer-reference-in-ndb.patch
+Patch6075: backport-Fix-rpmDigestBundleFinal-and-Update-return-code-on-i.patch
+Patch6076: backport-Actually-return-an-error-in-parseScript-if-parsing-f.patch
+Patch6077: backport-Check-inside-root-when-querying-for-files.patch
+Patch6078: backport-bugfix-wrong-symlink-length-on-some-filesystems.patch
+
+BuildRequires: gcc autoconf automake libtool make gawk popt-devel openssl-devel readline-devel
+BuildRequires: zlib-devel zstd-devel >= 1.3.8 xz-devel bzip2-devel libarchive-devel ima-evm-utils-devel
+BuildRequires: dbus-devel fakechroot elfutils-devel elfutils-libelf-devel ima-evm-utils
+BuildRequires: lua-devel libcap-devel libacl-devel libselinux-devel file-devel gettext-devel ncurses-devel
+BuildRequires: system-rpm-config dwz gnupg2 debugedit
+Requires: coreutils popt curl zstd >= 1.4.0 libcap crontabs logrotate
+Obsoletes: %{name}-build-libs %{name}-sign-libs %{name}-sign %{name}-cron
+Provides: %{name}-build-libs %{name}-sign-libs %{name}-sign %{name}-cron
+Obsoletes: %{name}-plugin-selinux %{name}-plugin-syslog %{name}-plugin-systemd-inhibit < 4.15.1-28 %{name}-plugin-ima %{name}-plugin-prioreset
+Provides: %{name}-plugin-selinux %{name}-plugin-syslog %{name}-plugin-ima %{name}-plugin-prioreset
+
+%description
+The RPM Package Manager (RPM) is a powerful package management system capability as below
+
+-building computer software from source into easily distributable packages
+-installing, updating and uninstalling packaged software
+-querying detailed information about the packaged software, whether installed or not
+-verifying integrity of packaged software and resulting software installation
+
+%package libs
+Summary: Shared library of rpm 4.17
+Requires: %{name} = %{version}-%{release}
+
+%description libs
+Shared library of rpm 4.17.
+
+%package build
+Summary: Scripts and executable programs used to build packages
+Requires: %{name} = %{version}-%{release}
+Requires: elfutils binutils findutils sed grep gawk diffutils file patch
+Requires: tar unzip gzip bzip2 cpio xz zstd pkgconfig system-rpm-config
+Requires: gdb-headless debugedit
+
+%description build
+This package provides scripts and executable programs that used to
+build rpm packages.
+
+%package -n python3-%{name}
+Summary: Python3 bindings for RPM user
+BuildRequires: python3-devel
+%{?python_provide:%python_provide python3-%{name}}
+Requires: %{name} = %{version}-%{release}
+Provides: %{name}-python3 = %{version}-%{release}
+Obsoletes: %{name}-python3 < %{version}-%{release}
+
+%description -n python3-%{name}
+This package contains a module that allow applications
+written with Python3 to use the interface
+supplied by RPM.
+
+%package devel
+Summary: Development files for RPM handling
+Requires: %{name} = %{version}-%{release}
+Requires: popt-devel
+
+%description devel
+%{summary}.
+
+%package plugin-systemd-inhibit
+Summary: rpm plugin to get systemd-inhibit lock
+Requires: %{name} = %{version}-%{release}
+
+%description plugin-systemd-inhibit
+This package use systemd-inhibit to block systemd from entering
+idle, sleep or shutdown while an rpm transcation is running.
+
+%package help
+Summary: Man page for %{name}
+BuildArch: noarch
+Obsoletes: apidocs
+
+%description help
+%{summary}.
+
+%prep
+%autosetup -n %{name}-%{version} -p1
+%ifnarch sw_64
+%patch23 -R -p1
+%endif
+
+%build
+CPPFLAGS="$CPPFLAGS -DLUA_COMPAT_APIINTCASTS"
+CFLAGS="$RPM_OPT_FLAGS -DLUA_COMPAT_APIINTCASTS"
+LDFLAGS="$LDFLAGS %{?__global_ldflags}"
+export CPPFLAGS CFLAGS LDFLAGS
+
+autoreconf -i -f
+
+for i in $(find . -name ltmain.sh) ; do
+ %{__sed} -i.backup -e 's~compiler_flags=$~compiler_flags="%{_hardened_ldflags}"~' $i
+done;
+
+./configure \
+ --prefix=%{_usr} \
+ --sysconfdir=%{_sysconfdir} \
+ --localstatedir=%{_var} \
+ --sharedstatedir=%{_var}/lib \
+ --libdir=%{_libdir} \
+ --build=%{_target_platform} \
+ --host=%{_target_platform} \
+ --with-vendor=%{_vendor} \
+ --with-external-db \
+ --with-lua \
+ --with-selinux \
+ --with-cap \
+ --with-acl \
+ --with-imaevm \
+ --enable-zstd \
+ --enable-python \
+ --enable-bdb-ro \
+ --enable-ndb \
+ --enable-bdb=no \
+ --enable-sqlite=no \
+ --with-crypto=openssl \
+ --with-fapolicyd=no \
+ --with-fsverity=no
+
+%make_build
+
+pushd python
+%{__python3} setup.py build
+popd
+
+%install
+%make_install
+
+pushd python
+%{__python3} setup.py install --skip-build --root $RPM_BUILD_ROOT
+popd
+
+mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily
+install -m 755 scripts/rpm.daily ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily/rpm
+
+# During the upgrade of the major rpm version, the dynamic library may not be compatible.
+# Therefore, ensure that no other rpm command is executed during the upgrade. A judgment
+# is added to the RPM script of the scheduled task. If the dynamic library is not the
+# dynamic library of the current version, exits directly.
+pushd ${RPM_BUILD_ROOT}%{_libdir}
+export SONAME=`ls librpm.so.*.*.*`
+popd
+sed -i "/bin\/sh/a \
+if [ ! -e %{_libdir}\/${SONAME} ]; then\n\
+ exit 0\n\
+fi" ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily/rpm
+cp ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily/rpm ${RPM_BUILD_ROOT}%{_rpmconfigdir}/rpm.daily
+
+mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d
+install -m 644 scripts/rpm.log ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/rpm
+
+install -m 755 build-aux/config.guess ${RPM_BUILD_ROOT}%{_rpmconfigdir}/
+install -m 755 build-aux/config.sub ${RPM_BUILD_ROOT}%{_rpmconfigdir}/
+
+mkdir -p ${RPM_BUILD_ROOT}/usr/lib/tmpfiles.d
+echo "r /var/lib/rpm/__db.*" > ${RPM_BUILD_ROOT}/usr/lib/tmpfiles.d/rpm.conf
+
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/rpm
+mkdir -p $RPM_BUILD_ROOT%{_rpmconfigdir}/macros.d
+mkdir -p $RPM_BUILD_ROOT/var/lib/rpm
+
+./rpmdb --define "_db_backend ndb" --dbpath=$(pwd)/ndb/ --initdb
+cp -va ndb/. $RPM_BUILD_ROOT/var/lib/rpm/
+
+%find_lang %{name}
+
+find $RPM_BUILD_ROOT -name "*.la"|xargs rm -f
+
+rm -f $RPM_BUILD_ROOT/%{_rpmconfigdir}/{perldeps.pl,perl.*,pythond*}
+rm -f $RPM_BUILD_ROOT/%{_fileattrsdir}/{perl*,python*}
+rm -f $RPM_BUILD_ROOT/%{_rpmconfigdir}/{tcl.req,osgideps.pl}
+rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/dbus-1/system.d/org.rpm.conf
+
+%check
+%ifnarch loongarch64
+make check || (cat tests/rpmtests.log; exit 0)
+%endif
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%post libs -p /sbin/ldconfig
+
+%postun libs -p /sbin/ldconfig
+
+%posttrans
+{
+ set -e
+ disable_auto_rebuilddb=$(rpm -E 0%%{?_disable_auto_rebuilddb})
+ if [ ${disable_auto_rebuilddb} -eq 0 ]; then
+ dbpath=$(rpm -E %{_dbpath})
+ while [ -e ${dbpath}/Packages ]
+ do
+ date >> /var/log/rebuilddb.log 2>&1
+ rpm -vvv --rebuilddb >> /var/log/rebuilddb.log 2>&1
+ done
+ fi
+} &
+
+%files -f %{name}.lang
+%defattr(-,root,root)
+%license COPYING
+%doc CREDITS
+/usr/lib/tmpfiles.d/rpm.conf
+%{_sysconfdir}/cron.daily/rpm
+%config(noreplace) %{_sysconfdir}/logrotate.d/rpm
+%dir %{_sysconfdir}/rpm
+%dir /var/lib/rpm
+%attr(0644, root, root) %ghost %config(missingok,noreplace) /var/lib/rpm/*
+%attr(0644, root, root) %ghost /var/lib/rpm/.*.lock
+%lang(fr) %{_mandir}/fr/man[18]/*.[18]*
+%lang(ko) %{_mandir}/ko/man[18]/*.[18]*
+%lang(ja) %{_mandir}/ja/man[18]/*.[18]*
+%lang(pl) %{_mandir}/pl/man[18]/*.[18]*
+%lang(ru) %{_mandir}/ru/man[18]/*.[18]*
+%lang(sk) %{_mandir}/sk/man[18]/*.[18]*
+
+%attr(0755, root, root) %dir %{_rpmconfigdir}
+%{_rpmconfigdir}/macros
+%{_rpmconfigdir}/macros.d
+%{_rpmconfigdir}/rpmpopt*
+%{_rpmconfigdir}/rpmrc
+%{_rpmconfigdir}/rpmdb_*
+%{_rpmconfigdir}/rpm.daily
+%{_rpmconfigdir}/rpm.log
+%{_rpmconfigdir}/rpm.supp
+%{_rpmconfigdir}/rpm2cpio.sh
+%{_rpmconfigdir}/tgpg
+%{_rpmconfigdir}/platform
+%{_libdir}/rpm-plugins/
+%exclude %{_libdir}/rpm-plugins/systemd_inhibit.so
+%exclude %{_libdir}/rpm-plugins/fsverity.so
+%exclude %{_libdir}/rpm-plugins/dbus_announce.so
+%dir %{_rpmconfigdir}/fileattrs
+%{_bindir}/rpm
+%{_bindir}/rpm2archive
+%{_bindir}/rpm2cpio
+%{_bindir}/rpmdb
+%{_bindir}/rpmkeys
+%{_bindir}/rpmquery
+%{_bindir}/rpmverify
+%{_bindir}/rpmsign
+
+%files libs
+%{_libdir}/librpm*.so.9*
+
+%files build
+%defattr(-,root,root)
+%{_bindir}/rpmbuild
+%{_bindir}/gendiff
+%{_bindir}/rpmspec
+
+%{_rpmconfigdir}/brp-*
+%{_rpmconfigdir}/check-*
+%{_rpmconfigdir}/find-lang.sh
+%{_rpmconfigdir}/*provides*
+%{_rpmconfigdir}/*requires*
+%{_rpmconfigdir}/*deps*
+%{_rpmconfigdir}/*.prov
+%{_rpmconfigdir}/*.req
+%{_rpmconfigdir}/mkinstalldirs
+%{_rpmconfigdir}/fileattrs/*
+%{_rpmconfigdir}/config.*
+
+%files -n python3-%{name}
+%defattr(-,root,root)
+%{python3_sitearch}/%{name}/
+%{python3_sitearch}/%{name}-%{version}*.egg-info
+
+%files devel
+%defattr(-,root,root)
+%{_bindir}/rpmgraph
+%{_libdir}/librp*[a-z].so
+%{_libdir}/pkgconfig/%{name}.pc
+%{_includedir}/%{name}/
+
+%files plugin-systemd-inhibit
+%{_libdir}/rpm-plugins/systemd_inhibit.so
+%{_mandir}/man8/rpm-plugin-systemd-inhibit.8*
+
+%files help
+%defattr(-,root,root)
+%doc docs/manual/[a-z]*
+%doc docs/librpm/html/*
+%{_mandir}/man8/rpm*.8*
+%exclude %{_mandir}/man8/rpm-plugin-systemd-inhibit.8*
+%exclude %{_mandir}/man8/rpm-plugin-dbus-announce.8*
+%{_mandir}/man1/gendiff.1*
+
+%changelog
+* Sun Sep 10 2023 chencheng<chenc136@chinaunicom.cn> - 4.17.0-31
+- add patch 6078
+
+* Fri Sep 08 2023 renhongxun<renhongxun@h-partners.com> - 4.17.0-30
+- support _disable_auto_rebuilddb macro in posttrans
+
+* Tue Sep 05 2023 renhongxun<renhongxun@h-partners.com> - 4.17.0-29
+- Fix the coredump which may occur during upgrading of rpm
+
+* Tue Aug 29 2023 renhongxun<renhongxun@h-partners.com> - 4.17.0-28
+- Check inside --root when querying for files
+
+* Wed Aug 02 2023 renhongxun<renhongxun@h-partners.com> - 4.17.0-27
+- backport some patches from upstream
+
+* Fri Jun 16 2023 renhongxun<renhongxun@h-partners.com> - 4.17.0-26
+- Fix a segfault on a non-stringable argument to macro call from Lua
+
+* Tue Jun 13 2023 renhongxun<renhongxun@h-partners.com> - 4.17.0-25
+- Fix a copy-paste --help description of --whatconflicts
+
+* Tue Feb 28 2023 renhongxun<renhongxun@h-partners.com> - 4.17.0-24
+- bugfix with upstream patches about fifo
+
+* Mon Dec 26 2022 xujing<xujing125@huawei.com> - 4.17.0-23
+- backport patches from upstream to fix resource leak
+
+* Mon Dec 19 2022 xujing<xujing125@huawei.com> - 4.17.0-22
+- Fix file leak when src rpm in URL format is used for installation
+
+* Mon Dec 19 2022 xujing<xujing125@huawei.com> - 4.17.0-21
+- backport patches from upstream to fix memleak
+
+* Mon Nov 28 2022 renhongxun<renhongxun@h-partners.com> - 4.17.0-20
+- Move file metadata setting back to unpack stage
+
+* Wed Nov 16 2022 huajingyun<huajingyun@loongson.cn> - 4.17.0-19
+- add default machine name loongarch support
+- disable test on loongarch
+
+* Tue Nov 8 2022 xujing<xujing125@huawei.com> - 4.17.0-18
+- rpm: fix rpm is blocked when open fifo file
+
+* Mon Nov 7 2022 wuzx<wuzx1226@qq.com> - 4.17.0-17
+- Add sw64 architecture
+
+* Thu Oct 27 2022 licunlong<licunlong1@huawei.com> - 4.17.0-16
+- sync patches from upstream
+
+* Fri Sep 09 2022 renhongxun<renhongxun@h-partners.com> - 4.17.0-15
+- sync patches from upstream
+
+* Wed Aug 31 2022 Hongxun Ren<renhongxun@h-partners.com> - 4.17.0-14
+- fix CVE-2021-35937 CVE-2021-35938 CVE-2021-35939
+
+* Tue Aug 16 2022 Kou Wenqi<kouwenqi@kylinos.cn> - 4.17.0-13
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:requires zstd >= 1.4.0, requires zstd-devel >= 1.3.8 in build
+
+* Thu Aug 11 2022 renhongxun<renhongxun@h-partners.com> - 4.17.0-12
+- sync some patches from upstream
+
+* Thu Aug 11 2022 renhongxun<renhongxun@h-partners.com> - 4.17.0-11
+- sync some patches from upstream
+
+* Mon Aug 08 2022 renhongxun<renhongxun@h-partners.com> - 4.17.0-10
+- sync some patches from upstream
+
+* Thu Jun 23 2022 renhongxun<renhongxun@h-partners.com> - 4.17.0-9
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:requires zstd >= 1.5.0
+
+* Wed Mar 16 2022 luhuaxin<luhuaxin1@huawei.com> - 4.17.0-8
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:fix issue of digest-list-tools upgrading
+
+* Tue Mar 15 2022 luhuaxin<luhuaxin1@huawei.com> - 4.17.0-7
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:backport IMA patches from 21.03
+
+* Thu Feb 17 2022 renhongxun<renhongxun@h-partners.com> - 4.17.0-6
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:delete some libdb symbolic link
+
+* Tue Jan 11 2022 Sunhaiyong <sunhaiyong@loongson.cn> - 4.17.0-5
+- Add loongarch support.
+
+* Thu Jan 06 2022 renhongxun<renhongxun@huawei.com> - 4.17.0-4
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:delete new plugins' files
+
+* Tue Jan 04 2022 renhongxun<renhongxun@huawei.com> - 4.17.0-3
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:disable three new plugins
+
+* Wed Dec 29 2021 renhongxun<renhongxun@huawei.com> - 4.17.0-2
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:still in use of python scripts from old version
+
+* Mon Dec 13 2021 renhongxun<renhongxun@huawei.com> - 4.17.0-1
+- Type:requirement
+- ID:NA
+- SUG:NA
+- DESC:upgrade to 4.17.0
+
+* Fri Dec 3 2021 luhuaxin<1539327763@qq.com> - 4.15.1-32
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:rpm selinux plugin check context file exist
+
+* Wed Nov 03 2021 tianwei <tianwei12@huawei.com> - 4.15.1-31
+- Type:cve
+- ID:NA
+- SUG:NA
+- DESC:fix CVE-2021-3521
+
+* Mon Sep 13 2021 zhangtianxing<zhangtianxing3@huawei.com> - 4.15.1-30
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:fix lsetxattr error in container
+
+* Thu Jul 22 2021 liudabo<liudabo1@huawei.com> - 4.15.1-29
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:deleting gdb build dependency
+
+* Thu Jul 08 2021 shixuantong <shixuantong@huawei.com> - 4.15.1-28
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:split rpm-plugin-systemd-inhibit out of rpm.
+
+* Thu Jul 08 2021 shixuantong <shixuantong@huawei.com> - 4.15.1-27
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:remove unnecessary installation dependencies
+
+* Mon Jun 28 2021 shangyibin <shangyibin1@huawei.com> - 4.15.1-26
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:modify dependency
+
+* Wed Jun 09 2021 shixuantong <shixuantong@huawei.com> - 4.15.1-25
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:Fix data race in packageBinaries() function and prioritize large packages
+
+* Wed Jun 2 2021 guoxiaoqi<guoxiaoqi2@huawei.com> - 4.15.1-23
+- Type:cve
+- ID:NA
+- SUG:NA
+- DESC:fix CVE-2021-20266
+
+* Sat May 22 2021 liudabo<liudabo1@huawei.com> - 4.15.1-22
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:Optimize signature header merge a bit
+
+* Tue Apr 13 2021 liudabo<liudabo1@huawei.com> - 4.15.1-22
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:Fix CVE-2021-20271
+
+* Mon Jan 11 2021 Liquor <lirui130@huawei.com> - 4.15.1-21
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:backport patches from upstream
+
+* Thu Dec 17 2020 Anakin Zhang <benjamin93@163.com> - 4.15.1-20
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:call process_digest_list before files are added
+
+* Thu Dec 17 2020 Anakin Zhang <benjamin93@163.com> - 4.15.1-19
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:use user.digest_list to avoid duplicate processing of the digest lists
+
+* Thu Oct 29 2020 Liquor <lirui130@huawei.com> - 4.15.1-18
+- Type:requirement
+- ID:NA
+- SUG:NA
+- DESC:remove python2
+
+* Tue Jul 14 2020 Roberto Sassu <roberto.sassu@huawei.com> - 4.15.1-17
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:add support for digest lists
+
+* Fri May 22 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-16
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:solve the error of setexecfilecon
+
+* Wed May 13 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-15
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:solve the failure of rpmsigdig.at test
+
+* Mon Mar 30 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-14
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:add requires of some common build packages to rpm-build
+
+* Wed Mar 25 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-13
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:revert always execute file trigger scriptlet callbacks with owning header
+
+* Fri Mar 6 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-12
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:silence spurious error message from lsetfilecon()
+
+* Wed Mar 4 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-11
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:add dist to release by default
+
+* Mon Mar 2 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-10
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:revert last commit
+
+* Thu Feb 27 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-9
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:add dist to the name of package
+
+* Fri Feb 14 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-8
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:skip update the preference of gpg during make check
+
+* Mon Jan 20 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-7
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:delete unneeded obsoletes
+
+* Sat Jan 18 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-6
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:delete unneeded shared library
+
+* Tue Jan 14 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-5
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:change requires to build requires
+
+* Tue Jan 14 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-4
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:add build requires of ima-evm-utils and old shared library
+
+* Mon Jan 13 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-3
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:add requires of shared library
+
+* Mon Jan 13 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-2
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:add subpack of librpm8 and librpm9 to support update
+
+* Fri Jan 10 2020 openEuler Buildteam <buildteam@openeuler.org> - 4.15.1-1
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:update version to 4.15.1
+
+* Tue Dec 24 2019 openEuler Buildteam <buildteam@openeuler.org> - 4.14.2-5
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:bugfix in files
+
+* Wed Nov 13 2019 hexiaowen<hexiaowen@huawei.com> - 4.14.2-4
+- add system-rpm-config buildrequires
+
+* Fri Sep 20 2019 openEuler Buildteam <buildteam@openeuler.org> - 4.14.2-3
+- Delete redundant information
+
+* Mon Sep 09 2019 openEuler Buildteam <buildteam@openeuler.org> - 4.14.2-2
+- Package init
diff --git a/sources b/sources
new file mode 100644
index 0000000..7b938d4
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+ba23b5d2403fd2f9163dfd0dadce1820 rpm-4.17.0.tar.bz2
diff --git a/still-in-use-of-python-scripts-from-old-version.patch b/still-in-use-of-python-scripts-from-old-version.patch
new file mode 100644
index 0000000..d9fee0b
--- /dev/null
+++ b/still-in-use-of-python-scripts-from-old-version.patch
@@ -0,0 +1,210 @@
+From 4ec83c32024a8faf0a66a4275acbcd15751ee303 Mon Sep 17 00:00:00 2001
+From: renhongxun <renhongxun@huawei.com>
+Date: Wed, 29 Dec 2021 16:37:45 +0800
+Subject: [PATCH] still in use of python scripts from old version
+
+---
+ platform.in | 3 ++
+ scripts/Makefile.am | 8 +--
+ scripts/brp-python-bytecompile | 112 +++++++++++++++++++++++++++++++++++++++++
+ scripts/brp-python-hardlink | 25 +++++++++
+ 4 files changed, 144 insertions(+), 4 deletions(-)
+ create mode 100644 scripts/brp-python-bytecompile
+ create mode 100755 scripts/brp-python-hardlink
+
+diff --git a/platform.in b/platform.in
+index 71496b8..748186e 100644
+--- a/platform.in
++++ b/platform.in
+@@ -82,10 +82,13 @@
+ #
+
+ %__arch_install_post @ARCH_INSTALL_POST@
++%_python_bytecompile_errors_terminate_build 0
++%_python_bytecompile_extra 1
+
+ # Standard brp-macro naming:
+ # convert all '-' in basename to '_', add two leading underscores.
+ %__brp_compress %{_rpmconfigdir}/brp-compress %{?_prefix}
++%__brp_python_bytecompile %{_rpmconfigdir}/brp-python-bytecompile "" "%{?_python_bytecompile_errors_terminate_build}" "%{?_python_bytecompile_extra}"
+ %__brp_strip %{_rpmconfigdir}/brp-strip %{__strip}
+ %__brp_strip_comment_note %{_rpmconfigdir}/brp-strip-comment-note %{__strip} %{__objdump}
+ %__brp_strip_static_archive %{_rpmconfigdir}/brp-strip-static-archive %{__strip}
+diff --git a/scripts/Makefile.am b/scripts/Makefile.am
+index 4aed76b..5a1c494 100644
+--- a/scripts/Makefile.am
++++ b/scripts/Makefile.am
+@@ -6,8 +6,8 @@ AM_CFLAGS = @RPMCFLAGS@
+ CLEANFILES =
+
+ EXTRA_DIST = \
+- brp-compress \
+- brp-strip brp-strip-comment-note \
++ brp-compress brp-python-bytecompile \
++ brp-strip brp-strip-comment-note brp-python-hardlink \
+ brp-strip-static-archive brp-elfperms \
+ brp-remove-la-files \
+ check-files check-prereqs \
+@@ -23,8 +23,8 @@ EXTRA_DIST = \
+ fontconfig.prov script.req
+
+ rpmconfig_SCRIPTS = \
+- brp-compress \
+- brp-strip brp-strip-comment-note \
++ brp-compress brp-python-bytecompile \
++ brp-strip brp-strip-comment-note brp-python-hardlink \
+ brp-strip-static-archive brp-elfperms \
+ brp-remove-la-files \
+ check-files check-prereqs \
+diff --git a/scripts/brp-python-bytecompile b/scripts/brp-python-bytecompile
+new file mode 100644
+index 0000000..d9c4832
+--- /dev/null
++++ b/scripts/brp-python-bytecompile
+@@ -0,0 +1,112 @@
++#!/bin/bash
++errors_terminate=$2
++extra=$3
++
++# If using normal root, avoid changing anything.
++if [ -z "$RPM_BUILD_ROOT" ] || [ "$RPM_BUILD_ROOT" = "/" ]; then
++ exit 0
++fi
++
++# Figure out how deep we need to descend. We could pick an insanely high
++# number and hope it's enough, but somewhere, somebody's sure to run into it.
++depth=`(find "$RPM_BUILD_ROOT" -type f -name "*.py" -print0 ; echo /) | \
++ xargs -0 -n 1 dirname | sed 's,[^/],,g' | sort -u | tail -n 1 | wc -c`
++if [ -z "$depth" ] || [ "$depth" -le "1" ]; then
++ exit 0
++fi
++
++function python_bytecompile()
++{
++ local options=$1
++ local python_binary=$2
++ local exclude=$3
++ local python_libdir=$4
++ local depth=$5
++ local real_libdir=$6
++
++cat << EOF | $python_binary $options
++import compileall, sys, os, re
++
++python_libdir = "$python_libdir"
++depth = $depth
++real_libdir = "$real_libdir"
++build_root = "$RPM_BUILD_ROOT"
++exclude = r"$exclude"
++
++class Filter:
++ def search(self, path):
++ ret = not os.path.realpath(path).startswith(build_root)
++ if exclude:
++ ret = ret or re.search(exclude, path)
++ return ret
++
++sys.exit(not compileall.compile_dir(python_libdir, depth, real_libdir, force=1, rx=Filter(), quiet=1))
++EOF
++}
++
++# .pyc/.pyo files embed a "magic" value, identifying the ABI version of Python
++# bytecode that they are for.
++#
++# The files below RPM_BUILD_ROOT could be targeting multiple versions of
++# python (e.g. a single build that emits several subpackages e.g. a
++# python26-foo subpackage, a python31-foo subpackage etc)
++#
++# Support this by assuming that below each /usr/lib/python$VERSION/, all
++# .pyc/.pyo files are to be compiled for /usr/bin/python$VERSION.
++#
++# For example, below /usr/lib/python2.6/, we're targeting /usr/bin/python2.6
++# and below /usr/lib/python3.1/, we're targeting /usr/bin/python3.1
++
++shopt -s nullglob
++for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]$"`;
++do
++ python_binary=/usr/bin/$(basename $python_libdir)
++ real_libdir=${python_libdir/$RPM_BUILD_ROOT/}
++ echo "Bytecompiling .py files below $python_libdir using $python_binary"
++
++ # Generate normal (.pyc) byte-compiled files.
++ python_bytecompile "" "$python_binary" "" "$python_libdir" "$depth" "$real_libdir"
++ if [ $? -ne 0 ] && [ 0$errors_terminate -ne 0 ]; then
++ # One or more of the files had a syntax error
++ exit 1
++ fi
++
++ # Generate optimized (.pyo) byte-compiled files.
++ python_bytecompile "-O" "$python_binary" "" "$python_libdir" "$depth" "$real_libdir"
++ if [ $? -ne 0 ] && [ 0$errors_terminate -ne 0 ]; then
++ # One or more of the files had a syntax error
++ exit 1
++ fi
++done
++
++
++# Handle other locations in the filesystem using the default python implementation
++# if extra is set to 0, don't do this
++if [ 0$extra -eq 0 ]; then
++ exit 0
++fi
++
++# If we don't have a default python interpreter, we cannot proceed
++default_python=${1:-/usr/bin/python}
++if [ ! -x "$default_python" ]; then
++ exit 0
++fi
++
++# Figure out if there are files to be bytecompiled with the default_python at all
++# this prevents unnecessary default_python invocation
++find "$RPM_BUILD_ROOT" -type f -name "*.py" | grep -Ev "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" || exit 0
++
++# Generate normal (.pyc) byte-compiled files.
++python_bytecompile "" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/"
++if [ $? -ne 0 ] && [ 0$errors_terminate -ne 0 ]; then
++ # One or more of the files had a syntax error
++ exit 1
++fi
++
++# Generate optimized (.pyo) byte-compiled files.
++python_bytecompile "-O" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/"
++if [ $? -ne 0 ] && [ 0$errors_terminate -ne 0 ]; then
++ # One or more of the files had a syntax error
++ exit 1
++fi
++exit 0
+diff --git a/scripts/brp-python-hardlink b/scripts/brp-python-hardlink
+new file mode 100755
+index 0000000..5fd1b43
+--- /dev/null
++++ b/scripts/brp-python-hardlink
+@@ -0,0 +1,25 @@
++#!/bin/sh
++
++# If using normal root, avoid changing anything.
++if [ -z "$RPM_BUILD_ROOT" ] || [ "$RPM_BUILD_ROOT" = "/" ]; then
++ exit 0
++fi
++
++hardlink_if_same() {
++ if cmp -s "$1" "$2" ; then
++ ln -f "$1" "$2"
++ return 0
++ fi
++ return 1
++}
++
++# Hardlink identical *.pyc, *.pyo, and *.opt-[12].pyc.
++# Originally from PLD's rpm-build-macros
++find "$RPM_BUILD_ROOT" -type f -name "*.pyc" -not -name "*.opt-[12].pyc" | while read pyc ; do
++ hardlink_if_same "$pyc" "${pyc%c}o"
++ o1pyc="${pyc%pyc}opt-1.pyc"
++ hardlink_if_same "$pyc" "$o1pyc"
++ o2pyc="${pyc%pyc}opt-2.pyc"
++ hardlink_if_same "$pyc" "$o2pyc" || hardlink_if_same "$o1pyc" "$o2pyc"
++done
++exit 0
+--
+1.8.3.1
+