diff --git a/Add-digest-list-plugin.patch b/Add-digest-list-plugin.patch new file mode 100644 index 0000000000000000000000000000000000000000..2256824aab1dd088f315df3db387587d3fc1cc32 --- /dev/null +++ b/Add-digest-list-plugin.patch @@ -0,0 +1,586 @@ +From e49074a4e4bd0699d2c4a5bb3a0dc5ca45e19e12 Mon Sep 17 00:00:00 2001 +From: Roberto Sassu +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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include "lib/rpmplugin.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 0000000000000000000000000000000000000000..fe07b05c81fcb7df548e19715732dbf1d0de2106 --- /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 +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 ++ * ++ * 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 index 15f7d517488ad7f2aca4098933373af9052f9729..80c9c41a2e7b3c6469798fec4314c02114d50a5f 100644 --- a/Add-loongarch-architecture-support.patch +++ b/Add-loongarch-architecture-support.patch @@ -9,7 +9,7 @@ Subject: [PATCH] Add loongarch architecture support. 2 files changed, 29 insertions(+) diff --git a/installplatform b/installplatform -index dd9effb..b8e6c33 100755 +index 12339fc..74c50a2 100755 --- a/installplatform +++ b/installplatform @@ -168,6 +168,18 @@ for ARCH in noarch `grep ^arch_canon $RPMRC | cut -d: -f2`; do @@ -32,7 +32,7 @@ index dd9effb..b8e6c33 100755 ISANAME=m68k ISABITS=32 diff --git a/rpmrc.in b/rpmrc.in -index f541b0e..9caa76c 100644 +index 5bd9ba3..fc2932a 100644 --- a/rpmrc.in +++ b/rpmrc.in @@ -67,6 +67,8 @@ optflags: mipsr6el -O2 -g @@ -44,7 +44,7 @@ index f541b0e..9caa76c 100644 optflags: armv3l -O2 -g -march=armv3 optflags: armv4b -O2 -g -march=armv4 optflags: armv4l -O2 -g -march=armv4 -@@ -139,6 +141,9 @@ archcolor: mipsr6el 1 +@@ -137,6 +139,9 @@ archcolor: mipsr6el 1 archcolor: mips64r6 2 archcolor: mips64r6el 2 @@ -54,9 +54,9 @@ index f541b0e..9caa76c 100644 archcolor: m68k 1 archcolor: m68kmint 1 -@@ -265,6 +270,9 @@ arch_canon: riscv64: riscv64 22 - - arch_canon: loongarch64: loongarch64 23 +@@ -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 @@ -64,7 +64,7 @@ index f541b0e..9caa76c 100644 ############################################################# # Canonical OS names and numbers -@@ -368,6 +376,9 @@ buildarchtranslate: mipsr6el: mipsr6el +@@ -360,6 +368,9 @@ buildarchtranslate: mipsr6el: mipsr6el buildarchtranslate: mips64r6: mips64r6 buildarchtranslate: mips64r6el: mips64r6el @@ -74,7 +74,7 @@ index f541b0e..9caa76c 100644 buildarchtranslate: m68k: m68k buildarchtranslate: atarist: m68kmint -@@ -460,6 +471,9 @@ arch_compat: mipsr6el: noarch +@@ -449,6 +460,9 @@ arch_compat: mipsr6el: noarch arch_compat: mips64r6: mipsr6 arch_compat: mips64r6el: mipsr6el @@ -84,7 +84,7 @@ index f541b0e..9caa76c 100644 arch_compat: hppa2.0: hppa1.2 arch_compat: hppa1.2: hppa1.1 arch_compat: hppa1.1: hppa1.0 -@@ -602,6 +616,9 @@ buildarch_compat: mipsr6el: noarch +@@ -586,6 +600,9 @@ buildarch_compat: mipsr6el: noarch buildarch_compat: mips64r6: noarch buildarch_compat: mips64r6el: noarch @@ -95,5 +95,5 @@ index f541b0e..9caa76c 100644 buildarch_compat: armv8l: armv7l buildarch_compat: armv7l: armv6l -- -2.26.2 +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 0000000000000000000000000000000000000000..ecfedb9c2f70b9a3e0599a86e2ea014bbd0efc8b --- /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 +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 0000000000000000000000000000000000000000..43052a291b287814cc3db4ad4329021b44b3f724 --- /dev/null +++ b/Check-rpm-parser.patch @@ -0,0 +1,29 @@ +From 18df7feaf512cf4d7548121e1f04d4e7066fb324 Mon Sep 17 00:00:00 2001 +From: Roberto Sassu +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 0000000000000000000000000000000000000000..8820ef2dd49427ed9a50e05ac4e87f7eb7a38a2f --- /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 +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 0000000000000000000000000000000000000000..b9a3cd9c9887195371a3b3f7b09c21bce8d47005 --- /dev/null +++ b/Fix-digest_list_counter.patch @@ -0,0 +1,81 @@ +From 8ecd5fc6884ae165e38e16b900cc4da90665b9db Mon Sep 17 00:00:00 2001 +From: Roberto Sassu +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 0000000000000000000000000000000000000000..bc85a01698ae70942d41c7d718908633178c1ca8 --- /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 +Date: Wed, 12 Aug 2020 18:23:42 +0200 +Subject: [PATCH] Generate digest lists before calling genCpioListAndHeader() + +Signed-off-by: luhuaxin +--- + 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 index f1a23733bf3c43db2f9e231f65afc945a011d30d..7fbac1c9fdbaf0c1f28a2637b9b421ad311400e5 100644 --- a/Generate-digest-lists.patch +++ b/Generate-digest-lists.patch @@ -1,33 +1,25 @@ -From 4006d48a5492749cc09fdf42d640a8be59be32eb Mon Sep 17 00:00:00 2001 +From 4d1801825c754171962050ee9c36c2d69c630ece Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 12 Mar 2020 17:29:55 +0100 -Subject: [PATCH] Generate digest lists +Subject: [PATCH 1/3] Generate digest lists --- - build/files.c | 296 ++++++++++++++++++- - build/parsePreamble.c | 2 +- - macros.in | 1 + - plugins/Makefile.am | 4 + - plugins/digest_list.c | 611 ++++++++++++++++++++++++++++++++++++++++ - rpmio/rpmio_internal.h | 31 ++ - rpmio/rpmpgp_internal.c | 33 +-- - 7 files changed, 938 insertions(+), 40 deletions(-) - create mode 100644 plugins/digest_list.c + build/files.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 169 insertions(+), 7 deletions(-) diff --git a/build/files.c b/build/files.c -index 5ae20c6..59c003a 100644 +index 6dfd801c8..ab6938d8c 100644 --- a/build/files.c +++ b/build/files.c -@@ -50,6 +50,8 @@ +@@ -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" -+#define DEST_DIGEST_LIST_DIR "/etc/ima/digest_lists" #undef HASHTYPE #undef HTKEYTYPE -@@ -129,6 +131,8 @@ typedef struct AttrRec_s { +@@ -129,6 +130,8 @@ typedef struct AttrRec_s { /* list of files */ static StringBuf check_fileList = NULL; @@ -36,7 +28,7 @@ index 5ae20c6..59c003a 100644 typedef struct FileEntry_s { rpmfileAttrs attrFlags; -@@ -193,6 +197,10 @@ typedef struct FileList_s { +@@ -193,6 +196,10 @@ typedef struct FileList_s { struct FileEntry_s cur; } * FileList; @@ -47,112 +39,48 @@ index 5ae20c6..59c003a 100644 static void nullAttrRec(AttrRec ar) { memset(ar, 0, sizeof(*ar)); -@@ -984,6 +992,132 @@ static int seenHardLink(FileRecords files, FileListRec flp, rpm_ino_t *fileid) - return 0; - } - -+ -+static void genDigestListInput(FileList fl, Package pkg, int isSrc) -+{ -+ FileListRec flp; -+ char buf[BUFSIZ]; +@@ -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, gen_digest_lists = 1; -+ 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); + 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); + -+ if (check_fileList_bin_pkg && S_ISREG(flp->fl_mode) && + 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); @@ -165,84 +93,23 @@ index 5ae20c6..59c003a 100644 + 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 (gen_digest_lists && -+ 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) -@@ -996,6 +1130,8 @@ 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 = RPM_HASH_MD5, digestalgo; -@@ -1003,7 +1139,11 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) - Header h = pkg->header; /* just a shortcut */ - 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 - * https://reproducible-builds.org/specs/source-date-epoch/ -@@ -1200,13 +1340,18 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) - 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); -- -+ 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)); ++ 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; + } -+ - buf[0] = '\0'; - if (S_ISLNK(flp->fl_mode)) { - ssize_t llen = readlink(flp->diskPath, buf, BUFSIZ-1); -@@ -1247,6 +1392,7 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) - - headerPutUint32(h, RPMTAG_FILEFLAGS, &(flp->flags) ,1); } + pkg->dpaths[npaths] = NULL; if (totalFileSize < UINT32_MAX) { -@@ -1285,6 +1431,7 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) - /* 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) -@@ -1359,8 +1506,8 @@ static int validFilename(const char *fn) +@@ -1343,8 +1380,8 @@ static int validFilename(const char *fn) * @param statp file stat (possibly NULL) * @return RPMRC_OK on success */ @@ -253,7 +120,7 @@ index 5ae20c6..59c003a 100644 { size_t plen = strlen(diskPath); char buf[plen + 1]; -@@ -1371,6 +1518,10 @@ static rpmRC addFile(FileList fl, const char * diskPath, +@@ -1355,6 +1392,10 @@ static rpmRC addFile(FileList fl, const char * diskPath, gid_t fileGid; const char *fileUname; const char *fileGname; @@ -264,7 +131,7 @@ index 5ae20c6..59c003a 100644 rpmRC rc = RPMRC_FAIL; /* assume failure */ /* Strip trailing slash. The special case of '/' path is handled below. */ -@@ -1406,6 +1557,33 @@ static rpmRC addFile(FileList fl, const char * diskPath, +@@ -1390,6 +1431,33 @@ static rpmRC addFile(FileList fl, const char * diskPath, if (*cpioPath == '\0') cpioPath = "/"; @@ -298,7 +165,7 @@ index 5ae20c6..59c003a 100644 /* * Unless recursing, we dont have stat() info at hand. Handle the * various cases, preserving historical behavior wrt %dev(): -@@ -1543,6 +1721,8 @@ static rpmRC addFile(FileList fl, const char * diskPath, +@@ -1527,6 +1595,8 @@ static rpmRC addFile(FileList fl, const char * diskPath, } flp->flags = fl->cur.attrFlags; @@ -307,7 +174,7 @@ index 5ae20c6..59c003a 100644 flp->specdFlags = fl->cur.specdFlags; flp->verifyFlags = fl->cur.verifyFlags; -@@ -1563,6 +1743,32 @@ exit: +@@ -1547,6 +1617,32 @@ exit: return rc; } @@ -340,7 +207,7 @@ index 5ae20c6..59c003a 100644 /** * Add directory (and all of its files) to the package manifest. * @param fl package file tree walk data -@@ -2584,6 +2790,58 @@ static void addPackageFileList (struct FileList_s *fl, Package pkg, +@@ -2556,6 +2652,58 @@ static void addPackageFileList (struct FileList_s *fl, Package pkg, argvFree(fileNames); } @@ -399,7 +266,7 @@ index 5ae20c6..59c003a 100644 static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, Package pkg, int didInstall, int test) { -@@ -2597,6 +2855,10 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, +@@ -2569,6 +2717,10 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, if (readFilesManifest(spec, pkg, *fp)) return RPMRC_FAIL; } @@ -410,17 +277,7 @@ index 5ae20c6..59c003a 100644 /* Init the file list structure */ memset(&fl, 0, sizeof(fl)); -@@ -2652,12 +2914,17 @@ 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: +@@ -2630,6 +2782,7 @@ exit: FileListFree(&fl); specialDirFree(specialDoc); specialDirFree(specialLic); @@ -428,7 +285,7 @@ index 5ae20c6..59c003a 100644 return fl.processingFailed ? RPMRC_FAIL : RPMRC_OK; } -@@ -3126,6 +3393,7 @@ static void addPackageDeps(Package from, Package to, enum rpmTag_e tag) +@@ -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) { @@ -436,7 +293,7 @@ index 5ae20c6..59c003a 100644 Package pkg; rpmRC rc = RPMRC_OK; char *buildroot; -@@ -3142,7 +3410,14 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, +@@ -3108,7 +3262,14 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, check_fileList = newStringBuf(); genSourceRpmName(spec); buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL); @@ -452,7 +309,7 @@ index 5ae20c6..59c003a 100644 if (rpmExpandNumeric("%{?_debuginfo_subpackages}")) { maindbg = findDebuginfoPackage(spec); if (maindbg) { -@@ -3248,6 +3523,7 @@ exit: +@@ -3214,6 +3375,7 @@ exit: check_fileList = freeStringBuf(check_fileList); _free(buildroot); _free(uniquearch); @@ -461,772 +318,6 @@ index 5ae20c6..59c003a 100644 + return rc; } -diff --git a/build/parsePreamble.c b/build/parsePreamble.c -index 722d0ac..eb043a9 100644 ---- a/build/parsePreamble.c -+++ b/build/parsePreamble.c -@@ -801,7 +801,7 @@ 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, NULL)) -diff --git a/macros.in b/macros.in -index 0f67b07..ae2ad1c 100644 ---- a/macros.in -+++ b/macros.in -@@ -1135,6 +1135,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 822c7d2..161fe4c 100644 ---- a/plugins/Makefile.am -+++ b/plugins/Makefile.am -@@ -69,3 +69,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 0000000..698c31e ---- /dev/null -+++ b/plugins/digest_list.c -@@ -0,0 +1,611 @@ -+/* -+ * Copyright (C) 2020-2021 Huawei Technologies Duesseldorf GmbH -+ * -+ * Author: Roberto Sassu -+ * -+ * 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" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "lib/rpmplugin.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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" -+ -+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 (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); -+ _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, 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; -+ cap_user_data_t cap_data = &cap_data_data; -+ 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); -+ -+ if (type == TR_ADDED && !pre && size < 0) { -+ 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; -+ } -+ } -+ -+ /* 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 { -+ ret = write_digest_list_ima_xattr(te, path, path_sig); -+ } -+ -+ if (ret < 0) { -+ 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, type, digest_list_signed); -+ -+ if (type == 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; -+} -+ -+rpmte cur_te; -+int digest_list_counter; -+ -+static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te) -+{ -+ Header rpm = rpmteHeader(te); -+ rpmtd dirnames, dirindexes; -+ int i = -1; -+ -+ 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) && -+ 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; -+} -+ -+static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi, -+ const char* path, mode_t file_mode, -+ rpmFsmOp op, int pre, int res) -+{ -+ 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 && rpmteType(cur_te) != TR_ADDED) -+ return RPMRC_OK; -+ -+ if (pre && action == FA_SKIP) -+ return RPMRC_OK; -+ -+ if (strncmp(path, DIGEST_LIST_DEFAULT_PATH, -+ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1) || -+ path[sizeof(DIGEST_LIST_DEFAULT_PATH) - 1] != '/') -+ return RPMRC_OK; -+ -+ 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 (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; -+} -+ -+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, -+ .fsm_file_pre = digest_list_file_pre, -+ .fsm_file_post = digest_list_file_post, -+}; -diff --git a/rpmio/rpmio_internal.h b/rpmio/rpmio_internal.h -index fb82b04..afb3a06 100644 ---- a/rpmio/rpmio_internal.h -+++ b/rpmio/rpmio_internal.h -@@ -7,11 +7,42 @@ - - #include - #include -+#include - - #ifdef __cplusplus - extern "C" { - #endif - -+/** \ingroup rpmio -+ * Values parsed from OpenPGP signature/pubkey packet(s). -+ */ -+struct pgpDigParams_s { -+ char * userid; -+ uint8_t * hash; -+ uint8_t tag; -+ const uint8_t * data; -+ -+ 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. */ -+ -+ uint8_t hash_algo; -+ uint8_t sigtype; -+ uint32_t hashlen; -+ uint8_t signhash16[2]; -+ pgpKeyID_t signid; -+ 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) -+#define PGPDIG_SIG_HAS_KEY_FLAGS (1 << 3) -+ -+ pgpDigAlg alg; -+}; -+ -+ - void fdSetBundle(FD_t fd, rpmDigestBundle bundle); - rpmDigestBundle fdGetBundle(FD_t fd, int create); - -diff --git a/rpmio/rpmpgp_internal.c b/rpmio/rpmpgp_internal.c -index 19947be..efc206c 100644 ---- a/rpmio/rpmpgp_internal.c -+++ b/rpmio/rpmpgp_internal.c -@@ -19,34 +19,6 @@ - - static int _print = 0; - --/** \ingroup rpmio -- * Values parsed from OpenPGP signature/pubkey packet(s). -- */ --struct pgpDigParams_s { -- char * userid; -- uint8_t * hash; -- 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. */ -- -- uint8_t hash_algo; -- uint8_t sigtype; -- uint32_t hashlen; -- uint8_t signhash16[2]; -- pgpKeyID_t signid; -- 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) --#define PGPDIG_SIG_HAS_KEY_FLAGS (1 << 3) -- -- pgpDigAlg alg; --}; -- - /** \ingroup rpmio - * Container for values parsed from an OpenPGP signature and public key. - */ -@@ -484,6 +456,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - } - - p = ((uint8_t *)v) + sizeof(*v); -+ _digp->data = p; - rc = tag ? pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp) : 0; - } break; - case 4: -@@ -545,7 +518,8 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - p += 2; - if (p > hend) - return 1; -- -+ -+ _digp->data = p; - rc = tag ? pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp) : 0; - } break; - default: -@@ -636,6 +610,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.26.2 +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 0000000000000000000000000000000000000000..2bd6caa8d42cb5d9beeb6a5521be353b6dd13b0e --- /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 +Date: Thu, 11 Mar 2021 11:59:45 +0100 +Subject: [PATCH] Remove digest list from the kernel during package + reinstallation + +Signed-off-by: luhuaxin +--- + 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 index 67c26837db11dfac22a5c447ac4442b2040a2915..920a28583d70b81602d78b09f0de94e65c2feb60 100644 --- a/Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch +++ b/Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch @@ -8,10 +8,10 @@ Subject: [PATCH] Unbundle config site and add RPM LD FLAGS macro 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/macros.in b/macros.in -index 0e801ff..0f67b07 100644 +index fe9803a..4027493 100644 --- a/macros.in +++ b/macros.in -@@ -711,10 +711,11 @@ package or when debugging this package.\ +@@ -794,10 +794,11 @@ package or when debugging this package.\ RPM_SOURCE_DIR=\"%{u2p:%{_sourcedir}}\"\ RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\ RPM_OPT_FLAGS=\"%{optflags}\"\ @@ -24,7 +24,7 @@ index 0e801ff..0f67b07 100644 RPM_DOC_DIR=\"%{_docdir}\"\ export RPM_DOC_DIR\ RPM_PACKAGE_NAME=\"%{NAME}\"\ -@@ -730,6 +731,8 @@ package or when debugging this package.\ +@@ -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\ @@ -34,5 +34,5 @@ index 0e801ff..0f67b07 100644 %[%{verbose}?"set -x":""]\ umask 022\ -- -2.26.2 +1.8.3.1 diff --git a/add-dist-to-release-by-default.patch b/add-dist-to-release-by-default.patch index 0ae2d998a58aed2fc0899194d47980886e6c41c1..36c8226469b03b654840a78a33756780de345740 100644 --- a/add-dist-to-release-by-default.patch +++ b/add-dist-to-release-by-default.patch @@ -1,29 +1,29 @@ -From 67f2f371822dde322047bcae05c433a91022f334 Mon Sep 17 00:00:00 2001 -From: licihua -Date: Thu, 20 Oct 2022 20:32:09 +0800 -Subject: [PATCH 03/22] add dist to release by default +From af9a2347cd725a8dbb6045d7d3e9661d524af110 Mon Sep 17 00:00:00 2001 +From: openEuler Buildteam +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 bd3da19..722d0ac 100644 +index b0a17c8..cac899a 100644 --- a/build/parsePreamble.c +++ b/build/parsePreamble.c -@@ -799,6 +799,11 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, +@@ -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) { ++ if (tag == RPMTAG_RELEASE) { + char *dist = rpmExpand("%{?dist}",NULL); + rasprintf(&field,"%s%s",field,dist); + free(dist); + } - if (rpmCharCheck(spec, field, ALLOWED_CHARS_VERREL, NULL)) + if (rpmCharCheck(spec, field, ALLOWED_CHARS_VERREL)) goto exit; headerPutString(pkg->header, tag, field); -@@ -986,6 +991,8 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, +@@ -987,6 +992,8 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, } rc = RPMRC_OK; exit: @@ -33,5 +33,5 @@ index bd3da19..722d0ac 100644 } -- -2.26.2 +1.8.3.1 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 0000000000000000000000000000000000000000..691208265f2e569eb33dc9281c6ad4f1e5e48247 --- /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 +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-optional-callback-on-directory-changes-during-rp.patch b/backport-Add-optional-callback-on-directory-changes-during-rp.patch new file mode 100644 index 0000000000000000000000000000000000000000..53765d4400397462fa01fc6c838c9e5a31a06dfb --- /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 +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 0000000000000000000000000000000000000000..7b63d29a69d0cdad18d8c5026ff3735e1a318a23 --- /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 +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 0000000000000000000000000000000000000000..d237fa50336d808e20315097299f9b097e8380d5 --- /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 +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 0000000000000000000000000000000000000000..a3bf26085d9718de412dfaaed4d1a5af35d82c85 --- /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 +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 0000000000000000000000000000000000000000..c73590909d29ad1251b383b82fad26bbcec94e46 --- /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 +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 0000000000000000000000000000000000000000..b5f994a9fba736ce670f5d8247f8bb2514d5fde1 --- /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 +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 + #include + #include ++#include + #if WITH_CAP + #include + #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 0000000000000000000000000000000000000000..4e5b3d4758ddbc01402d3708cb7fc6dc93393b50 --- /dev/null +++ b/backport-CVE-2021-35938.patch @@ -0,0 +1,40 @@ +From 25a435e90844ea98fe5eb7bef22c1aecf3a9c033 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +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 0000000000000000000000000000000000000000..ecc32bb4c0363a5f4e6c06be97fd92766341240c --- /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 +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-that-the-CRC-length-is-correct.patch b/backport-Check-that-the-CRC-length-is-correct.patch new file mode 100644 index 0000000000000000000000000000000000000000..8506a456ff10a6b82c6209396832f04e0605758b --- /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 +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 0000000000000000000000000000000000000000..33fd5a3a960c75e8f92c01de00f5e46df913bc9c --- /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 +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 0000000000000000000000000000000000000000..e992dca3b4d2bc9e894967ff1134948ff1043d2b --- /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 +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 0000000000000000000000000000000000000000..1b4de6f856802aa55aea04d762fd4ff6a0fea378 --- /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 +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-OpenPGP-key-ID-parsing-regression.patch b/backport-Fix-OpenPGP-key-ID-parsing-regression.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6189f9d7e36d5ac2787eae24f41299d4ade7ba8 --- /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 +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 0000000000000000000000000000000000000000..26e5cb8404885990990868c098da9e793e9230b8 --- /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 +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-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 0000000000000000000000000000000000000000..baeb339ab1faba95a8bc544ba533bd5a1f532f29 --- /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 +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-changelog-parsing-affecting-caller-timezone-stat.patch b/backport-Fix-changelog-parsing-affecting-caller-timezone-stat.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b236e89d900be0ac08f745963fd9b45706b6dbe --- /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 +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-hash-context-leak.patch b/backport-Fix-hash-context-leak.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8fda68ff9e7760e26997f4f8947a3e4de68d970 --- /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 +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 0000000000000000000000000000000000000000..4717174c24b62e63e2fc831cd2f0e31abbc005f7 --- /dev/null +++ b/backport-Fix-hashlen-overflow.patch @@ -0,0 +1,46 @@ +From 3f142b210ae0c01e1b21c2c057b12db574386e7a Mon Sep 17 00:00:00 2001 +From: Justus Winter +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-memory-leak-in-pgpPrtParams-1.patch b/backport-Fix-memory-leak-in-pgpPrtParams-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..16e5cca886af91ba84864723107c719a9041fdea --- /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 +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 0000000000000000000000000000000000000000..72db05c6cd78ea7316246bf16fe82dc0a8c90890 --- /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 +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 0000000000000000000000000000000000000000..a9bcff6e1ca83ce9ecda6e1e39c144e36cd4fdcb --- /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 +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 0000000000000000000000000000000000000000..cb718a4a6a89c93df88343934f44e4faad15f3e7 --- /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 +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-return-value-checks-in-OpenSSL-code.patch b/backport-Fix-return-value-checks-in-OpenSSL-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ef25c78a463d888ffb277a818ae8aa5fdd0681f --- /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 +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-sanitize-the-hardlink-metadata-setting-logic.patch b/backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..58bd285e0c7832e2ef4ce68ac6b12d57270b73f0 --- /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 +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-short-circuiting-of-version-strings-in-expressio.patch b/backport-Fix-short-circuiting-of-version-strings-in-expressio.patch new file mode 100644 index 0000000000000000000000000000000000000000..9effafb7268823e37d8f44404060f138fcd45a62 --- /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 +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 0000000000000000000000000000000000000000..7166cceb1d2a01746c6f07a5daa958c7fca7d290 --- /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 +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 0000000000000000000000000000000000000000..869d0d36dd9517169d39f49b6f0241ab0d399843 --- /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 +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 0000000000000000000000000000000000000000..bb6b95cae1b1aa9fe9b9940535231416cc273c33 --- /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 +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 ) = 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-rpmfiSetFX-return-code-meaningful.patch b/backport-Make-rpmfiSetFX-return-code-meaningful.patch new file mode 100644 index 0000000000000000000000000000000000000000..e1e475b131218018991d5ed4305dcd176e4875ba --- /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 +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-Parse-key-usage-flags.patch b/backport-Parse-key-usage-flags.patch new file mode 100644 index 0000000000000000000000000000000000000000..3d20288064b8c7709c4e766a431f5150e0355cd9 --- /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 +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 0000000000000000000000000000000000000000..771f92ee212e000020d0e8e1237da1bf429fb808 --- /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 +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 0000000000000000000000000000000000000000..c472084b51c0fdebe5498171cad5c9f112faa63f --- /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 +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 0000000000000000000000000000000000000000..457b406fd08b4d037b5b4fca9dbfac14ea8f6b4f --- /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 +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 0000000000000000000000000000000000000000..05287be766d28bdf89a8ceb4f80232102b3a7e0a --- /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 +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-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 0000000000000000000000000000000000000000..5268282d4554ad3f0e930711d1566c6506be4f0b --- /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 +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 0000000000000000000000000000000000000000..bb9bb168794efa9f65e2dd1ad5504f19fc6c13e0 --- /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 +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 0000000000000000000000000000000000000000..cb30a4606be93bcea9f57e9256f221218ebe1cc1 --- /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 +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 0000000000000000000000000000000000000000..c0f0968f5f848aacdc5c8a2622cc5aa90b40e69e --- /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 +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 0000000000000000000000000000000000000000..1d09f82f5df92485e2b06bb25cbeb6cbbbd42528 --- /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 +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 0000000000000000000000000000000000000000..1b9a924c40b5df9614d25ee6e843bb8190e16630 --- /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 +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-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 0000000000000000000000000000000000000000..80b87905b5d224ae2abfa6b3fb72a6805132623a --- /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 +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-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 0000000000000000000000000000000000000000..33c74020f971f69355e0ca82b5a057e9eb7c75e4 --- /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 +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 1]) +-- +1.8.3.1 + 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 0000000000000000000000000000000000000000..fbe4a7848c0b4d1834bc5b6298f978acd329bac0 --- /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 +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 0000000000000000000000000000000000000000..490ec443e17f7d554aeb1077a647b547a74ecefc --- /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 +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 0000000000000000000000000000000000000000..5cdef02780b45365e23f73743eb28c99ca5228c1 --- /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 +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 0000000000000000000000000000000000000000..ac18f3553d4f2f72b80834b2d90fbfb5b6929279 --- /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 +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 1]) + AT_KEYWORDS([rpmkeys digest]) + AT_CHECK([ +-- +1.8.3.1 + 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 0000000000000000000000000000000000000000..154e55adaf241b69e386e916f1091971d36f29db --- /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 +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 index 1adcceaddb41d17a9054d76a5577d3f9872297d5..c5981260dea2932c04ba48c53a2e04178d6e2459 100644 --- a/bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch +++ b/bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch @@ -1,18 +1,7 @@ -From c580bc45b40d7782754e14e11b79085acdb9be8d Mon Sep 17 00:00:00 2001 -From: licihua -Date: Thu, 20 Oct 2022 20:37:44 +0800 -Subject: [PATCH 05/22] bugfix rpm 4.11.3 add aarch64_ilp32 arch - ---- - installplatform | 7 +++++++ - rpmrc.in | 9 +++++++-- - 2 files changed, 14 insertions(+), 2 deletions(-) - -diff --git a/installplatform b/installplatform -index 4391691..dd9effb 100755 ---- a/installplatform -+++ b/installplatform -@@ -180,6 +180,13 @@ for ARCH in noarch `grep ^arch_canon $RPMRC | cut -d: -f2`; do +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 ;; @@ -23,14 +12,13 @@ index 4391691..dd9effb 100755 + CANONCOLOR=0 + LIB=libilp32 + ;; - loongarch64) - ISANAME=loongarch64 - ISABITS=64 -diff --git a/rpmrc.in b/rpmrc.in -index 2975a3a..f541b0e 100644 ---- a/rpmrc.in -+++ b/rpmrc.in -@@ -101,7 +101,7 @@ optflags: sh4 -O2 -g -mieee + 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 @@ -38,8 +26,8 @@ index 2975a3a..f541b0e 100644 +optflags: aarch64_ilp32 -O2 -g -mabi=ilp32 optflags: riscv64 -O2 -g - optflags: loongarch64 -O2 -g -@@ -154,7 +154,7 @@ archcolor: sh3 1 + ############################################################# +@@ -149,7 +149,7 @@ archcolor: sh4 1 archcolor: aarch64 2 @@ -47,40 +35,46 @@ index 2975a3a..f541b0e 100644 +archcolor: aarch64_ilp32 1 archcolor: riscv64 2 - -@@ -253,6 +253,7 @@ arch_canon: sh4: sh4 17 + ############################################################# +@@ -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 -@@ -391,6 +392,7 @@ buildarchtranslate: sh4: sh4 + 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 -@@ -504,6 +506,8 @@ arch_compat: sh4: noarch + +-############################################################# ++#########################################/#################### + # 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: noarch +arch_compat: aarch64_ilp32: aarch64 noarch +arch_compat: aarch64: aarch64_ilp32 noarch arch_compat: riscv: noarch arch_compat: riscv64: noarch -@@ -542,6 +546,7 @@ arch_compat: loongarch64: 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 --- -2.26.2 - + 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 index 7e5ea746211e2f5de127640d0da71b30f91ece6f..23793318def898428696f62294b0910ff33707fb 100644 --- a/bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch +++ b/bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch @@ -12,10 +12,10 @@ Signed-off-by: shanshishi 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/rpmlock.c b/lib/rpmlock.c -index b889e79..a546407 100644 +index d693c4b..86e07b3 100644 --- a/lib/rpmlock.c +++ b/lib/rpmlock.c -@@ -127,13 +127,10 @@ rpmlock rpmlockNew(const char *lock_path, const char *descr) +@@ -125,13 +125,10 @@ rpmlock rpmlockNew(const char *lock_path, const char *descr) int rpmlockAcquire(rpmlock lock) { int locked = 0; /* assume failure */ @@ -31,5 +31,5 @@ index b889e79..a546407 100644 lock->descr, lock->path); locked = rpmlock_acquire(lock, (RPMLOCK_WRITE|RPMLOCK_WAIT)); -- -2.26.2 +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 0000000000000000000000000000000000000000..4809b5856a436374a03f83da6ceeac59c1961967 --- /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 +Date: Mon, 26 Oct 2020 12:10:31 +0800 +Subject: [PATCH] call process_digest_list after files are added + +Signed-off-by: Anakin Zhang +--- + 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 0000000000000000000000000000000000000000..b2e04248ba7fa0d4fc7267bc1ccffbf8d71987db --- /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 +Date: Tue, 15 Mar 2022 20:54:06 +0800 +Subject: [PATCH] dont remove ima xattr of parser when upgrading + +Signed-off-by: luhuaxin +--- + 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 0000000000000000000000000000000000000000..c7cd4dad86608ebed5659a40bf11674caae99f6f --- /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 +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 +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 358450dc8d66cb339a48983a091d434b30e1829d..c3d31ffa00d375a3f859706c3f914854e16c05ab 100644 --- a/get-in-use-of-ndb.patch +++ b/get-in-use-of-ndb.patch @@ -5,13 +5,14 @@ Subject: [PATCH] get in use of ndb --- configure.ac | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) + macros.in | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac -index fbbfead..f0e6dd6 100644 +index 6b161dc..ab1c667 100644 --- a/configure.ac +++ b/configure.ac -@@ -523,9 +523,9 @@ AM_CONDITIONAL([BDB_RO], [test "$enable_bdb_ro" = yes]) +@@ -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@:>@)], @@ -23,6 +24,19 @@ index fbbfead..f0e6dd6 100644 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. -- -2.26.2 +1.8.3.1 diff --git a/revert-always-execute-file-trigger-scriptlet-callbac.patch b/revert-always-execute-file-trigger-scriptlet-callbac.patch index f2a2aa0a6fa0633fa56d69e7768409c0554de26b..c8fd59c3b53d1144c9fab70be6efef0cfaeaf5f8 100644 --- a/revert-always-execute-file-trigger-scriptlet-callbac.patch +++ b/revert-always-execute-file-trigger-scriptlet-callbac.patch @@ -1,7 +1,7 @@ -From 974dcb304c57fc5c1f4088f19856c4941c15c90a Mon Sep 17 00:00:00 2001 -From: licihua -Date: Thu, 20 Oct 2022 20:33:29 +0800 -Subject: [PATCH 04/22] revert always execute file trigger scriptlet callbacks with +From 9680c3f2f8ceeddced6e91048daeb9b93abf4c8d Mon Sep 17 00:00:00 2001 +From: openEuler Buildteam +Date: Wed, 25 Mar 2020 16:57:29 +0800 +Subject: [PATCH] revert always execute file trigger scriptlet callbacks with owning header --- @@ -9,10 +9,10 @@ Subject: [PATCH 04/22] revert always execute file trigger scriptlet callbacks wi 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c -index 3f8fa22..f5c79ba 100644 +index 285b2f0..b7c76e7 100644 --- a/lib/rpmtriggers.c +++ b/lib/rpmtriggers.c -@@ -433,7 +433,7 @@ static int runHandleTriggersInPkg(rpmts ts, rpmte te, Header h, +@@ -437,7 +437,7 @@ static int runHandleTriggersInPkg(rpmts ts, rpmte te, Header h, inputFunc = (char *(*)(void *)) matchFilesNext; rpmScriptSetNextFileFunc(script, inputFunc, mfi); @@ -22,5 +22,5 @@ index 3f8fa22..f5c79ba 100644 rpmtdFreeData(&installPrefixes); rpmScriptFree(script); -- -2.26.2 +1.8.3.1 diff --git a/rpm-4.12.0-rpm2cpio-hack.patch b/rpm-4.12.0-rpm2cpio-hack.patch index b92f0535b49517ab9206d9a4c2731b0ccf8ed968..38c7dbd2fbe8b0a1dcf72f59098724751ef72234 100644 --- a/rpm-4.12.0-rpm2cpio-hack.patch +++ b/rpm-4.12.0-rpm2cpio-hack.patch @@ -1,17 +1,8 @@ -From 3b518bff7579647d2e9160e37dbbabc63c3d6792 Mon Sep 17 00:00:00 2001 -From: licihua -Date: Thu, 20 Oct 2022 20:28:48 +0800 -Subject: [PATCH 02/22] rpm-4.12.0-rpm2cpio-hack - ---- - rpm2cpio.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - diff --git a/rpm2cpio.c b/rpm2cpio.c -index fcc3b30..5e650d5 100644 +index 89ebdfa..ae999ff 100644 --- a/rpm2cpio.c +++ b/rpm2cpio.c -@@ -94,7 +94,12 @@ int main(int argc, char *argv[]) +@@ -84,7 +84,12 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } @@ -25,6 +16,3 @@ index fcc3b30..5e650d5 100644 Fclose(fdo); --- -2.26.2 - diff --git a/rpm-4.18.0.tar.bz2 b/rpm-4.17.0.tar.bz2 old mode 100755 new mode 100644 similarity index 35% rename from rpm-4.18.0.tar.bz2 rename to rpm-4.17.0.tar.bz2 index 37ea9292b836f201a6655a943e4ba7c7e47c2781..0aecf44db7f8691a253e8d2e05023c24d99bf304 Binary files a/rpm-4.18.0.tar.bz2 and b/rpm-4.17.0.tar.bz2 differ diff --git a/rpm-selinux-plugin-check-context-file-exist.patch b/rpm-selinux-plugin-check-context-file-exist.patch index fc4f137cb6ba97f3adcfb4fdf566a30a707e66d8..56d7982701330c135df1c8ef2c4ef1155670c906 100644 --- a/rpm-selinux-plugin-check-context-file-exist.patch +++ b/rpm-selinux-plugin-check-context-file-exist.patch @@ -8,10 +8,10 @@ Subject: [PATCH] rpm selinux plugin check context file exist 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/selinux.c b/plugins/selinux.c -index 316ff88..ac1e354 100644 +index 1254517..fb8b7a2 100644 --- a/plugins/selinux.c +++ b/plugins/selinux.c -@@ -64,7 +64,8 @@ static rpmRC selinux_tsm_pre(rpmPlugin plugin, rpmts ts) +@@ -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 */ @@ -22,5 +22,5 @@ index 316ff88..ac1e354 100644 } -- -2.26.2 +2.23.0 diff --git a/rpm.spec b/rpm.spec index 08c1258461980637bd81a8baffc3618083db0079..6540878e5a4ad3d00a4ba30bcf61b5fc653667b4 100644 --- a/rpm.spec +++ b/rpm.spec @@ -1,22 +1,84 @@ Name: rpm -Version: 4.18.0 -Release: 1 +Version: 4.17.0 +Release: 13 Summary: RPM Package Manager License: GPLv2+ URL: http://www.rpm.org/ -Source0: http://ftp.rpm.org/releases/rpm-4.18.x/%{name}-%{version}.tar.bz2 - -Patch0001: Unbundle-config-site-and-add-RPM-LD-FLAGS-macro.patch -Patch0002: rpm-4.12.0-rpm2cpio-hack.patch -Patch0003: add-dist-to-release-by-default.patch -Patch0004: revert-always-execute-file-trigger-scriptlet-callbac.patch -Patch0005: bugfix-rpm-4.11.3-add-aarch64_ilp32-arch.patch -Patch0006: bugfix-rpm-4.14.2-wait-once-get-rpmlock-fail.patch -Patch0007: rpm-selinux-plugin-check-context-file-exist.patch -Patch0008: get-in-use-of-ndb.patch -Patch0009: still-in-use-of-python-scripts-from-old-version.patch -Patch0010: Add-loongarch-architecture-support.patch -Patch0011: Generate-digest-lists.patch +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 + +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 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 @@ -38,7 +100,7 @@ The RPM Package Manager (RPM) is a powerful package management system capability -verifying integrity of packaged software and resulting software installation %package libs -Summary: Shared library of rpm %{version} +Summary: Shared library of rpm 4.17 Requires: %{name} = %{version}-%{release} %description libs @@ -247,7 +309,6 @@ make check || (cat tests/rpmtests.log; exit 0) %{_bindir}/rpmbuild %{_bindir}/gendiff %{_bindir}/rpmspec -%{_bindir}/rpmlua %{_rpmconfigdir}/brp-* %{_rpmconfigdir}/check-* @@ -260,7 +321,6 @@ make check || (cat tests/rpmtests.log; exit 0) %{_rpmconfigdir}/mkinstalldirs %{_rpmconfigdir}/fileattrs/* %{_rpmconfigdir}/config.* -%{_rpmconfigdir}/rpmuncompress %files -n python3-%{name} %defattr(-,root,root) @@ -288,6 +348,9 @@ make check || (cat tests/rpmtests.log; exit 0) %{_mandir}/man1/gendiff.1* %changelog +* Thu Oct 27 2022 renhongxun - 4.17.0-13 +- downgrade to 4.17 + * Tue Oct 25 2022 licihua - 4.18.0-1 - upgrade to 4.18 diff --git a/still-in-use-of-python-scripts-from-old-version.patch b/still-in-use-of-python-scripts-from-old-version.patch index 2825965055ffdf52c6e881c683f1c42792c09248..50fdb6f5e208ea8f451e3cb837ef40d918a1a491 100644 --- a/still-in-use-of-python-scripts-from-old-version.patch +++ b/still-in-use-of-python-scripts-from-old-version.patch @@ -4,10 +4,10 @@ Date: Wed, 29 Dec 2021 16:37:45 +0800 Subject: [PATCH] still in use of python scripts from old version --- - platform.in | 3 + + platform.in | 3 ++ scripts/Makefile.am | 8 +-- - scripts/brp-python-bytecompile | 112 +++++++++++++++++++++++++++++++++ - scripts/brp-python-hardlink | 25 ++++++++ + 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 @@ -31,7 +31,7 @@ index 71496b8..748186e 100644 %__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 5cbed80..a1608f9 100644 +index 4aed76b..5a1c494 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -6,8 +6,8 @@ AM_CFLAGS = @RPMCFLAGS@ @@ -45,7 +45,7 @@ index 5cbed80..a1608f9 100644 brp-strip-static-archive brp-elfperms \ brp-remove-la-files \ check-files check-prereqs \ -@@ -24,8 +24,8 @@ EXTRA_DIST = \ +@@ -23,8 +23,8 @@ EXTRA_DIST = \ fontconfig.prov script.req rpmconfig_SCRIPTS = \ @@ -58,7 +58,7 @@ index 5cbed80..a1608f9 100644 check-files check-prereqs \ diff --git a/scripts/brp-python-bytecompile b/scripts/brp-python-bytecompile new file mode 100644 -index 0000000..114a493 +index 0000000..d9c4832 --- /dev/null +++ b/scripts/brp-python-bytecompile @@ -0,0 +1,112 @@ @@ -206,5 +206,5 @@ index 0000000..5fd1b43 +done +exit 0 -- -2.26.2 +1.8.3.1