Compare commits

..

No commits in common. 'c9' and 'i10c-beta' have entirely different histories.

2
.gitignore vendored

@ -1 +1 @@
SOURCES/rpm-4.16.1.3.tar.bz2 SOURCES/rpm-4.19.1.1.tar.bz2

@ -1 +1 @@
4c70c0dc08aec5ba29f3ee72eda774bd32230f77 SOURCES/rpm-4.16.1.3.tar.bz2 5ff9a545a18cd7183854b7ec6de675969fd9b1ec SOURCES/rpm-4.19.1.1.tar.bz2

@ -1,107 +0,0 @@
From 186e0ab025b9ad92d900697f611633a6f6162f3b Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 9 Feb 2022 14:47:14 +0200
Subject: [PATCH] Add optional callback on directory changes during rpmfi
iteration
Internal only for now in case we need to fiddle with the API some more,
but no reason this couldn't be made public later.
---
lib/rpmfi.c | 24 ++++++++++++++++++++----
lib/rpmfi_internal.h | 17 +++++++++++++++++
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index aec8220a3..6c631fdb5 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -53,6 +53,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 */
@@ -298,11 +301,16 @@ rpm_count_t rpmfiDC(rpmfi fi)
return (fi != NULL ? rpmfilesDC(fi->files) : 0);
}
-#ifdef NOTYET
-int rpmfiDI(rpmfi fi)
+int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data)
{
+ int rc = -1;
+ if (fi != NULL) {
+ fi->onChdir = cb;
+ fi->onChdirData = data;
+ rc = 0;
+ }
+ return rc;
}
-#endif
int rpmfiFX(rpmfi fi)
{
@@ -314,9 +322,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;
}
@@ -1682,9 +1698,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 dccc6ccbe..37f1d45f5 100644
--- a/lib/rpmfi_internal.h
+++ b/lib/rpmfi_internal.h
@@ -13,6 +13,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
--
2.41.0

@ -1,30 +0,0 @@
From 6c66abd34cccbb5b3c063f8f613e0c2faffc415f Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 13 Dec 2023 11:57:50 +0200
Subject: [PATCH] Don't warn about missing user/group on skipped files
There's no reason to complain about missing user/group for entities
we don't create at all. It's cosmetical only, but "regressed" in the
4.17 fsm robustness rewrite.
Reported in https://issues.redhat.com/browse/RHEL-18037
---
lib/fsm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/fsm.c b/lib/fsm.c
index 2189bd84c..a54e43bae 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -903,7 +903,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
fp->fpath = fsmFsPath(fi, fp->suffix);
/* Remap file perms, owner, and group. */
- rc = rpmfiStat(fi, 1, &fp->sb);
+ rc = rpmfiStat(fi, (fp->skip == 0), &fp->sb);
/* Hardlinks are tricky and handled elsewhere for install */
fp->setmeta = (fp->skip == 0) &&
--
2.43.0

@ -1,35 +0,0 @@
From 0bc13d75b5883ccf4d6579f7a60fb1badd104649 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 10 Feb 2022 10:23:22 +0200
Subject: [PATCH] Eliminate code duplication from rpmfiNext()
Now that we can, let rpmfiSetFX() take care of the details.
---
lib/rpmfi.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index 689ead2c5..aec8220a3 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -856,15 +856,8 @@ int rpmfiNext(rpmfi fi)
next = fi->next(fi);
} while (next == RPMERR_ITER_SKIP);
- if (next >= 0 && next < rpmfilesFC(fi->files)) {
- fi->i = next;
- fi->j = rpmfilesDI(fi->files, fi->i);
- } else {
- fi->i = -1;
- if (next >= 0) {
- next = -1;
- }
- }
+ if (next >= 0)
+ next = rpmfiSetFX(fi, next);
}
return next;
}
--
2.41.0

@ -1,66 +0,0 @@
From c140768202e271b60910644c1e4bf848a50218d3 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 27 Nov 2023 11:52:34 +0200
Subject: [PATCH] Emit full paths for file disposition diagnostics on
--fsmdebug
The full path is visible in the actual file operations later, but the
pre-flight disposition diagnostics is unreadable without the full path.
This regressed in the switch to relative paths for the *at() API family
for the symlink CVE fixes.
---
lib/fsm.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/fsm.c b/lib/fsm.c
index 091e90554..fcd764648 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -482,14 +482,14 @@ static void removeSBITS(int dirfd, const char *path)
}
}
-static void fsmDebug(const char *fpath, rpmFileAction action,
+static void fsmDebug(const char *dn, const char *fpath, rpmFileAction action,
const struct stat *st)
{
- rpmlog(RPMLOG_DEBUG, "%-10s %06o%3d (%4d,%4d)%6d %s\n",
+ rpmlog(RPMLOG_DEBUG, "%-10s %06o%3d (%4d,%4d)%6d %s%s\n",
fileActionString(action), (int)st->st_mode,
(int)st->st_nlink, (int)st->st_uid,
(int)st->st_gid, (int)st->st_size,
- (fpath ? fpath : ""));
+ (dn ? dn : ""), (fpath ? fpath : ""));
}
static int fsmSymlink(const char *opath, int dirfd, const char *path)
@@ -910,7 +910,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
(fp->sb.st_nlink == 1 || fp->action == FA_TOUCH);
setFileState(fs, fx);
- fsmDebug(fp->fpath, fp->action, &fp->sb);
+ fsmDebug(rpmfiDN(fi), fp->fpath, fp->action, &fp->sb);
fp->stage = FILE_PRE;
}
@@ -975,7 +975,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n",
fp->fpath);
fp->action = FA_CREATE;
- fsmDebug(fp->fpath, fp->action, &fp->sb);
+ fsmDebug(rpmfiDN(fi), fp->fpath, fp->action, &fp->sb);
}
/* When touching we don't need any of this... */
@@ -1138,7 +1138,7 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
rc = fsmStat(di.dirfd, fp->fpath, 1, &fp->sb);
- fsmDebug(fp->fpath, fp->action, &fp->sb);
+ fsmDebug(rpmfiDN(fi), fp->fpath, fp->action, &fp->sb);
/* Run fsm file pre hook for all plugins */
rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
--
2.43.0

@ -0,0 +1,27 @@
From 65fa582b5cb267bb73c3e2b4c502f456d50c41f0 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 12 Aug 2024 17:15:48 +0200
Subject: [PATCH] Fix memory leak in rpmsign
Found by Coverity.
Fixes: RHEL-37564
---
tools/rpmsign.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/rpmsign.c b/tools/rpmsign.c
index a47b2c109..c5e3e11b4 100644
--- a/tools/rpmsign.c
+++ b/tools/rpmsign.c
@@ -152,6 +152,7 @@ static int doSign(poptContext optCon, struct rpmSignArgs *sargs)
char *key = rpmExpand("%{?_file_signing_key}", NULL);
if (rstreq(key, "")) {
fprintf(stderr, _("You must set \"%%_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
+ free(key);
goto exit;
}
--
2.46.0

@ -0,0 +1,32 @@
From 1b90b8c7d176026b669ce28c6e185724a4b208b0 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 7 Jun 2024 10:14:25 +0200
Subject: [PATCH] Fix potential use of uninitialized pgp struct
We only call initPgpData() after base64 encoding the pubkey so if the
latter fails, the kd struct will be left uninitialized and subsequently
read from after skipping to the exit label. Fix by initializing it.
Found by Coverity.
Fixes: RHEL-22605
---
lib/rpmts.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/rpmts.c b/lib/rpmts.c
index 3070b97e6..76964c60a 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -508,6 +508,8 @@ static int makePubkeyHeader(rpmts ts, rpmPubkey key, rpmPubkey *subkeys,
int rc = -1;
int i;
+ memset(&kd, 0, sizeof(kd));
+
if ((enc = rpmPubkeyBase64(key)) == NULL)
goto exit;
--
2.46.0

@ -0,0 +1,32 @@
From bff65aad8af719542c7b0c6429e09223c014a909 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Thu, 6 Jun 2024 09:15:02 +0200
Subject: [PATCH] Fix potential use of uninitialized pipe array
We only call pipe(2) after the script is written to disk so if the
latter fails, the array will be left uninitialized and subsequently read
after skipping to the exit label. Fix by initializing it.
Found by Coverity.
Fixes: RHEL-22604
---
lib/rpmscript.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/rpmscript.c b/lib/rpmscript.c
index 281c55c53..1de4acf8e 100644
--- a/lib/rpmscript.c
+++ b/lib/rpmscript.c
@@ -316,7 +316,7 @@ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
char * fn = NULL;
pid_t pid, reaped;
int status;
- int inpipe[2];
+ int inpipe[2] = { -1, -1 };
FILE *in = NULL;
const char *line;
char *mline = NULL;
--
2.46.0

@ -1,46 +0,0 @@
From 89ce4e7ca592f5abafc3f25aeaa07d36a7b43a61 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 14 Nov 2023 11:37:48 +0200
Subject: [PATCH] Fix wrong return code on O_DIRECTORY open of invalid symlink
The dir argument to fsmOpenpath() is supposed to be a rough O_DIRECTORY
equivalent, and if the path is actually a misowned symlink it should
return ENOTDIR instead of ELOOP. Makes the resulting error messages
at least a little more comprehensible.
---
lib/fsm.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lib/fsm.c b/lib/fsm.c
index 51f439ef3..091e90554 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -304,6 +304,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
struct stat lsb, sb;
int sflags = flags | O_NOFOLLOW;
int fd = openat(dirfd, path, sflags);
+ int ffd = fd;
/*
* Only ever follow symlinks by root or target owner. Since we can't
@@ -312,7 +313,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
* it could've only been the link owner or root.
*/
if (fd < 0 && errno == ELOOP && flags != sflags) {
- int ffd = openat(dirfd, path, flags);
+ ffd = openat(dirfd, path, flags);
if (ffd >= 0) {
if (fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) {
if (fstat(ffd, &sb) == 0) {
@@ -327,7 +328,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
}
/* O_DIRECTORY equivalent */
- if (dir && fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
+ if (dir && ((fd != ffd) || (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)))) {
errno = ENOTDIR;
fsmClose(&fd);
}
--
2.43.0

@ -1,40 +0,0 @@
From 48546ffc0a3f3eb15bfd439a19fc9722eaea592f Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Tue, 28 Jun 2022 12:50:54 +0200
Subject: [PATCH] Give warning on not supported hash for RSA keys
This can happen when old keys are used on systems that have disabled SHA1
e.g. for FIPS requirements.
This is less than ideal but there is currently no way to pass a meaningful
error code up to rpmtsImportPubkey. rpmPubkeyNew just returns a valid key
or NULL.
See rhbz#2069877
---
rpmio/digest_openssl.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c
index a28a13acc..2ec5140f1 100644
--- a/rpmio/digest_openssl.c
+++ b/rpmio/digest_openssl.c
@@ -4,6 +4,7 @@
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <rpm/rpmpgp.h>
+#include <rpm/rpmlog.h>
#include "rpmio/digest.h"
@@ -483,6 +484,7 @@ static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
ret = EVP_PKEY_CTX_set_signature_md(pkey_ctx, getEVPMD(hash_algo));
if (ret < 0) {
+ rpmlog(RPMLOG_WARNING, "Signature not supported. Hash algorithm %s not available.\n", pgpValString(PGPVAL_HASHALGO, hash_algo));
rc = 1;
goto done;
}
--
2.36.1

@ -1,28 +0,0 @@
From 5a80033676f331de2b0979fe7be9557279b6bff3 Mon Sep 17 00:00:00 2001
Message-Id: <5a80033676f331de2b0979fe7be9557279b6bff3.1603865959.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 28 Oct 2020 08:14:55 +0200
Subject: [PATCH] Issue deprecation warning when creating BDB databases
---
lib/backend/db3.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/backend/db3.c b/lib/backend/db3.c
index 68cfa6fb2..cb31676e7 100644
--- a/lib/backend/db3.c
+++ b/lib/backend/db3.c
@@ -874,6 +874,10 @@ static int db3_dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flag
oflags &= ~DB_RDONLY;
dbtype = (rpmtag == RPMDBI_PACKAGES) ? DB_HASH : DB_BTREE;
retry_open--;
+ if (rpmtag == RPMDBI_PACKAGES) {
+ rpmlog(RPMLOG_WARNING,
+ "using deprecated bdb database backend");
+ }
} else {
retry_open = 0;
}
--
2.28.0

@ -1,51 +0,0 @@
From 1a2554da434548e916240796fe7ca9689c5771fe Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 27 May 2021 13:58:58 +0300
Subject: [PATCH] Macroize find-debuginfo script location
Makes it easier to handle varying paths, mainly in preparation for the
next step.
(cherry picked from commit ce48167f37af59b6366083fb78a314f7931c0c6b)
---
configure.ac | 1 +
macros.in | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 39f9a0e5b..35b4dff4c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,6 +113,7 @@ AC_PATH_PROG(__NM, nm, /usr/bin/nm, $MYPATH)
AC_PATH_PROG(__OBJCOPY, objcopy, /usr/bin/objcopy, $MYPATH)
AC_PATH_PROG(__OBJDUMP, objdump, /usr/bin/objdump, $MYPATH)
AC_PATH_PROG(__STRIP, strip, /usr/bin/strip, $MYPATH)
+AC_PATH_PROG(__FIND_DEBUGINFO, find-debuginfo, /usr/bin/find-debuginfo, $MYPATH)
AC_PATH_PROG(__GIT, git, /usr/bin/git, $MYPATH)
AC_PATH_PROG(__HG, hg, /usr/bin/hg, $MYPATH)
diff --git a/macros.in b/macros.in
index 24b124702..2bcf07ef8 100644
--- a/macros.in
+++ b/macros.in
@@ -80,6 +80,8 @@
%__remsh %{__rsh}
%__strip @__STRIP@
+%__find_debuginfo @__FIND_DEBUGINFO@
+
#==============================================================================
# Conditional build stuff.
@@ -149,7 +151,7 @@
# _find_debuginfo_vendor_opts to pass options to the script.
#
%__debug_install_post \
- %{_rpmconfigdir}/find-debuginfo.sh \\\
+ %{__find_debuginfo} \\\
%{?_smp_build_ncpus:-j%{_smp_build_ncpus}} \\\
%{?_missing_build_ids_terminate_build:--strict-build-id} \\\
%{?_no_recompute_build_ids:-n} \\\
--
2.41.0

@ -1,61 +0,0 @@
From a93b0f5c9f0abef6efb5413df9e98b047a2a9a46 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Mon, 17 Aug 2020 16:56:56 +0200
Subject: [PATCH 1/6] [NFC] debugedit: Protect macro arguments by parentheses
---
tools/debugedit.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 6bea88551..a351adec8 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -233,7 +233,7 @@ typedef struct
int shift = 0; \
do \
{ \
- c = *ptr++; \
+ c = *(ptr)++; \
ret |= (c & 0x7f) << shift; \
shift += 7; \
} while (c & 0x80); \
@@ -251,7 +251,7 @@ typedef struct
valv >>= 7; \
if (valv) \
c |= 0x80; \
- *ptr++ = c; \
+ *(ptr)++ = c; \
} \
while (valv); \
})
@@ -311,7 +311,7 @@ strptr (DSO *dso, int sec, off_t offset)
}
-#define read_8(ptr) *ptr++
+#define read_8(ptr) *(ptr)++
#define read_16(ptr) ({ \
uint16_t ret = do_read_16 (ptr); \
@@ -328,13 +328,13 @@ strptr (DSO *dso, int sec, off_t offset)
REL *relptr, *relend;
int reltype;
-#define do_read_32_relocated(ptr) ({ \
- uint32_t dret = do_read_32 (ptr); \
+#define do_read_32_relocated(xptr) ({ \
+ uint32_t dret = do_read_32 (xptr); \
if (relptr) \
{ \
- while (relptr < relend && relptr->ptr < ptr) \
+ while (relptr < relend && relptr->ptr < (xptr)) \
++relptr; \
- if (relptr < relend && relptr->ptr == ptr) \
+ if (relptr < relend && relptr->ptr == (xptr)) \
{ \
if (reltype == SHT_REL) \
dret += relptr->addend; \
--
2.18.4

@ -1,158 +0,0 @@
From ac7b0dbd5a18d2c57a942ca14ac856b8047425ff Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 15 Feb 2022 10:43:13 +0200
Subject: [PATCH] Pass file descriptor to file prepare plugin hook, use when
possible
Sadly the thing that allegedly makes things better mostly just makes
things more complicated as symlinks can't be opened, so we'll now have
to deal with both cases in plugins too. To make matters worse, most
APIs out there support either an fd or a path, but very few support
the *at() style dirfd + basename approach so plugins are stuck with
absolute paths for now.
This is of course a plugin API/ABI change too.
---
lib/rpmplugin.h | 2 +-
lib/rpmplugins.c | 4 ++--
lib/rpmplugins.h | 3 ++-
plugins/ima.c | 9 +++++++--
plugins/selinux.c | 13 ++++++++-----
5 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/lib/rpmplugin.h b/lib/rpmplugin.h
index fd81aec8d..fab4b3e83 100644
--- a/lib/rpmplugin.h
+++ b/lib/rpmplugin.h
@@ -57,7 +57,7 @@ typedef rpmRC (*plugin_fsm_file_post_func)(rpmPlugin plugin, rpmfi fi,
const char* path, mode_t file_mode,
rpmFsmOp op, int res);
typedef rpmRC (*plugin_fsm_file_prepare_func)(rpmPlugin plugin, rpmfi fi,
- const char* path,
+ int fd, const char* path,
const char *dest,
mode_t file_mode, rpmFsmOp op);
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
index 65e684e84..923084b78 100644
--- a/lib/rpmplugins.c
+++ b/lib/rpmplugins.c
@@ -384,7 +384,7 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char *path,
}
rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
- const char *path, const char *dest,
+ int fd, const char *path, const char *dest,
mode_t file_mode, rpmFsmOp op)
{
plugin_fsm_file_prepare_func hookFunc;
@@ -394,7 +394,7 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
for (i = 0; i < plugins->count; i++) {
rpmPlugin plugin = plugins->plugins[i];
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_prepare);
- if (hookFunc && hookFunc(plugin, fi, path, dest, file_mode, op) == RPMRC_FAIL) {
+ if (hookFunc && hookFunc(plugin, fi, fd, path, dest, file_mode, op) == RPMRC_FAIL) {
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_prepare failed\n", plugin->name);
rc = RPMRC_FAIL;
}
diff --git a/lib/rpmplugins.h b/lib/rpmplugins.h
index 39762c376..ddf5d7048 100644
--- a/lib/rpmplugins.h
+++ b/lib/rpmplugins.h
@@ -156,6 +156,7 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char* path,
* permissions etc, but before committing file to destination path.
* @param plugins plugins structure
* @param fi file info iterator (or NULL)
+ * @param fd file descriptor (or -1 if not available)
* @param path file object current path
* @param dest file object destination path
* @param mode file object mode
@@ -164,7 +165,7 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char* path,
*/
RPM_GNUC_INTERNAL
rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
- const char *path, const char *dest,
+ int fd, const char *path, const char *dest,
mode_t mode, rpmFsmOp op);
#ifdef __cplusplus
diff --git a/plugins/ima.c b/plugins/ima.c
index fe6d3ad7f..9c28a41a3 100644
--- a/plugins/ima.c
+++ b/plugins/ima.c
@@ -39,7 +39,7 @@ static int check_zero_hdr(const unsigned char *fsig, size_t siglen)
return (memcmp(fsig, &zero_hdr, sizeof(zero_hdr)) == 0);
}
-static rpmRC ima_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
+static rpmRC ima_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, int fd,
const char *path,
const char *dest,
mode_t file_mode, rpmFsmOp op)
@@ -68,8 +68,13 @@
fsig = rpmfiFSignature(fi, &len);
if (fsig && (check_zero_hdr(fsig, len) == 0)) {
- if (lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0) < 0) {
- int is_err = errno != EOPNOTSUPP;
+ int xx;
+ if (fd >= 0)
+ xx = fsetxattr(fd, XATTR_NAME_IMA, fsig, len, 0);
+ else
+ xx = lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0);
+ if (xx < 0) {
+ int is_err = errno != EOPNOTSUPP;
rpmlog(is_err?RPMLOG_ERR:RPMLOG_DEBUG,
"ima: could not apply signature on '%s': %s\n",
path, strerror(errno));
diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
index 7ac44f0d0..1ff50c30f 100644
--- a/plugins/fapolicyd.c
+++ b/plugins/fapolicyd.c
@@ -145,7 +145,8 @@ static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
}
static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
- const char *path, const char *dest,
+ int fd, const char *path,
+ const char *dest,
mode_t file_mode, rpmFsmOp op)
{
/* not ready */
diff --git a/plugins/selinux.c b/plugins/selinux.c
index 32c3b7529..a7f20aeca 100644
--- a/plugins/selinux.c
+++ b/plugins/selinux.c
@@ -149,7 +149,7 @@ static rpmRC selinux_scriptlet_fork_post(rpmPlugin plugin,
return rc;
}
-static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
+static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, int fd,
const char *path, const char *dest,
mode_t file_mode, rpmFsmOp op)
{
@@ -194,13 +194,17 @@
if (sehandle && !XFA_SKIPPING(action)) {
char *scon = NULL;
if (selabel_lookup_raw(sehandle, &scon, dest, file_mode) == 0) {
- int conrc = lsetfilecon(path, scon);
+ int conrc;
+ if (fd >= 0)
+ conrc = fsetfilecon(fd, scon);
+ else
+ conrc = lsetfilecon(path, scon);
if (conrc == 0 || (conrc < 0 && errno == EOPNOTSUPP))
rc = RPMRC_OK;
- rpmlog(loglvl(rc != RPMRC_OK), "lsetfilecon: (%s, %s) %s\n",
- path, scon, (conrc < 0 ? strerror(errno) : ""));
+ rpmlog(loglvl(rc != RPMRC_OK), "lsetfilecon: (%d %s, %s) %s\n",
+ fd, path, scon, (conrc < 0 ? strerror(errno) : ""));
freecon(scon);
} else {
--
2.41.0

@ -1,32 +0,0 @@
From f1503ab6e898430b80017c0f8347860f3a74d5bb Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Mon, 11 Dec 2023 15:50:15 +0100
Subject: [PATCH] Print full path if file removal fails
For normal debug output the basename of the files are sufficient as when
debugging is enabled the directories are also printed. But here the
warning is given without a debug flag so we need the full context right
there.
---
lib/fsm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/fsm.c b/lib/fsm.c
index fcd764648..2189bd84c 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -1174,9 +1174,9 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
if (rc) {
int lvl = strict_erasures ? RPMLOG_ERR : RPMLOG_WARNING;
- rpmlog(lvl, _("%s %s: remove failed: %s\n"),
+ rpmlog(lvl, _("%s %s%s: remove failed: %s\n"),
S_ISDIR(fp->sb.st_mode) ? _("directory") : _("file"),
- fp->fpath, strerror(errno));
+ rpmfiDN(fi), fp->fpath, strerror(errno));
}
}
--
2.43.0

@ -1,90 +0,0 @@
From 6dd62720fe84f7e2ad902c915b952fc0b29e3dcd Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 15 Feb 2022 11:34:37 +0200
Subject: [PATCH] Swap over to dirfd+basename based operation within the fsm
Within fsm this is just a matter of adjusting error messages to include
the directory... if it only wasn't for the plugins requiring absolute
paths for outside users. For the plugins, we need to assemble absolute
paths as needed, both in ensureDir() and plugin file slots.
---
lib/rpmplugins.c | 20 +++++++++++++++++---
2 files changed, 36 insertions(+), 14 deletions(-)
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
index 703368c0d..f06fd7895 100644
--- a/lib/rpmplugins.c
+++ b/lib/rpmplugins.c
@@ -350,21 +350,31 @@ rpmRC rpmpluginsCallScriptletPost(rpmPlugins plugins, const char *s_name, int ty
return rc;
}
+static char *abspath(rpmfi fi, const char *path)
+{
+ if (*path == '/')
+ return xstrdup(path);
+ else
+ return rstrscat(NULL, rpmfiDN(fi), path, NULL);
+}
+
rpmRC rpmpluginsCallFsmFilePre(rpmPlugins plugins, rpmfi fi, const char *path,
mode_t file_mode, rpmFsmOp op)
{
plugin_fsm_file_pre_func hookFunc;
int i;
rpmRC rc = RPMRC_OK;
+ char *apath = abspath(fi, path);
for (i = 0; i < plugins->count; i++) {
rpmPlugin plugin = plugins->plugins[i];
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_pre);
- if (hookFunc && hookFunc(plugin, fi, path, file_mode, op) == RPMRC_FAIL) {
+ if (hookFunc && hookFunc(plugin, fi, apath, file_mode, op) == RPMRC_FAIL) {
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_pre failed\n", plugin->name);
rc = RPMRC_FAIL;
}
}
+ free(apath);
return rc;
}
@@ -375,14 +385,16 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char *path,
plugin_fsm_file_post_func hookFunc;
int i;
rpmRC rc = RPMRC_OK;
+ char *apath = abspath(fi, path);
for (i = 0; i < plugins->count; i++) {
rpmPlugin plugin = plugins->plugins[i];
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_post);
- if (hookFunc && hookFunc(plugin, fi, path, file_mode, op, res) == RPMRC_FAIL) {
+ if (hookFunc && hookFunc(plugin, fi, apath, file_mode, op, res) == RPMRC_FAIL) {
rpmlog(RPMLOG_WARNING, "Plugin %s: hook fsm_file_post failed\n", plugin->name);
}
}
+ free(apath);
return rc;
}
@@ -394,15 +406,17 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
plugin_fsm_file_prepare_func hookFunc;
int i;
rpmRC rc = RPMRC_OK;
+ char *apath = abspath(fi, path);
for (i = 0; i < plugins->count; i++) {
rpmPlugin plugin = plugins->plugins[i];
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_prepare);
- if (hookFunc && hookFunc(plugin, fi, fd, path, dest, file_mode, op) == RPMRC_FAIL) {
+ if (hookFunc && hookFunc(plugin, fi, fd, apath, dest, file_mode, op) == RPMRC_FAIL) {
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_prepare failed\n", plugin->name);
rc = RPMRC_FAIL;
}
}
+ free(apath);
return rc;
}
--
2.41.0

File diff suppressed because it is too large Load Diff

@ -1,30 +0,0 @@
From f2bc669cd0a080792522dd1bb7f50ef7025f16f0 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Sat, 21 Jul 2018 10:13:04 +0200
Subject: [PATCH] find-debuginfo.sh: decompress DWARF compressed ELF sections
debugedit and dwz do not support DWARF compressed ELF sections, let's
just decompress those before extracting debuginfo.
Tested-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
---
scripts/find-debuginfo.sh | 3 +++
1 file changed, 3 insertions(+)
diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
index 90a44942d..7b01bc036 100755
--- a/scripts/find-debuginfo.sh
+++ b/scripts/find-debuginfo.sh
@@ -357,6 +357,9 @@ do_file()
get_debugfn "$f"
[ -f "${debugfn}" ] && return
+ echo "explicitly decompress any DWARF compressed ELF sections in $f"
+ eu-elfcompress -q -p -t none "$f"
+
echo "extracting debug info from $f"
# See also cpio SOURCEFILE copy. Directories must match up.
debug_base_name="$RPM_BUILD_DIR"
--
2.18.0

@ -1,753 +0,0 @@
From de119ea9797f3ccfa3842e3926b6ea8198607207 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Sat, 1 Aug 2020 10:43:12 +0200
Subject: [PATCH 2/6] [NFC] debugedit: Move code from edit_dwarf2() to
edit_info().
---
tools/debugedit.c | 672 +++++++++++++++++++++++-----------------------
1 file changed, 343 insertions(+), 329 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index a351adec8..cad0cc349 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1964,6 +1964,106 @@ line_rel_cmp (const void *a, const void *b)
return 0;
}
+static int
+edit_info (DSO *dso, int phase)
+{
+ unsigned char *ptr, *endcu, *endsec;
+ uint32_t value;
+ htab_t abbrev;
+ struct abbrev_tag tag, *t;
+
+ ptr = debug_sections[DEBUG_INFO].data;
+ setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
+ endsec = ptr + debug_sections[DEBUG_INFO].size;
+ while (ptr < endsec)
+ {
+ if (ptr + 11 > endsec)
+ {
+ error (0, 0, "%s: .debug_info CU header too small",
+ dso->filename);
+ return 1;
+ }
+
+ endcu = ptr + 4;
+ endcu += read_32 (ptr);
+ if (endcu == ptr + 0xffffffff)
+ {
+ error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
+ return 1;
+ }
+
+ if (endcu > endsec)
+ {
+ error (0, 0, "%s: .debug_info too small", dso->filename);
+ return 1;
+ }
+
+ cu_version = read_16 (ptr);
+ if (cu_version != 2 && cu_version != 3 && cu_version != 4)
+ {
+ error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
+ cu_version);
+ return 1;
+ }
+
+ value = read_32_relocated (ptr);
+ if (value >= debug_sections[DEBUG_ABBREV].size)
+ {
+ if (debug_sections[DEBUG_ABBREV].data == NULL)
+ error (0, 0, "%s: .debug_abbrev not present", dso->filename);
+ else
+ error (0, 0, "%s: DWARF CU abbrev offset too large",
+ dso->filename);
+ return 1;
+ }
+
+ if (ptr_size == 0)
+ {
+ ptr_size = read_8 (ptr);
+ if (ptr_size != 4 && ptr_size != 8)
+ {
+ error (0, 0, "%s: Invalid DWARF pointer size %d",
+ dso->filename, ptr_size);
+ return 1;
+ }
+ }
+ else if (read_8 (ptr) != ptr_size)
+ {
+ error (0, 0, "%s: DWARF pointer size differs between CUs",
+ dso->filename);
+ return 1;
+ }
+
+ abbrev = read_abbrev (dso,
+ debug_sections[DEBUG_ABBREV].data + value);
+ if (abbrev == NULL)
+ return 1;
+
+ while (ptr < endcu)
+ {
+ tag.entry = read_uleb128 (ptr);
+ if (tag.entry == 0)
+ continue;
+ t = htab_find_with_hash (abbrev, &tag, tag.entry);
+ if (t == NULL)
+ {
+ error (0, 0, "%s: Could not find DWARF abbreviation %d",
+ dso->filename, tag.entry);
+ htab_delete (abbrev);
+ return 1;
+ }
+
+ ptr = edit_attributes (dso, ptr, t, phase);
+ if (ptr == NULL)
+ break;
+ }
+
+ htab_delete (abbrev);
+ }
+
+ return 0;
+}
+
static int
edit_dwarf2 (DSO *dso)
{
@@ -2100,385 +2200,299 @@ edit_dwarf2 (DSO *dso)
return 1;
}
- if (debug_sections[DEBUG_INFO].data != NULL)
+ if (debug_sections[DEBUG_INFO].data == NULL)
+ return 0;
+
+ unsigned char *ptr, *endcu, *endsec;
+ uint32_t value;
+ htab_t abbrev;
+ struct abbrev_tag tag, *t;
+ int phase;
+ bool info_rel_updated = false;
+ bool macro_rel_updated = false;
+
+ for (phase = 0; phase < 2; phase++)
{
- unsigned char *ptr, *endcu, *endsec;
- uint32_t value;
- htab_t abbrev;
- struct abbrev_tag tag, *t;
- int phase;
- bool info_rel_updated = false;
- bool macro_rel_updated = false;
+ /* If we don't need to update anyhing, skip phase 1. */
+ if (phase == 1
+ && !need_strp_update
+ && !need_string_replacement
+ && !need_stmt_update)
+ break;
- for (phase = 0; phase < 2; phase++)
+ rel_updated = false;
+ if (edit_info (dso, phase))
+ return 1;
+
+ /* Remember whether any .debug_info relocations might need
+ to be updated. */
+ info_rel_updated = rel_updated;
+
+ /* We might have to recalculate/rewrite the debug_line
+ section. We need to do that before going into phase one
+ so we have all new offsets. We do this separately from
+ scanning the dirs/file names because the DW_AT_stmt_lists
+ might not be in order or skip some padding we might have
+ to (re)move. */
+ if (phase == 0 && need_stmt_update)
{
- /* If we don't need to update anyhing, skip phase 1. */
- if (phase == 1
- && !need_strp_update
- && !need_string_replacement
- && !need_stmt_update)
- break;
+ edit_dwarf2_line (dso);
- ptr = debug_sections[DEBUG_INFO].data;
- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
- rel_updated = false;
- endsec = ptr + debug_sections[DEBUG_INFO].size;
- while (ptr < endsec)
+ /* The line table programs will be moved
+ forward/backwards a bit in the new data. Update the
+ debug_line relocations to the new offsets. */
+ int rndx = debug_sections[DEBUG_LINE].relsec;
+ if (rndx != 0)
{
- if (ptr + 11 > endsec)
- {
- error (0, 0, "%s: .debug_info CU header too small",
- dso->filename);
- return 1;
- }
-
- endcu = ptr + 4;
- endcu += read_32 (ptr);
- if (endcu == ptr + 0xffffffff)
- {
- error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
- return 1;
- }
-
- if (endcu > endsec)
- {
- error (0, 0, "%s: .debug_info too small", dso->filename);
- return 1;
- }
-
- cu_version = read_16 (ptr);
- if (cu_version != 2 && cu_version != 3 && cu_version != 4)
- {
- error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
- cu_version);
- return 1;
- }
-
- value = read_32_relocated (ptr);
- if (value >= debug_sections[DEBUG_ABBREV].size)
+ LINE_REL *rbuf;
+ size_t rels;
+ Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
+ int rtype = dso->shdr[rndx].sh_type;
+ rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
+ rbuf = malloc (rels * sizeof (LINE_REL));
+ if (rbuf == NULL)
+ error (1, errno, "%s: Could not allocate line relocations",
+ dso->filename);
+
+ /* Sort them by offset into section. */
+ for (size_t i = 0; i < rels; i++)
{
- if (debug_sections[DEBUG_ABBREV].data == NULL)
- error (0, 0, "%s: .debug_abbrev not present", dso->filename);
+ if (rtype == SHT_RELA)
+ {
+ GElf_Rela rela;
+ if (gelf_getrela (rdata, i, &rela) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ rbuf[i].r_offset = rela.r_offset;
+ rbuf[i].ndx = i;
+ }
else
- error (0, 0, "%s: DWARF CU abbrev offset too large",
- dso->filename);
- return 1;
- }
-
- if (ptr_size == 0)
- {
- ptr_size = read_8 (ptr);
- if (ptr_size != 4 && ptr_size != 8)
{
- error (0, 0, "%s: Invalid DWARF pointer size %d",
- dso->filename, ptr_size);
- return 1;
+ GElf_Rel rel;
+ if (gelf_getrel (rdata, i, &rel) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ rbuf[i].r_offset = rel.r_offset;
+ rbuf[i].ndx = i;
}
}
- else if (read_8 (ptr) != ptr_size)
- {
- error (0, 0, "%s: DWARF pointer size differs between CUs",
- dso->filename);
- return 1;
- }
+ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
- abbrev = read_abbrev (dso,
- debug_sections[DEBUG_ABBREV].data + value);
- if (abbrev == NULL)
- return 1;
-
- while (ptr < endcu)
+ size_t lndx = 0;
+ for (size_t i = 0; i < rels; i++)
{
- tag.entry = read_uleb128 (ptr);
- if (tag.entry == 0)
- continue;
- t = htab_find_with_hash (abbrev, &tag, tag.entry);
- if (t == NULL)
+ /* These relocations only happen in ET_REL files
+ and are section offsets. */
+ GElf_Addr r_offset;
+ size_t ndx = rbuf[i].ndx;
+
+ GElf_Rel rel;
+ GElf_Rela rela;
+ if (rtype == SHT_RELA)
{
- error (0, 0, "%s: Could not find DWARF abbreviation %d",
- dso->filename, tag.entry);
- htab_delete (abbrev);
- return 1;
+ if (gelf_getrela (rdata, ndx, &rela) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ r_offset = rela.r_offset;
+ }
+ else
+ {
+ if (gelf_getrel (rdata, ndx, &rel) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+ r_offset = rel.r_offset;
}
- ptr = edit_attributes (dso, ptr, t, phase);
- if (ptr == NULL)
- break;
- }
+ while (lndx < dso->lines.used
+ && r_offset > (dso->lines.table[lndx].old_idx
+ + 4
+ + dso->lines.table[lndx].unit_length))
+ lndx++;
- htab_delete (abbrev);
- }
+ if (lndx >= dso->lines.used)
+ error (1, 0,
+ ".debug_line relocation offset out of range");
- /* Remember whether any .debug_info relocations might need
- to be updated. */
- info_rel_updated = rel_updated;
-
- /* We might have to recalculate/rewrite the debug_line
- section. We need to do that before going into phase one
- so we have all new offsets. We do this separately from
- scanning the dirs/file names because the DW_AT_stmt_lists
- might not be in order or skip some padding we might have
- to (re)move. */
- if (phase == 0 && need_stmt_update)
- {
- edit_dwarf2_line (dso);
+ /* Offset (pointing into the line program) moves
+ from old to new index including the header
+ size diff. */
+ r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
+ - dso->lines.table[lndx].old_idx)
+ + dso->lines.table[lndx].size_diff);
- /* The line table programs will be moved
- forward/backwards a bit in the new data. Update the
- debug_line relocations to the new offsets. */
- int rndx = debug_sections[DEBUG_LINE].relsec;
- if (rndx != 0)
- {
- LINE_REL *rbuf;
- size_t rels;
- Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
- int rtype = dso->shdr[rndx].sh_type;
- rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
- rbuf = malloc (rels * sizeof (LINE_REL));
- if (rbuf == NULL)
- error (1, errno, "%s: Could not allocate line relocations",
- dso->filename);
-
- /* Sort them by offset into section. */
- for (size_t i = 0; i < rels; i++)
+ if (rtype == SHT_RELA)
{
- if (rtype == SHT_RELA)
- {
- GElf_Rela rela;
- if (gelf_getrela (rdata, i, &rela) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- rbuf[i].r_offset = rela.r_offset;
- rbuf[i].ndx = i;
- }
- else
- {
- GElf_Rel rel;
- if (gelf_getrel (rdata, i, &rel) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- rbuf[i].r_offset = rel.r_offset;
- rbuf[i].ndx = i;
- }
+ rela.r_offset = r_offset;
+ if (gelf_update_rela (rdata, ndx, &rela) == 0)
+ error (1, 0, "Couldn't update relocation: %s",
+ elf_errmsg (-1));
}
- qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
-
- size_t lndx = 0;
- for (size_t i = 0; i < rels; i++)
+ else
{
- /* These relocations only happen in ET_REL files
- and are section offsets. */
- GElf_Addr r_offset;
- size_t ndx = rbuf[i].ndx;
-
- GElf_Rel rel;
- GElf_Rela rela;
- if (rtype == SHT_RELA)
- {
- if (gelf_getrela (rdata, ndx, &rela) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- r_offset = rela.r_offset;
- }
- else
- {
- if (gelf_getrel (rdata, ndx, &rel) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
- r_offset = rel.r_offset;
- }
-
- while (lndx < dso->lines.used
- && r_offset > (dso->lines.table[lndx].old_idx
- + 4
- + dso->lines.table[lndx].unit_length))
- lndx++;
-
- if (lndx >= dso->lines.used)
- error (1, 0,
- ".debug_line relocation offset out of range");
-
- /* Offset (pointing into the line program) moves
- from old to new index including the header
- size diff. */
- r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
- - dso->lines.table[lndx].old_idx)
- + dso->lines.table[lndx].size_diff);
-
- if (rtype == SHT_RELA)
- {
- rela.r_offset = r_offset;
- if (gelf_update_rela (rdata, ndx, &rela) == 0)
- error (1, 0, "Couldn't update relocation: %s",
- elf_errmsg (-1));
- }
- else
- {
- rel.r_offset = r_offset;
- if (gelf_update_rel (rdata, ndx, &rel) == 0)
- error (1, 0, "Couldn't update relocation: %s",
- elf_errmsg (-1));
- }
+ rel.r_offset = r_offset;
+ if (gelf_update_rel (rdata, ndx, &rel) == 0)
+ error (1, 0, "Couldn't update relocation: %s",
+ elf_errmsg (-1));
}
-
- elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
- free (rbuf);
}
+
+ elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
+ free (rbuf);
}
+ }
- /* The .debug_macro section also contains offsets into the
- .debug_str section and references to the .debug_line
- tables, so we need to update those as well if we update
- the strings or the stmts. */
- if ((need_strp_update || need_stmt_update)
- && debug_sections[DEBUG_MACRO].data)
+ /* The .debug_macro section also contains offsets into the
+ .debug_str section and references to the .debug_line
+ tables, so we need to update those as well if we update
+ the strings or the stmts. */
+ if ((need_strp_update || need_stmt_update)
+ && debug_sections[DEBUG_MACRO].data)
+ {
+ /* There might be multiple (COMDAT) .debug_macro sections. */
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+ while (macro_sec != NULL)
{
- /* There might be multiple (COMDAT) .debug_macro sections. */
- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
- while (macro_sec != NULL)
- {
- setup_relbuf(dso, macro_sec, &reltype);
- rel_updated = false;
+ setup_relbuf(dso, macro_sec, &reltype);
+ rel_updated = false;
- ptr = macro_sec->data;
- endsec = ptr + macro_sec->size;
- int op = 0, macro_version, macro_flags;
- int offset_len = 4, line_offset = 0;
+ ptr = macro_sec->data;
+ endsec = ptr + macro_sec->size;
+ int op = 0, macro_version, macro_flags;
+ int offset_len = 4, line_offset = 0;
- while (ptr < endsec)
+ while (ptr < endsec)
+ {
+ if (!op)
{
- if (!op)
- {
- macro_version = read_16 (ptr);
- macro_flags = read_8 (ptr);
- if (macro_version < 4 || macro_version > 5)
- error (1, 0, "unhandled .debug_macro version: %d",
- macro_version);
- if ((macro_flags & ~2) != 0)
- error (1, 0, "unhandled .debug_macro flags: 0x%x",
- macro_flags);
-
- offset_len = (macro_flags & 0x01) ? 8 : 4;
- line_offset = (macro_flags & 0x02) ? 1 : 0;
-
- if (offset_len != 4)
- error (0, 1,
- "Cannot handle 8 byte macro offsets: %s",
- dso->filename);
-
- /* Update the line_offset if it is there. */
- if (line_offset)
- {
- if (phase == 0)
- ptr += offset_len;
- else
- {
- size_t idx, new_idx;
- idx = do_read_32_relocated (ptr);
- new_idx = find_new_list_offs (&dso->lines,
- idx);
- write_32_relocated (ptr, new_idx);
- }
- }
- }
+ macro_version = read_16 (ptr);
+ macro_flags = read_8 (ptr);
+ if (macro_version < 4 || macro_version > 5)
+ error (1, 0, "unhandled .debug_macro version: %d",
+ macro_version);
+ if ((macro_flags & ~2) != 0)
+ error (1, 0, "unhandled .debug_macro flags: 0x%x",
+ macro_flags);
+
+ offset_len = (macro_flags & 0x01) ? 8 : 4;
+ line_offset = (macro_flags & 0x02) ? 1 : 0;
+
+ if (offset_len != 4)
+ error (0, 1,
+ "Cannot handle 8 byte macro offsets: %s",
+ dso->filename);
- op = read_8 (ptr);
- if (!op)
- continue;
- switch(op)
+ /* Update the line_offset if it is there. */
+ if (line_offset)
{
- case DW_MACRO_GNU_define:
- case DW_MACRO_GNU_undef:
- read_uleb128 (ptr);
- ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
- + 1);
- break;
- case DW_MACRO_GNU_start_file:
- read_uleb128 (ptr);
- read_uleb128 (ptr);
- break;
- case DW_MACRO_GNU_end_file:
- break;
- case DW_MACRO_GNU_define_indirect:
- case DW_MACRO_GNU_undef_indirect:
- read_uleb128 (ptr);
if (phase == 0)
- {
- size_t idx = read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings,
- idx);
- }
+ ptr += offset_len;
else
{
- struct stridxentry *entry;
size_t idx, new_idx;
idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
- new_idx = strent_offset (entry->entry);
+ new_idx = find_new_list_offs (&dso->lines,
+ idx);
write_32_relocated (ptr, new_idx);
}
- break;
- case DW_MACRO_GNU_transparent_include:
- ptr += offset_len;
- break;
- default:
- error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
- break;
}
}
- if (rel_updated)
- macro_rel_updated = true;
- macro_sec = macro_sec->next;
+ op = read_8 (ptr);
+ if (!op)
+ continue;
+ switch(op)
+ {
+ case DW_MACRO_GNU_define:
+ case DW_MACRO_GNU_undef:
+ read_uleb128 (ptr);
+ ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
+ + 1);
+ break;
+ case DW_MACRO_GNU_start_file:
+ read_uleb128 (ptr);
+ read_uleb128 (ptr);
+ break;
+ case DW_MACRO_GNU_end_file:
+ break;
+ case DW_MACRO_GNU_define_indirect:
+ case DW_MACRO_GNU_undef_indirect:
+ read_uleb128 (ptr);
+ if (phase == 0)
+ {
+ size_t idx = read_32_relocated (ptr);
+ record_existing_string_entry_idx (&dso->strings,
+ idx);
+ }
+ else
+ {
+ struct stridxentry *entry;
+ size_t idx, new_idx;
+ idx = do_read_32_relocated (ptr);
+ entry = string_find_entry (&dso->strings, idx);
+ new_idx = strent_offset (entry->entry);
+ write_32_relocated (ptr, new_idx);
+ }
+ break;
+ case DW_MACRO_GNU_transparent_include:
+ ptr += offset_len;
+ break;
+ default:
+ error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
+ break;
+ }
}
- }
- /* Same for the debug_str section. Make sure everything is
- in place for phase 1 updating of debug_info
- references. */
- if (phase == 0 && need_strp_update)
- {
- Strtab *strtab = dso->strings.str_tab;
- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
- int strndx = debug_sections[DEBUG_STR].sec;
- Elf_Scn *strscn = dso->scn[strndx];
-
- /* Out with the old. */
- strdata->d_size = 0;
- /* In with the new. */
- strdata = elf_newdata (strscn);
-
- /* We really should check whether we had enough memory,
- but the old ebl version will just abort on out of
- memory... */
- strtab_finalize (strtab, strdata);
- debug_sections[DEBUG_STR].size = strdata->d_size;
- dso->strings.str_buf = strdata->d_buf;
+ if (rel_updated)
+ macro_rel_updated = true;
+ macro_sec = macro_sec->next;
}
+ }
+ /* Same for the debug_str section. Make sure everything is
+ in place for phase 1 updating of debug_info
+ references. */
+ if (phase == 0 && need_strp_update)
+ {
+ Strtab *strtab = dso->strings.str_tab;
+ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+ int strndx = debug_sections[DEBUG_STR].sec;
+ Elf_Scn *strscn = dso->scn[strndx];
+
+ /* Out with the old. */
+ strdata->d_size = 0;
+ /* In with the new. */
+ strdata = elf_newdata (strscn);
+
+ /* We really should check whether we had enough memory,
+ but the old ebl version will just abort on out of
+ memory... */
+ strtab_finalize (strtab, strdata);
+ debug_sections[DEBUG_STR].size = strdata->d_size;
+ dso->strings.str_buf = strdata->d_buf;
}
- /* After phase 1 we might have rewritten the debug_info with
- new strp, strings and/or linep offsets. */
- if (need_strp_update || need_string_replacement || need_stmt_update)
- dirty_section (DEBUG_INFO);
- if (need_strp_update || need_stmt_update)
- dirty_section (DEBUG_MACRO);
- if (need_stmt_update)
- dirty_section (DEBUG_LINE);
+ }
+
+ /* After phase 1 we might have rewritten the debug_info with
+ new strp, strings and/or linep offsets. */
+ if (need_strp_update || need_string_replacement || need_stmt_update)
+ dirty_section (DEBUG_INFO);
+ if (need_strp_update || need_stmt_update)
+ dirty_section (DEBUG_MACRO);
+ if (need_stmt_update)
+ dirty_section (DEBUG_LINE);
- /* Update any relocations addends we might have touched. */
- if (info_rel_updated)
- update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+ /* Update any relocations addends we might have touched. */
+ if (info_rel_updated)
+ update_rela_data (dso, &debug_sections[DEBUG_INFO]);
- if (macro_rel_updated)
+ if (macro_rel_updated)
+ {
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+ while (macro_sec != NULL)
{
- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
- while (macro_sec != NULL)
- {
- update_rela_data (dso, macro_sec);
- macro_sec = macro_sec->next;
- }
+ update_rela_data (dso, macro_sec);
+ macro_sec = macro_sec->next;
}
}
--
2.18.4

@ -1,269 +0,0 @@
From 8cd4d5046d7cb1bc16f01e77a5ff50eca8d9da3d Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Sat, 1 Aug 2020 10:45:47 +0200
Subject: [PATCH 3/6] debugedit: Fix missing relocation of .debug_types
section.
---
tools/debugedit.c | 123 ++++++++++++++++++++++++++++++----------------
1 file changed, 80 insertions(+), 43 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index cad0cc349..87c1cd622 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -433,7 +433,8 @@ typedef struct debug_section
int sec, relsec;
REL *relbuf;
REL *relend;
- struct debug_section *next; /* Only happens for COMDAT .debug_macro. */
+ /* Only happens for COMDAT .debug_macro and .debug_types. */
+ struct debug_section *next;
} debug_section;
static debug_section debug_sections[] =
@@ -1269,7 +1270,9 @@ static int dirty_elf;
static void
dirty_section (unsigned int sec)
{
- elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY);
+ for (struct debug_section *secp = &debug_sections[sec]; secp != NULL;
+ secp = secp->next)
+ elf_flagdata (secp->elf_data, ELF_C_SET, ELF_F_DIRTY);
dirty_elf = 1;
}
@@ -1469,12 +1472,7 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
if (get_line_table (dso, off, &table) == false
|| table == NULL)
- {
- if (table != NULL)
- error (0, 0, ".debug_line offset 0x%x referenced multiple times",
- off);
- return false;
- }
+ return false;
/* Skip to the directory table. The rest of the header has already
been read and checked by get_line_table. */
@@ -1965,22 +1963,25 @@ line_rel_cmp (const void *a, const void *b)
}
static int
-edit_info (DSO *dso, int phase)
+edit_info (DSO *dso, int phase, struct debug_section *sec)
{
unsigned char *ptr, *endcu, *endsec;
uint32_t value;
htab_t abbrev;
struct abbrev_tag tag, *t;
- ptr = debug_sections[DEBUG_INFO].data;
- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
- endsec = ptr + debug_sections[DEBUG_INFO].size;
+ ptr = sec->data;
+ if (ptr == NULL)
+ return 0;
+
+ setup_relbuf(dso, sec, &reltype);
+ endsec = ptr + sec->size;
while (ptr < endsec)
{
- if (ptr + 11 > endsec)
+ if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
{
- error (0, 0, "%s: .debug_info CU header too small",
- dso->filename);
+ error (0, 0, "%s: %s CU header too small",
+ dso->filename, sec->name);
return 1;
}
@@ -1994,7 +1995,7 @@ edit_info (DSO *dso, int phase)
if (endcu > endsec)
{
- error (0, 0, "%s: .debug_info too small", dso->filename);
+ error (0, 0, "%s: %s too small", dso->filename, sec->name);
return 1;
}
@@ -2034,6 +2035,9 @@ edit_info (DSO *dso, int phase)
return 1;
}
+ if (sec != &debug_sections[DEBUG_INFO])
+ ptr += 12; /* Skip type_signature and type_offset. */
+
abbrev = read_abbrev (dso,
debug_sections[DEBUG_ABBREV].data + value);
if (abbrev == NULL)
@@ -2095,7 +2099,7 @@ edit_dwarf2 (DSO *dso)
struct debug_section *debug_sec = &debug_sections[j];
if (debug_sections[j].data)
{
- if (j != DEBUG_MACRO)
+ if (j != DEBUG_MACRO && j != DEBUG_TYPES)
{
error (0, 0, "%s: Found two copies of %s section",
dso->filename, name);
@@ -2103,22 +2107,21 @@ edit_dwarf2 (DSO *dso)
}
else
{
- /* In relocatable files .debug_macro might
- appear multiple times as COMDAT
- section. */
+ /* In relocatable files .debug_macro and .debug_types
+ might appear multiple times as COMDAT section. */
struct debug_section *sec;
sec = calloc (sizeof (struct debug_section), 1);
if (sec == NULL)
error (1, errno,
- "%s: Could not allocate more macro sections",
- dso->filename);
- sec->name = ".debug_macro";
+ "%s: Could not allocate more %s sections",
+ dso->filename, name);
+ sec->name = name;
- struct debug_section *macro_sec = debug_sec;
- while (macro_sec->next != NULL)
- macro_sec = macro_sec->next;
+ struct debug_section *multi_sec = debug_sec;
+ while (multi_sec->next != NULL)
+ multi_sec = multi_sec->next;
- macro_sec->next = sec;
+ multi_sec->next = sec;
debug_sec = sec;
}
}
@@ -2155,23 +2158,23 @@ edit_dwarf2 (DSO *dso)
+ (dso->shdr[i].sh_type == SHT_RELA),
debug_sections[j].name) == 0)
{
- if (j == DEBUG_MACRO)
+ if (j == DEBUG_MACRO || j == DEBUG_TYPES)
{
/* Pick the correct one. */
int rel_target = dso->shdr[i].sh_info;
- struct debug_section *macro_sec = &debug_sections[j];
- while (macro_sec != NULL)
+ struct debug_section *multi_sec = &debug_sections[j];
+ while (multi_sec != NULL)
{
- if (macro_sec->sec == rel_target)
+ if (multi_sec->sec == rel_target)
{
- macro_sec->relsec = i;
+ multi_sec->relsec = i;
break;
}
- macro_sec = macro_sec->next;
+ multi_sec = multi_sec->next;
}
- if (macro_sec == NULL)
- error (0, 1, "No .debug_macro reloc section: %s",
- dso->filename);
+ if (multi_sec == NULL)
+ error (0, 1, "No %s reloc section: %s",
+ debug_sections[j].name, dso->filename);
}
else
debug_sections[j].relsec = i;
@@ -2203,12 +2206,10 @@ edit_dwarf2 (DSO *dso)
if (debug_sections[DEBUG_INFO].data == NULL)
return 0;
- unsigned char *ptr, *endcu, *endsec;
- uint32_t value;
- htab_t abbrev;
- struct abbrev_tag tag, *t;
+ unsigned char *ptr, *endsec;
int phase;
bool info_rel_updated = false;
+ bool types_rel_updated = false;
bool macro_rel_updated = false;
for (phase = 0; phase < 2; phase++)
@@ -2221,13 +2222,26 @@ edit_dwarf2 (DSO *dso)
break;
rel_updated = false;
- if (edit_info (dso, phase))
- return 1;
+ if (edit_info (dso, phase, &debug_sections[DEBUG_INFO]))
+ return 1;
/* Remember whether any .debug_info relocations might need
to be updated. */
info_rel_updated = rel_updated;
+ rel_updated = false;
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
+ while (types_sec != NULL)
+ {
+ if (edit_info (dso, phase, types_sec))
+ return 1;
+ types_sec = types_sec->next;
+ }
+
+ /* Remember whether any .debug_types relocations might need
+ to be updated. */
+ types_rel_updated = rel_updated;
+
/* We might have to recalculate/rewrite the debug_line
section. We need to do that before going into phase one
so we have all new offsets. We do this separately from
@@ -2475,8 +2489,11 @@ edit_dwarf2 (DSO *dso)
/* After phase 1 we might have rewritten the debug_info with
new strp, strings and/or linep offsets. */
- if (need_strp_update || need_string_replacement || need_stmt_update)
+ if (need_strp_update || need_string_replacement || need_stmt_update) {
dirty_section (DEBUG_INFO);
+ if (debug_sections[DEBUG_TYPES].data != NULL)
+ dirty_section (DEBUG_TYPES);
+ }
if (need_strp_update || need_stmt_update)
dirty_section (DEBUG_MACRO);
if (need_stmt_update)
@@ -2485,6 +2502,15 @@ edit_dwarf2 (DSO *dso)
/* Update any relocations addends we might have touched. */
if (info_rel_updated)
update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+ if (types_rel_updated)
+ {
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
+ while (types_sec != NULL)
+ {
+ update_rela_data (dso, types_sec);
+ types_sec = types_sec->next;
+ }
+ }
if (macro_rel_updated)
{
@@ -3037,6 +3063,17 @@ main (int argc, char *argv[])
macro_sec = next;
}
+ /* In case there were multiple (COMDAT) .debug_types sections,
+ free them. */
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
+ types_sec = types_sec->next;
+ while (types_sec != NULL)
+ {
+ struct debug_section *next = types_sec->next;
+ free (types_sec);
+ types_sec = next;
+ }
+
poptFreeContext (optCon);
return 0;
--
2.18.4

@ -1,455 +0,0 @@
From bab443ab4f756ef80f814af0353143f41e90e6a6 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Mon, 17 Aug 2020 21:58:19 +0200
Subject: [PATCH 4/6] [NFC] debugedit: Move code to separate functions.
New functions edit_strp, skip_form and edit_attributes_str_comp_dir
called by edit_attributes.
Split part of read_dwarf2_line into a read_dwarf4_line function.
New function edit_dwarf2_any_str called by edit_dwarf2 at the end of
phase 0 to rebuild .debug_str.
---
tools/debugedit.c | 367 ++++++++++++++++++++++++++--------------------
1 file changed, 212 insertions(+), 155 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 87c1cd622..7464883c5 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1457,37 +1457,128 @@ edit_dwarf2_line (DSO *dso)
}
}
-/* Called during phase zero for each debug_line table referenced from
- .debug_info. Outputs all source files seen and records any
- adjustments needed in the debug_list data structures. Returns true
- if line_table needs to be rewrite either the dir or file paths. */
+/* Record or adjust (according to phase) DW_FORM_strp. */
+static void
+edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
+{
+ unsigned char *ptr_orig = ptr;
+
+ /* In the first pass we collect all strings, in the
+ second we put the new references back (if there are
+ any changes). */
+ if (phase == 0)
+ {
+ /* handled_strp is set for attributes referring to
+ files. If it is set the string is already
+ recorded. */
+ if (! handled_strp)
+ {
+ size_t idx = do_read_32_relocated (ptr);
+ record_existing_string_entry_idx (&dso->strings, idx);
+ }
+ }
+ else if (need_strp_update) /* && phase == 1 */
+ {
+ struct stridxentry *entry;
+ size_t idx, new_idx;
+ idx = do_read_32_relocated (ptr);
+ entry = string_find_entry (&dso->strings, idx);
+ new_idx = strent_offset (entry->entry);
+ do_write_32_relocated (ptr, new_idx);
+ }
+
+ assert (ptr == ptr_orig);
+}
+
+/* Adjust *PTRP after the current *FORMP, update *FORMP for FORM_INDIRECT. */
+static enum { FORM_OK, FORM_ERROR, FORM_INDIRECT }
+skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
+{
+ size_t len = 0;
+
+ switch (*formp)
+ {
+ case DW_FORM_ref_addr:
+ if (cu_version == 2)
+ *ptrp += ptr_size;
+ else
+ *ptrp += 4;
+ break;
+ case DW_FORM_flag_present:
+ break;
+ case DW_FORM_addr:
+ *ptrp += ptr_size;
+ break;
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ ++*ptrp;
+ break;
+ case DW_FORM_ref2:
+ case DW_FORM_data2:
+ *ptrp += 2;
+ break;
+ case DW_FORM_ref4:
+ case DW_FORM_data4:
+ case DW_FORM_sec_offset:
+ *ptrp += 4;
+ break;
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
+ *ptrp += 8;
+ break;
+ case DW_FORM_sdata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_udata:
+ read_uleb128 (*ptrp);
+ break;
+ case DW_FORM_strp:
+ *ptrp += 4;
+ break;
+ case DW_FORM_string:
+ *ptrp = (unsigned char *) strchr ((char *)*ptrp, '\0') + 1;
+ break;
+ case DW_FORM_indirect:
+ *formp = read_uleb128 (*ptrp);
+ return FORM_INDIRECT;
+ case DW_FORM_block1:
+ len = *(*ptrp)++;
+ break;
+ case DW_FORM_block2:
+ len = read_16 (*ptrp);
+ *formp = DW_FORM_block1;
+ break;
+ case DW_FORM_block4:
+ len = read_32 (*ptrp);
+ *formp = DW_FORM_block1;
+ break;
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ len = read_uleb128 (*ptrp);
+ *formp = DW_FORM_block1;
+ assert (len < UINT_MAX);
+ break;
+ default:
+ error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
+ return FORM_ERROR;
+ }
+
+ if (*formp == DW_FORM_block1)
+ *ptrp += len;
+
+ return FORM_OK;
+}
+
+/* Part of read_dwarf2_line processing DWARF-4. */
static bool
-read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
+ struct line_table *table)
{
- unsigned char *ptr, *dir;
unsigned char **dirt;
uint32_t value, dirt_cnt;
size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir);
- struct line_table *table;
-
- if (get_line_table (dso, off, &table) == false
- || table == NULL)
- return false;
-
- /* Skip to the directory table. The rest of the header has already
- been read and checked by get_line_table. */
- ptr = debug_sections[DEBUG_LINE].data + off;
- ptr += (4 /* unit len */
- + 2 /* version */
- + 4 /* header len */
- + 1 /* min instr len */
- + (table->version >= 4) /* max op per instr, if version >= 4 */
- + 1 /* default is stmt */
- + 1 /* line base */
- + 1 /* line range */
- + 1 /* opcode base */
- + table->opcode_base - 1); /* opcode len table */
- dir = ptr;
+ unsigned char *dir = ptr;
/* dir table: */
value = 1;
@@ -1620,6 +1711,40 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
read_uleb128 (ptr);
}
+ return true;
+}
+
+/* Called during phase zero for each debug_line table referenced from
+ .debug_info. Outputs all source files seen and records any
+ adjustments needed in the debug_list data structures. Returns true
+ if line_table needs to be rewrite either the dir or file paths. */
+static bool
+read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+{
+ unsigned char *ptr;
+ struct line_table *table;
+
+ if (get_line_table (dso, off, &table) == false
+ || table == NULL)
+ return false;
+
+ /* Skip to the directory table. The rest of the header has already
+ been read and checked by get_line_table. */
+ ptr = debug_sections[DEBUG_LINE].data + off;
+ ptr += (4 /* unit len */
+ + 2 /* version */
+ + 4 /* header len */
+ + 1 /* min instr len */
+ + (table->version >= 4) /* max op per instr, if version >= 4 */
+ + 1 /* default is stmt */
+ + 1 /* line base */
+ + 1 /* line range */
+ + 1 /* opcode base */
+ + table->opcode_base - 1); /* opcode len table */
+
+ if (! read_dwarf4_line (dso, ptr, comp_dir, table))
+ return false;
+
dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
return table->replace_dirs || table->replace_files;
}
@@ -1637,6 +1762,33 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
return table->new_idx;
}
+/* Read DW_FORM_strp collecting compilation directory. */
+static void
+edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
+ char **comp_dirp, bool *handled_strpp)
+{
+ const char *dir;
+ size_t idx = do_read_32_relocated (*ptrp);
+ /* In phase zero we collect the comp_dir. */
+ if (phase == 0)
+ {
+ if (idx >= debug_sections[DEBUG_STR].size)
+ error (1, 0, "%s: Bad string pointer index %zd for comp_dir",
+ dso->filename, idx);
+ dir = (char *) debug_sections[DEBUG_STR].data + idx;
+
+ free (*comp_dirp);
+ *comp_dirp = strdup (dir);
+ }
+
+ if (dest_dir != NULL && phase == 0)
+ {
+ if (record_file_string_entry_idx (&dso->strings, idx))
+ need_strp_update = true;
+ *handled_strpp = true;
+ }
+}
+
/* This scans the attributes of one DIE described by the given abbrev_tag.
PTR points to the data in the debug_info. It will be advanced till all
abbrev data is consumed. In phase zero data is collected, in phase one
@@ -1655,7 +1807,6 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
for (i = 0; i < t->nattr; ++i)
{
uint32_t form = t->attr[i].form;
- size_t len = 0;
while (1)
{
/* Whether we already handled a string as file for this
@@ -1743,29 +1894,8 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
}
else if (form == DW_FORM_strp &&
debug_sections[DEBUG_STR].data)
- {
- const char *dir;
- size_t idx = do_read_32_relocated (ptr);
- /* In phase zero we collect the comp_dir. */
- if (phase == 0)
- {
- if (idx >= debug_sections[DEBUG_STR].size)
- error (1, 0,
- "%s: Bad string pointer index %zd for comp_dir",
- dso->filename, idx);
- dir = (char *) debug_sections[DEBUG_STR].data + idx;
-
- free (comp_dir);
- comp_dir = strdup (dir);
- }
-
- if (dest_dir != NULL && phase == 0)
- {
- if (record_file_string_entry_idx (&dso->strings, idx))
- need_strp_update = true;
- handled_strp = true;
- }
- }
+ edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir,
+ &handled_strp);
}
else if ((t->tag == DW_TAG_compile_unit
|| t->tag == DW_TAG_partial_unit)
@@ -1815,99 +1945,21 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
switch (form)
{
- case DW_FORM_ref_addr:
- if (cu_version == 2)
- ptr += ptr_size;
- else
- ptr += 4;
- break;
- case DW_FORM_flag_present:
- break;
- case DW_FORM_addr:
- ptr += ptr_size;
- break;
- case DW_FORM_ref1:
- case DW_FORM_flag:
- case DW_FORM_data1:
- ++ptr;
- break;
- case DW_FORM_ref2:
- case DW_FORM_data2:
- ptr += 2;
- break;
- case DW_FORM_ref4:
- case DW_FORM_data4:
- case DW_FORM_sec_offset:
- ptr += 4;
- break;
- case DW_FORM_ref8:
- case DW_FORM_data8:
- case DW_FORM_ref_sig8:
- ptr += 8;
- break;
- case DW_FORM_sdata:
- case DW_FORM_ref_udata:
- case DW_FORM_udata:
- read_uleb128 (ptr);
- break;
case DW_FORM_strp:
- /* In the first pass we collect all strings, in the
- second we put the new references back (if there are
- any changes). */
- if (phase == 0)
- {
- /* handled_strp is set for attributes referring to
- files. If it is set the string is already
- recorded. */
- if (! handled_strp)
- {
- size_t idx = do_read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings, idx);
- }
- }
- else if (need_strp_update) /* && phase == 1 */
- {
- struct stridxentry *entry;
- size_t idx, new_idx;
- idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
- new_idx = strent_offset (entry->entry);
- do_write_32_relocated (ptr, new_idx);
- }
- ptr += 4;
- break;
- case DW_FORM_string:
- ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1;
- break;
- case DW_FORM_indirect:
- form = read_uleb128 (ptr);
- continue;
- case DW_FORM_block1:
- len = *ptr++;
- break;
- case DW_FORM_block2:
- len = read_16 (ptr);
- form = DW_FORM_block1;
+ edit_strp (dso, ptr, phase, handled_strp);
break;
- case DW_FORM_block4:
- len = read_32 (ptr);
- form = DW_FORM_block1;
- break;
- case DW_FORM_block:
- case DW_FORM_exprloc:
- len = read_uleb128 (ptr);
- form = DW_FORM_block1;
- assert (len < UINT_MAX);
+ }
+
+ switch (skip_form (dso, &form, &ptr))
+ {
+ case FORM_OK:
break;
- default:
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename,
- form);
+ case FORM_ERROR:
return NULL;
+ case FORM_INDIRECT:
+ continue;
}
- if (form == DW_FORM_block1)
- ptr += len;
-
break;
}
}
@@ -2068,6 +2120,28 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
return 0;
}
+/* Rebuild .debug_str. */
+static void
+edit_dwarf2_any_str (DSO *dso)
+{
+ Strtab *strtab = dso->strings.str_tab;
+ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+ int strndx = debug_sections[DEBUG_STR].sec;
+ Elf_Scn *strscn = dso->scn[strndx];
+
+ /* Out with the old. */
+ strdata->d_size = 0;
+ /* In with the new. */
+ strdata = elf_newdata (strscn);
+
+ /* We really should check whether we had enough memory,
+ but the old ebl version will just abort on out of
+ memory... */
+ strtab_finalize (strtab, strdata);
+ debug_sections[DEBUG_STR].size = strdata->d_size;
+ dso->strings.str_buf = strdata->d_buf;
+}
+
static int
edit_dwarf2 (DSO *dso)
{
@@ -2466,24 +2540,7 @@ edit_dwarf2 (DSO *dso)
in place for phase 1 updating of debug_info
references. */
if (phase == 0 && need_strp_update)
- {
- Strtab *strtab = dso->strings.str_tab;
- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
- int strndx = debug_sections[DEBUG_STR].sec;
- Elf_Scn *strscn = dso->scn[strndx];
-
- /* Out with the old. */
- strdata->d_size = 0;
- /* In with the new. */
- strdata = elf_newdata (strscn);
-
- /* We really should check whether we had enough memory,
- but the old ebl version will just abort on out of
- memory... */
- strtab_finalize (strtab, strdata);
- debug_sections[DEBUG_STR].size = strdata->d_size;
- dso->strings.str_buf = strdata->d_buf;
- }
+ edit_dwarf2_any_str (dso);
}
--
2.18.4

@ -1,217 +0,0 @@
From 8b5dcb4c2175ac706a4e1c34ce83301213800689 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Mon, 18 Jan 2021 22:56:53 +0100
Subject: [PATCH 5/6] debugedit: Implement DWARF-5 unit header and new forms
parsing.
Recognize the various new DWARF5 .debug sections.
Parse and skip new DWARF5 forms in read_abbrev and skip_form.
Read DWARF5 unit headers for compile and partial units in edit_info.
This is enough to be able to process gcc -gdwarf-5 produced binaries
without the new DWARF5 .debug_line format (which isn't produced with
binutils < 2.36).
Patches slightly edited/merged by Mark Wielaard <mark@klomp.org>
---
tools/debugedit.c | 88 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 81 insertions(+), 7 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 7464883c5..be5fee85b 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -453,6 +453,11 @@ static debug_section debug_sections[] =
#define DEBUG_TYPES 11
#define DEBUG_MACRO 12
#define DEBUG_GDB_SCRIPT 13
+#define DEBUG_RNGLISTS 14
+#define DEBUG_LINE_STR 15
+#define DEBUG_ADDR 16
+#define DEBUG_STR_OFFSETS 17
+#define DEBUG_LOCLISTS 18
{ ".debug_info", NULL, NULL, 0, 0, 0 },
{ ".debug_abbrev", NULL, NULL, 0, 0, 0 },
{ ".debug_line", NULL, NULL, 0, 0, 0 },
@@ -467,6 +472,11 @@ static debug_section debug_sections[] =
{ ".debug_types", NULL, NULL, 0, 0, 0 },
{ ".debug_macro", NULL, NULL, 0, 0, 0 },
{ ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 },
+ { ".debug_rnglists", NULL, NULL, 0, 0, 0 },
+ { ".debug_line_str", NULL, NULL, 0, 0, 0 },
+ { ".debug_addr", NULL, NULL, 0, 0, 0 },
+ { ".debug_str_offsets", NULL, NULL, 0, 0, 0 },
+ { ".debug_loclists", NULL, NULL, 0, 0, 0 },
{ NULL, NULL, NULL, 0, 0, 0 }
};
@@ -755,12 +765,28 @@ no_memory:
}
form = read_uleb128 (ptr);
if (form == 2
- || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
+ || (form > DW_FORM_flag_present
+ && !(form == DW_FORM_ref_sig8
+ || form == DW_FORM_data16
+ || form == DW_FORM_implicit_const
+ || form == DW_FORM_addrx
+ || form == DW_FORM_loclistx
+ || form == DW_FORM_rnglistx
+ || form == DW_FORM_addrx1
+ || form == DW_FORM_addrx2
+ || form == DW_FORM_addrx3
+ || form == DW_FORM_addrx4)))
{
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
+ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename,
+ form);
htab_delete (h);
return NULL;
}
+ if (form == DW_FORM_implicit_const)
+ {
+ /* It is SLEB128 but the value is dropped anyway. */
+ read_uleb128 (ptr);
+ }
t->attr[t->nattr].attr = attr;
t->attr[t->nattr++].form = form;
@@ -1505,6 +1531,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
*ptrp += 4;
break;
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
break;
case DW_FORM_addr:
*ptrp += ptr_size;
@@ -1512,14 +1539,24 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
case DW_FORM_ref1:
case DW_FORM_flag:
case DW_FORM_data1:
+ case DW_FORM_strx1:
+ case DW_FORM_addrx1:
++*ptrp;
break;
case DW_FORM_ref2:
case DW_FORM_data2:
+ case DW_FORM_strx2:
+ case DW_FORM_addrx2:
*ptrp += 2;
break;
+ case DW_FORM_strx3:
+ case DW_FORM_addrx3:
+ *ptrp += 3;
+ break;
case DW_FORM_ref4:
case DW_FORM_data4:
+ case DW_FORM_strx4:
+ case DW_FORM_addrx4:
case DW_FORM_sec_offset:
*ptrp += 4;
break;
@@ -1528,12 +1565,20 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
case DW_FORM_ref_sig8:
*ptrp += 8;
break;
+ case DW_FORM_data16:
+ *ptrp += 16;
+ break;
case DW_FORM_sdata:
case DW_FORM_ref_udata:
case DW_FORM_udata:
+ case DW_FORM_strx:
+ case DW_FORM_loclistx:
+ case DW_FORM_rnglistx:
+ case DW_FORM_addrx:
read_uleb128 (*ptrp);
break;
case DW_FORM_strp:
+ case DW_FORM_line_strp:
*ptrp += 4;
break;
case DW_FORM_string:
@@ -1560,7 +1605,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
assert (len < UINT_MAX);
break;
default:
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
+ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, *formp);
return FORM_ERROR;
}
@@ -2030,7 +2075,10 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
endsec = ptr + sec->size;
while (ptr < endsec)
{
- if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
+ unsigned char *cu_start = ptr;
+
+ /* header size, version, unit_type, ptr_size. */
+ if (ptr + 4 + 2 + 1 + 1 > endsec)
{
error (0, 0, "%s: %s CU header too small",
dso->filename, sec->name);
@@ -2052,13 +2100,36 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
}
cu_version = read_16 (ptr);
- if (cu_version != 2 && cu_version != 3 && cu_version != 4)
+ if (cu_version != 2 && cu_version != 3 && cu_version != 4
+ && cu_version != 5)
{
error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
cu_version);
return 1;
}
+ int cu_ptr_size = 0;
+
+ if (cu_version >= 5)
+ {
+ uint8_t unit_type = read_8 (ptr);
+ if (unit_type != DW_UT_compile && unit_type != DW_UT_partial)
+ {
+ error (0, 0, "%s: Unit type %u unhandled", dso->filename,
+ unit_type);
+ return 1;
+ }
+
+ cu_ptr_size = read_8 (ptr);
+ }
+
+ unsigned char *header_end = (cu_start + 23 + (cu_version < 5 ? 0 : 1));
+ if (header_end > endsec)
+ {
+ error (0, 0, "%s: %s CU header too small", dso->filename, sec->name);
+ return 1;
+ }
+
value = read_32_relocated (ptr);
if (value >= debug_sections[DEBUG_ABBREV].size)
{
@@ -2070,9 +2141,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
return 1;
}
+ if (cu_version < 5)
+ cu_ptr_size = read_8 (ptr);
+
if (ptr_size == 0)
{
- ptr_size = read_8 (ptr);
+ ptr_size = cu_ptr_size;
if (ptr_size != 4 && ptr_size != 8)
{
error (0, 0, "%s: Invalid DWARF pointer size %d",
@@ -2080,7 +2154,7 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
return 1;
}
}
- else if (read_8 (ptr) != ptr_size)
+ else if (cu_ptr_size != ptr_size)
{
error (0, 0, "%s: DWARF pointer size differs between CUs",
dso->filename);
--
2.18.4

@ -1,772 +0,0 @@
From d9947f2dc0c2cd812f8e64380d5f6f53705a5280 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Tue, 19 Jan 2021 04:12:33 +0100
Subject: [PATCH 6/6] debugedit: Handle DWARF-5 debug_line and debug_line_str.
Handle the new DWARF5 .debug_line tables and the new DW_FORM_line_strp.
DWARF5 tables are handled separately from the earlier tables. They
will never change size, but they do need updates to the .debug_str
or .debug_line_str references.
Based on a patch from Jan Kratochvil <jan.kratochvil@redhat.com>
---
tools/debugedit.c | 471 ++++++++++++++++++++++++++++++++++++++++------
1 file changed, 410 insertions(+), 61 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index be5fee85b..d6a0058e9 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -103,6 +103,8 @@ static bool need_string_replacement = false;
/* Whether we need to do any updates of the string indexes (DW_FORM_strp)
in debug_info for string indexes. */
static bool need_strp_update = false;
+/* Likewise for DW_FORM_line_strp. */
+static bool need_line_strp_update = false;
/* If the debug_line changes size we will need to update the
DW_AT_stmt_list attributes indexes in the debug_info. */
static bool need_stmt_update = false;
@@ -192,7 +194,7 @@ typedef struct
const char *filename;
int lastscn;
size_t phnum;
- struct strings strings;
+ struct strings debug_str, debug_line_str;
struct debug_lines lines;
GElf_Shdr shdr[0];
} DSO;
@@ -553,10 +555,11 @@ setup_relbuf (DSO *dso, debug_section *sec, int *reltype)
/* Relocations against section symbols are uninteresting in REL. */
if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
continue;
- /* Only consider relocations against .debug_str, .debug_line
- and .debug_abbrev. */
+ /* Only consider relocations against .debug_str, .debug_line,
+ .debug_line_str, and .debug_abbrev. */
if (sym.st_shndx != debug_sections[DEBUG_STR].sec
&& sym.st_shndx != debug_sections[DEBUG_LINE].sec
+ && sym.st_shndx != debug_sections[DEBUG_LINE_STR].sec
&& sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
continue;
rela.r_addend += sym.st_value;
@@ -768,6 +771,7 @@ no_memory:
|| (form > DW_FORM_flag_present
&& !(form == DW_FORM_ref_sig8
|| form == DW_FORM_data16
+ || form == DW_FORM_line_strp
|| form == DW_FORM_implicit_const
|| form == DW_FORM_addrx
|| form == DW_FORM_loclistx
@@ -1049,17 +1053,20 @@ string_find_entry (struct strings *strings, size_t old_idx)
a replacement file string has been recorded for it, otherwise
returns false. */
static bool
-record_file_string_entry_idx (struct strings *strings, size_t old_idx)
+record_file_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
{
+ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
bool ret = false;
struct stridxentry *entry = string_find_new_entry (strings, old_idx);
if (entry != NULL)
{
- if (old_idx >= debug_sections[DEBUG_STR].size)
- error (1, 0, "Bad string pointer index %zd", old_idx);
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (old_idx >= sec->size)
+ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
Strent *strent;
- const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx;
+ const char *old_str = (char *)sec->data + old_idx;
const char *file = skip_dir_prefix (old_str, base_dir);
if (file == NULL)
{
@@ -1103,15 +1110,18 @@ record_file_string_entry_idx (struct strings *strings, size_t old_idx)
base_dir with dest_dir, just records the existing string associated
with the index. */
static void
-record_existing_string_entry_idx (struct strings *strings, size_t old_idx)
+record_existing_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
{
+ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
struct stridxentry *entry = string_find_new_entry (strings, old_idx);
if (entry != NULL)
{
- if (old_idx >= debug_sections[DEBUG_STR].size)
- error (1, 0, "Bad string pointer index %zd", old_idx);
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (old_idx >= sec->size)
+ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
- const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx;
+ const char *str = (char *)sec->data + old_idx;
Strent *strent = strtab_add_len (strings->str_tab,
str, strlen (str) + 1);
if (strent == NULL)
@@ -1244,13 +1254,28 @@ get_line_table (DSO *dso, size_t off, struct line_table **table)
/* version */
t->version = read_16 (ptr);
- if (t->version != 2 && t->version != 3 && t->version != 4)
+ if (t->version != 2 && t->version != 3 && t->version != 4 && t->version != 5)
{
error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
t->version);
return false;
}
+ if (t->version >= 5)
+ {
+ /* address_size */
+ assert (ptr_size != 0);
+ if (ptr_size != read_8 (ptr))
+ {
+ error (0, 0, "%s: .debug_line address size differs from .debug_info",
+ dso->filename);
+ return false;
+ }
+
+ /* segment_selector_size */
+ (void) read_8 (ptr);
+ }
+
/* header_length */
unsigned char *endprol = ptr + 4;
t->header_length = read_32 (ptr);
@@ -1343,7 +1368,9 @@ edit_dwarf2_line (DSO *dso)
linedata->d_size = dso->lines.debug_lines_len;
linedata->d_buf = dso->lines.line_buf;
+ debug_sections[DEBUG_LINE].data = linedata->d_buf;
debug_sections[DEBUG_LINE].size = linedata->d_size;
+ debug_sections[DEBUG_LINE].elf_data = linedata;
/* Make sure the line tables are sorted on the old index. */
qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table),
@@ -1483,9 +1510,10 @@ edit_dwarf2_line (DSO *dso)
}
}
-/* Record or adjust (according to phase) DW_FORM_strp. */
+/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp. */
static void
-edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
+edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase,
+ bool handled_strp)
{
unsigned char *ptr_orig = ptr;
@@ -1500,15 +1528,18 @@ edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
if (! handled_strp)
{
size_t idx = do_read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings, idx);
+ record_existing_string_entry_idx (line_strp, dso, idx);
}
}
- else if (need_strp_update) /* && phase == 1 */
+ else if (line_strp
+ ? need_line_strp_update : need_strp_update) /* && phase == 1 */
{
struct stridxentry *entry;
size_t idx, new_idx;
+ struct strings *strings = (line_strp
+ ? &dso->debug_line_str : &dso->debug_str);
idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
+ entry = string_find_entry (strings, idx);
new_idx = strent_offset (entry->entry);
do_write_32_relocated (ptr, new_idx);
}
@@ -1759,6 +1790,254 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
return true;
}
+/* Called by read_dwarf5_line first for directories and then file
+ names as they both have the same format. */
+static bool
+read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp,
+ struct line_table *table, int phase,
+ char ***dirs, int *ndir,
+ const char *entry_name)
+{
+ /* directory_entry_format_count */
+ /* file_name_entry_format_count */
+ unsigned format_count = read_8 (*ptrp);
+
+ unsigned char *formats = *ptrp;
+
+ /* directory_entry_format */
+ /* file_name_entry_format */
+ for (unsigned formati = 0; formati < format_count; ++formati)
+ {
+ read_uleb128 (*ptrp);
+ read_uleb128 (*ptrp);
+ }
+
+ /* directories_count */
+ /* file_names_count */
+ unsigned entry_count = read_uleb128 (*ptrp);
+
+ bool collecting_dirs = dest_dir && phase == 0 && *dirs == NULL;
+ bool writing_files = dest_dir && phase == 0 && *dirs != NULL;
+ if (collecting_dirs)
+ {
+ *ndir = entry_count;
+ *dirs = malloc (entry_count * sizeof (char *));
+ if (*dirs == NULL)
+ error (1, errno, "%s: Could not allocate debug_line dirs",
+ dso->filename);
+ }
+
+ /* directories */
+ /* file_names */
+ for (unsigned entryi = 0; entryi < entry_count; ++entryi)
+ {
+ char *dir = NULL;
+ char *file = NULL;;
+ unsigned char *format_ptr = formats;
+ for (unsigned formati = 0; formati < format_count; ++formati)
+ {
+ unsigned lnct = read_uleb128 (format_ptr);
+ unsigned form = read_uleb128 (format_ptr);
+ bool handled_form = false;
+ bool handled_strp = false;
+ bool line_strp = form == DW_FORM_line_strp;
+ if (lnct == DW_LNCT_path)
+ {
+ switch (form)
+ {
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ if (dest_dir && phase == 0)
+ {
+ size_t idx = do_read_32_relocated (*ptrp);
+ if (record_file_string_entry_idx (line_strp, dso, idx))
+ {
+ if (line_strp)
+ need_line_strp_update = true;
+ else
+ need_strp_update = true;
+ }
+ handled_strp = true;
+ if (collecting_dirs || writing_files)
+ {
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (collecting_dirs)
+ dir = (char *)sec->data + idx;
+ if (writing_files)
+ file = (char *)sec->data + idx;
+ }
+ }
+ break;
+ default:
+ error (0, 0, "%s: Unsupported "
+ ".debug_line %s %u path DW_FORM_0x%x",
+ dso->filename, entry_name, entryi, form);
+ return false;
+ }
+ }
+ if (writing_files && lnct == DW_LNCT_directory_index)
+ {
+ int dirndx;
+ switch (form)
+ {
+ case DW_FORM_udata:
+ handled_form = true;
+ dirndx = read_uleb128 (*ptrp);
+ break;
+ case DW_FORM_data1:
+ dirndx = **ptrp;
+ break;
+ case DW_FORM_data2:
+ dirndx = do_read_16 (*ptrp);
+ break;
+ case DW_FORM_data4:
+ dirndx = do_read_32 (*ptrp);
+ break;
+ default:
+ error (0, 0, "%s: Unsupported "
+ ".debug_line %s %u dirndx DW_FORM_0x%x",
+ dso->filename, entry_name, entryi, form);
+ return false;
+ }
+
+ if (dirndx > *ndir)
+ {
+ error (0, 0, "%s: Bad dir number %u in .debug_line %s",
+ dso->filename, entryi, entry_name);
+ return false;
+ }
+ dir = (*dirs)[dirndx];
+ }
+
+ switch (form)
+ {
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ edit_strp (dso, line_strp, *ptrp, phase, handled_strp);
+ break;
+ }
+
+ if (!handled_form)
+ {
+ switch (skip_form (dso, &form, ptrp))
+ {
+ case FORM_OK:
+ break;
+ case FORM_ERROR:
+ return false;
+ case FORM_INDIRECT:
+ error (0, 0, "%s: Unsupported "
+ ".debug_line %s %u DW_FORM_indirect",
+ dso->filename, entry_name, entryi);
+ return false;
+ }
+ }
+ }
+
+ if (collecting_dirs)
+ (*dirs)[entryi] = dir;
+
+ if (writing_files)
+ {
+ char *comp_dir = (*dirs)[0];
+ size_t comp_dir_len = strlen(comp_dir);
+ size_t file_len = strlen (file);
+ size_t dir_len = strlen (dir);
+
+ char *s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
+ if (s == NULL)
+ {
+ error (0, ENOMEM, "%s: Reading file table", dso->filename);
+ return false;
+ }
+ if (file[0] == '/')
+ {
+ memcpy (s, file, file_len + 1);
+ }
+ else if (dir[0] == '/')
+ {
+ memcpy (s, dir, dir_len);
+ s[dir_len] = '/';
+ memcpy (s + dir_len + 1, file, file_len + 1);
+ }
+ else
+ {
+ char *p = s;
+ if (comp_dir_len != 0)
+ {
+ memcpy (s, comp_dir, comp_dir_len);
+ s[comp_dir_len] = '/';
+ p += comp_dir_len + 1;
+ }
+ memcpy (p, dir, dir_len);
+ p[dir_len] = '/';
+ memcpy (p + dir_len + 1, file, file_len + 1);
+ }
+ canonicalize_path (s, s);
+ if (list_file_fd != -1)
+ {
+ const char *p = NULL;
+ if (base_dir == NULL)
+ p = s;
+ else
+ {
+ p = skip_dir_prefix (s, base_dir);
+ if (p == NULL && dest_dir != NULL)
+ p = skip_dir_prefix (s, dest_dir);
+ }
+
+ if (p)
+ {
+ size_t size = strlen (p) + 1;
+ while (size > 0)
+ {
+ ssize_t ret = write (list_file_fd, p, size);
+ if (ret == -1)
+ break;
+ size -= ret;
+ p += ret;
+ }
+ }
+ }
+
+ free (s);
+ }
+ }
+
+ return true;
+}
+
+/* Part of read_dwarf2_line processing DWARF-5. */
+static bool
+read_dwarf5_line (DSO *dso, unsigned char *ptr, struct line_table *table,
+ int phase)
+{
+ char **dirs = NULL;
+ int ndir;
+ /* Skip header. */
+ ptr += (4 /* unit len */
+ + 2 /* version */
+ + (table->version < 5 ? 0 : 0
+ + 1 /* address_size */
+ + 1 /* segment_selector*/)
+ + 4 /* header len */
+ + 1 /* min instr len */
+ + (table->version >= 4) /* max op per instr, if version >= 4 */
+ + 1 /* default is stmt */
+ + 1 /* line base */
+ + 1 /* line range */
+ + 1 /* opcode base */
+ + table->opcode_base - 1); /* opcode len table */
+
+ bool retval = (read_dwarf5_line_entries (dso, &ptr, table, phase,
+ &dirs, &ndir, "directory")
+ && read_dwarf5_line_entries (dso, &ptr, table, phase,
+ &dirs, &ndir, "file name"));
+ free (dirs);
+ return retval;
+}
+
/* Called during phase zero for each debug_line table referenced from
.debug_info. Outputs all source files seen and records any
adjustments needed in the debug_list data structures. Returns true
@@ -1778,6 +2057,9 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
ptr = debug_sections[DEBUG_LINE].data + off;
ptr += (4 /* unit len */
+ 2 /* version */
+ + (table->version < 5 ? 0 : 0
+ + 1 /* address_size */
+ + 1 /* segment_selector*/)
+ 4 /* header len */
+ 1 /* min instr len */
+ (table->version >= 4) /* max op per instr, if version >= 4 */
@@ -1787,8 +2069,13 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
+ 1 /* opcode base */
+ table->opcode_base - 1); /* opcode len table */
- if (! read_dwarf4_line (dso, ptr, comp_dir, table))
- return false;
+ /* DWARF version 5 line tables won't change size. But they might need
+ [line]strp recording/updates. Handle that part later. */
+ if (table->version < 5)
+ {
+ if (! read_dwarf4_line (dso, ptr, comp_dir, table))
+ return false;
+ }
dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
return table->replace_dirs || table->replace_files;
@@ -1807,20 +2094,22 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
return table->new_idx;
}
-/* Read DW_FORM_strp collecting compilation directory. */
+/* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory. */
static void
-edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
- char **comp_dirp, bool *handled_strpp)
+edit_attributes_str_comp_dir (bool line_strp, DSO *dso, unsigned char **ptrp,
+ int phase, char **comp_dirp, bool *handled_strpp)
{
const char *dir;
size_t idx = do_read_32_relocated (*ptrp);
/* In phase zero we collect the comp_dir. */
if (phase == 0)
{
- if (idx >= debug_sections[DEBUG_STR].size)
- error (1, 0, "%s: Bad string pointer index %zd for comp_dir",
- dso->filename, idx);
- dir = (char *) debug_sections[DEBUG_STR].data + idx;
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR : DEBUG_STR];
+ if (sec->data == NULL || idx >= sec->size)
+ error (1, 0, "%s: Bad string pointer index %zd for comp_dir (%s)",
+ dso->filename, idx, sec->name);
+ dir = (char *) sec->data + idx;
free (*comp_dirp);
*comp_dirp = strdup (dir);
@@ -1828,8 +2117,13 @@ edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
if (dest_dir != NULL && phase == 0)
{
- if (record_file_string_entry_idx (&dso->strings, idx))
- need_strp_update = true;
+ if (record_file_string_entry_idx (line_strp, dso, idx))
+ {
+ if (line_strp)
+ need_line_strp_update = true;
+ else
+ need_strp_update = true;
+ }
*handled_strpp = true;
}
}
@@ -1937,17 +2231,24 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
}
}
}
- else if (form == DW_FORM_strp &&
- debug_sections[DEBUG_STR].data)
- edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir,
+ else if (form == DW_FORM_strp)
+ edit_attributes_str_comp_dir (false /* line_strp */, dso,
+ &ptr, phase, &comp_dir,
&handled_strp);
+ else if (form == DW_FORM_line_strp)
+ edit_attributes_str_comp_dir (true /* line_strp */, dso, &ptr,
+ phase, &comp_dir, &handled_strp);
}
else if ((t->tag == DW_TAG_compile_unit
|| t->tag == DW_TAG_partial_unit)
- && t->attr[i].attr == DW_AT_name
- && form == DW_FORM_strp
- && debug_sections[DEBUG_STR].data)
+ && ((form == DW_FORM_strp
+ && debug_sections[DEBUG_STR].data)
+ || (form == DW_FORM_line_strp
+ && debug_sections[DEBUG_LINE_STR].data))
+ && t->attr[i].attr == DW_AT_name)
{
+ bool line_strp = form == DW_FORM_line_strp;
+
/* DW_AT_name is the primary file for this compile
unit. If starting with / it is a full path name.
Note that we don't handle DW_FORM_string in this
@@ -1957,11 +2258,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
/* In phase zero we will look for a comp_dir to use. */
if (phase == 0)
{
- if (idx >= debug_sections[DEBUG_STR].size)
+ debug_section *sec = &debug_sections[line_strp
+ ? DEBUG_LINE_STR
+ : DEBUG_STR];
+ if (idx >= sec->size)
error (1, 0,
- "%s: Bad string pointer index %zd for unit name",
- dso->filename, idx);
- char *name = (char *) debug_sections[DEBUG_STR].data + idx;
+ "%s: Bad string pointer index %zd for unit name (%s)",
+ dso->filename, idx, sec->name);
+ char *name = (char *) sec->data + idx;
if (*name == '/' && comp_dir == NULL)
{
char *enddir = strrchr (name, '/');
@@ -1982,8 +2286,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
pass (1) stores it (the new index). */
if (dest_dir && phase == 0)
{
- if (record_file_string_entry_idx (&dso->strings, idx))
- need_strp_update = true;
+ if (record_file_string_entry_idx (line_strp, dso, idx))
+ {
+ if (line_strp)
+ need_line_strp_update = true;
+ else
+ need_strp_update = true;
+ }
handled_strp = true;
}
}
@@ -1991,7 +2300,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
switch (form)
{
case DW_FORM_strp:
- edit_strp (dso, ptr, phase, handled_strp);
+ edit_strp (dso, false /* line_strp */, ptr, phase, handled_strp);
+ break;
+ case DW_FORM_line_strp:
+ edit_strp (dso, true /* line_strp */, ptr, phase, handled_strp);
break;
}
@@ -2196,11 +2508,11 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
/* Rebuild .debug_str. */
static void
-edit_dwarf2_any_str (DSO *dso)
+edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp)
{
- Strtab *strtab = dso->strings.str_tab;
- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
- int strndx = debug_sections[DEBUG_STR].sec;
+ Strtab *strtab = strings->str_tab;
+ Elf_Data *strdata = secp->elf_data;
+ int strndx = secp->sec;
Elf_Scn *strscn = dso->scn[strndx];
/* Out with the old. */
@@ -2212,8 +2524,8 @@ edit_dwarf2_any_str (DSO *dso)
but the old ebl version will just abort on out of
memory... */
strtab_finalize (strtab, strdata);
- debug_sections[DEBUG_STR].size = strdata->d_size;
- dso->strings.str_buf = strdata->d_buf;
+ secp->size = strdata->d_size;
+ strings->str_buf = strdata->d_buf;
}
static int
@@ -2359,12 +2671,14 @@ edit_dwarf2 (DSO *dso)
bool info_rel_updated = false;
bool types_rel_updated = false;
bool macro_rel_updated = false;
+ bool line_rel_updated = false;
for (phase = 0; phase < 2; phase++)
{
/* If we don't need to update anyhing, skip phase 1. */
if (phase == 1
&& !need_strp_update
+ && !need_line_strp_update
&& !need_string_replacement
&& !need_stmt_update)
break;
@@ -2582,15 +2896,14 @@ edit_dwarf2 (DSO *dso)
if (phase == 0)
{
size_t idx = read_32_relocated (ptr);
- record_existing_string_entry_idx (&dso->strings,
- idx);
+ record_existing_string_entry_idx (false, dso, idx);
}
else
{
struct stridxentry *entry;
size_t idx, new_idx;
idx = do_read_32_relocated (ptr);
- entry = string_find_entry (&dso->strings, idx);
+ entry = string_find_entry (&dso->debug_str, idx);
new_idx = strent_offset (entry->entry);
write_32_relocated (ptr, new_idx);
}
@@ -2610,24 +2923,50 @@ edit_dwarf2 (DSO *dso)
}
}
- /* Same for the debug_str section. Make sure everything is
- in place for phase 1 updating of debug_info
+
+ /* Now handle all the DWARF5 line tables, they contain strp
+ and/or line_strp entries that need to be registered/rewritten. */
+ setup_relbuf(dso, &debug_sections[DEBUG_LINE], &reltype);
+ rel_updated = false;
+
+ /* edit_dwarf2_line will have set this up, unless there are no
+ moved/resized (DWARF4) lines. In which case we can just use
+ the original section data. new_idx will have been setup
+ correctly, even if it is the same as old_idx. */
+ unsigned char *line_buf = (unsigned char *)dso->lines.line_buf;
+ if (line_buf == NULL)
+ line_buf = debug_sections[DEBUG_LINE].data;
+ for (int ldx = 0; ldx < dso->lines.used; ldx++)
+ {
+ struct line_table *t = &dso->lines.table[ldx];
+ if (t->version >= 5)
+ read_dwarf5_line (dso, line_buf + t->new_idx, t, phase);
+ }
+ if (rel_updated)
+ line_rel_updated = true;
+
+ /* Same for the debug_str and debug_line_str sections.
+ Make sure everything is in place for phase 1 updating of debug_info
references. */
if (phase == 0 && need_strp_update)
- edit_dwarf2_any_str (dso);
-
+ edit_dwarf2_any_str (dso, &dso->debug_str,
+ &debug_sections[DEBUG_STR]);
+ if (phase == 0 && need_line_strp_update)
+ edit_dwarf2_any_str (dso, &dso->debug_line_str,
+ &debug_sections[DEBUG_LINE_STR]);
}
/* After phase 1 we might have rewritten the debug_info with
new strp, strings and/or linep offsets. */
- if (need_strp_update || need_string_replacement || need_stmt_update) {
+ if (need_strp_update || need_line_strp_update
+ || need_string_replacement || need_stmt_update) {
dirty_section (DEBUG_INFO);
if (debug_sections[DEBUG_TYPES].data != NULL)
dirty_section (DEBUG_TYPES);
}
if (need_strp_update || need_stmt_update)
dirty_section (DEBUG_MACRO);
- if (need_stmt_update)
+ if (need_stmt_update || need_line_strp_update)
dirty_section (DEBUG_LINE);
/* Update any relocations addends we might have touched. */
@@ -2653,6 +2992,9 @@ edit_dwarf2 (DSO *dso)
}
}
+ if (line_rel_updated)
+ update_rela_data (dso, &debug_sections[DEBUG_LINE]);
+
return 0;
}
@@ -2745,7 +3087,8 @@ fdopen_dso (int fd, const char *name)
}
dso->filename = (const char *) strdup (name);
- setup_strings (&dso->strings);
+ setup_strings (&dso->debug_str);
+ setup_strings (&dso->debug_line_str);
setup_lines (&dso->lines);
return dso;
@@ -2753,7 +3096,8 @@ error_out:
if (dso)
{
free ((char *) dso->filename);
- destroy_strings (&dso->strings);
+ destroy_strings (&dso->debug_str);
+ destroy_strings (&dso->debug_line_str);
destroy_lines (&dso->lines);
free (dso);
}
@@ -3034,7 +3378,9 @@ main (int argc, char *argv[])
in elfutils before 0.169 we will have to update and write out all
section data if any data has changed (when ELF_F_LAYOUT was
set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */
- bool need_update = need_strp_update || need_stmt_update;
+ bool need_update = (need_strp_update
+ || need_line_strp_update
+ || need_stmt_update);
#if !_ELFUTILS_PREREQ (0, 169)
/* string replacements or build_id updates don't change section size. */
@@ -3106,10 +3452,12 @@ main (int argc, char *argv[])
GElf_Xword sec_size = shdr->sh_size;
/* We might have changed the size (and content) of the
- debug_str or debug_line section. */
+ debug_str, debug_line_str or debug_line section. */
size_t secnum = elf_ndxscn (scn);
if (secnum == debug_sections[DEBUG_STR].sec)
sec_size = debug_sections[DEBUG_STR].size;
+ if (secnum == debug_sections[DEBUG_LINE_STR].sec)
+ sec_size = debug_sections[DEBUG_LINE_STR].size;
if (secnum == debug_sections[DEBUG_LINE].sec)
sec_size = debug_sections[DEBUG_LINE].size;
@@ -3179,7 +3527,8 @@ main (int argc, char *argv[])
chmod (file, stat_buf.st_mode);
free ((char *) dso->filename);
- destroy_strings (&dso->strings);
+ destroy_strings (&dso->debug_str);
+ destroy_strings (&dso->debug_line_str);
destroy_lines (&dso->lines);
free (dso);
--
2.18.4

@ -1,18 +0,0 @@
diff --git a/rpm2cpio.c b/rpm2cpio.c
index 89ebdfa..ae999ff 100644
--- a/rpm2cpio.c
+++ b/rpm2cpio.c
@@ -84,7 +84,12 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- rc = (ufdCopy(gzdi, fdo) == payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
+ /*
+ * XXX HACK for #1142949: should be equality test, but archive size
+ * short by cpio trailer size in packages built with rpm 4.12.0
+ * and its pre-releases.
+ */
+ rc = (ufdCopy(gzdi, fdo) >= payload_size) ? EXIT_SUCCESS : EXIT_FAILURE;
Fclose(fdo);

@ -1,29 +0,0 @@
From fe274b8f965582fdf97e6c46f90b9e7c124b0b8b Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Fri, 16 Dec 2022 15:50:12 +0100
Subject: [PATCH] rpm2archive: Don't print usage on no arguments
given as we want to default to reading from stdin and writing to stdout in
that case.
---
rpm2archive.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/rpm2archive.c b/rpm2archive.c
index 09da8d16b..53f047f58 100644
--- a/rpm2archive.c
+++ b/rpm2archive.c
@@ -241,10 +241,6 @@ int main(int argc, const char *argv[])
exit(EXIT_FAILURE);
}
}
- if (argc < 2 || poptGetNextOpt(optCon) == 0) {
- poptPrintUsage(optCon, stderr, 0);
- exit(EXIT_FAILURE);
- }
rpmts ts = rpmtsCreate();
rpmVSFlags vsflags = 0;
--
2.38.1

@ -1,36 +0,0 @@
From 8f416b275a365426b07c75adfc017e0b18a85450 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Fri, 16 Dec 2022 15:45:20 +0100
Subject: [PATCH] rpm2archive: Properly parse popt options
and issue an error message for unknown options. Before unknown options
could mess up the argument parsing leading to reading and writing from
stdin/stdout.
Thanks to Eva Mrakova and the Red Hat QE team for spotting this!
---
rpm2archive.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/rpm2archive.c b/rpm2archive.c
index de1a17d2b..09da8d16b 100644
--- a/rpm2archive.c
+++ b/rpm2archive.c
@@ -233,6 +233,14 @@ int main(int argc, const char *argv[])
optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
poptSetOtherOptionHelp(optCon, "[OPTIONS]* <FILES>");
+ while ((rc = poptGetNextOpt(optCon)) != -1) {
+ if (rc < 0) {
+ fprintf(stderr, "%s: %s\n",
+ poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
+ poptStrerror(rc));
+ exit(EXIT_FAILURE);
+ }
+ }
if (argc < 2 || poptGetNextOpt(optCon) == 0) {
poptPrintUsage(optCon, stderr, 0);
exit(EXIT_FAILURE);
--
2.38.1

@ -1,15 +0,0 @@
diff -up rpm-4.9.1.1/macros.in.jx rpm-4.9.1.1/macros.in
--- rpm-4.9.1.1/macros.in.jx 2011-08-03 16:19:05.000000000 -0400
+++ rpm-4.9.1.1/macros.in 2011-08-08 09:41:52.981064316 -0400
@@ -674,9 +674,10 @@ print (t)\
RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\
RPM_OPT_FLAGS=\"%{optflags}\"\
+ RPM_LD_FLAGS=\"%{?build_ldflags}\"\
RPM_ARCH=\"%{_arch}\"\
RPM_OS=\"%{_os}\"\
RPM_BUILD_NCPUS=\"%{_smp_build_ncpus}\"\
- export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS\
+ export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_LD_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS RPM_LD_FLAGS\
RPM_DOC_DIR=\"%{_docdir}\"\
export RPM_DOC_DIR\
RPM_PACKAGE_NAME=\"%{NAME}\"\

@ -1,12 +0,0 @@
diff -up rpm-4.11.1-rc1/macros.in.siteconfig rpm-4.11.1-rc1/macros.in
--- rpm-4.11.1-rc1/macros.in.siteconfig 2013-06-07 13:19:21.000000000 +0300
+++ rpm-4.11.1-rc1/macros.in 2013-06-11 15:06:59.525747503 +0300
@@ -647,6 +647,8 @@ package or when debugging this package.\
export CLASSPATH}\
PKG_CONFIG_PATH=\"${PKG_CONFIG_PATH}:%{_libdir}/pkgconfig:%{_datadir}/pkgconfig\"\
export PKG_CONFIG_PATH\
+ CONFIG_SITE=${CONFIG_SITE:-NONE}\
+ export CONFIG_SITE\
\
%{verbose:set -x}\
umask 022\

@ -1,36 +0,0 @@
From 7f0b7217fb1c20ec6ce0c0e0bfee0349f27a2511 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 8 Jan 2021 13:59:59 +0200
Subject: [PATCH] Ensure ELF files get stripped when debuginfo is disabled
Depending on libmagic version, PIE executables can be reported as
"shared object" avoiding the strip. And so will any libraries because
we're explicitly skipping them for whatever historical reason - perhaps
because there's a separate script for stripping the libraries, but that
has been never enabled in rpm, and relying on "file" strings to do this
is hopelessly unreliable.
Also drop file permissions checks: making shared libraries executable
just to have them stripped is not sensical, especially in the light of
commit 80818e4f902ba3cf85e4cfcd8a7a4c71c601f3cf
Reported once upon time as RhBug:988812 and later RhBug:1634084
---
scripts/brp-strip | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/brp-strip b/scripts/brp-strip
index c3484fe3c..35fbb593a 100755
--- a/scripts/brp-strip
+++ b/scripts/brp-strip
@@ -13,5 +13,5 @@ Darwin*) exit 0 ;;
esac
# Strip ELF binaries
-find "$RPM_BUILD_ROOT" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \! -regex "${RPM_BUILD_ROOT}/*usr/lib/debug.*" -print0 | \
- xargs -0 -r -P$NCPUS -n32 sh -c "file \"\$@\" | grep -v ' shared object,' | sed -n -e 's/^\(.*\):[ ]*ELF.*, not stripped.*/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0
+find "$RPM_BUILD_ROOT" -type f \! -regex "${RPM_BUILD_ROOT}/*usr/lib/debug.*" -print0 | \
+ xargs -0 -r -P$NCPUS -n32 sh -c "file \"\$@\" | sed -n -e 's/^\(.*\):[ ]*ELF.*, not stripped.*/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0
--
2.33.1

@ -1,41 +0,0 @@
Based on
From 7db2efa95d859cebda2b095ffdffac42812bd6d9 Mon Sep 17 00:00:00 2001
From: Darren Kenny <darren.kenny@oracle.com>
Date: Tue, 22 Feb 2022 16:57:00 +0000
Subject: [PATCH] ima: Install on filesystems without xattr support without
failing
If an RPM contains IMA signed digests and rpm-plugin-ima is installed,
then any attempt to install to a filesystem that doesn't support
extended attributes will cause the RPM installation to fail.
This can be seen, for example, if installing a file /boot, which is
usually a vFAT filesystem.
The rpm-plugin for selinux fixed this some time back, and that same
logic can be applied to IMA too - where, if a failure to set an extended
attribute results in an errno that is set to EOPNOTSUPP, then this
should not cause a complete failure, but should instead just be logged
at a debug level.
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
--- rpm-4.16.1.3/plugins/ima.c.orig 2023-05-02 18:19:25.095992859 +0200
+++ rpm-4.16.1.3/plugins/ima.c 2023-05-02 18:21:46.032941008 +0200
@@ -69,10 +69,13 @@
fsig = rpmfiFSignature(fi, &len);
if (fsig && (check_zero_hdr(fsig, len) == 0)) {
if (lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0) < 0) {
- rpmlog(RPMLOG_ERR,
+ int is_err = errno != EOPNOTSUPP;
+ rpmlog(is_err?RPMLOG_ERR:RPMLOG_DEBUG,
"ima: could not apply signature on '%s': %s\n",
path, strerror(errno));
- rc = RPMRC_FAIL;
+ if (is_err) {
+ rc = RPMRC_FAIL;
+ }
}
}

@ -1,57 +0,0 @@
diff --git a/scripts/rpm2cpio.sh b/scripts/rpm2cpio.sh
index 4531271cc..74aeed851 100755
--- a/scripts/rpm2cpio.sh
+++ b/scripts/rpm2cpio.sh
@@ -15,13 +15,23 @@ _dd() {
}
calcsize() {
+
+ case "$(_dd $1 bs=4 count=1 | tr -d '\0')" in
+ "$(printf '\216\255\350')"*) ;; # '\x8e\xad\xe8'
+ *) fatal "File doesn't look like rpm: $pkg" ;;
+ esac
+
offset=$(($1 + 8))
local i b b0 b1 b2 b3 b4 b5 b6 b7
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")"
@@ -33,7 +43,7 @@ calcsize() {
offset=$(($offset + $rsize))
}
-case "$(_dd 0 bs=8 count=1)" 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
@@ -44,11 +54,11 @@ sigsize=$rsize
calcsize $(($offset + (8 - ($sigsize % 8)) % 8))
hdrsize=$rsize
-case "$(_dd $offset bs=3 count=1)" 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'
- "$(printf '\135\000')"*) _dd $offset | unlzma ;; # '\x5d\x00'
- "$(printf '\050\265')"*) _dd $offset | unzstd ;; # '\x28\xb5'
- *) fatal "Unrecognized rpm file: $pkg" ;;
+case "$(_dd $offset bs=2 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'
+ "$(printf '\135')") _dd $offset | unlzma ;; # '\x5d\x00'
+ "$(printf '\050\265')") _dd $offset | unzstd ;; # '\x28\xb5'
+ *) fatal "Unrecognized payload compression format in rpm file: $pkg" ;;
esac

@ -1,40 +0,0 @@
From 35739c2a2298e61caacb45157706bf342ffcd20e Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Tue, 27 Apr 2021 10:09:41 +0200
Subject: [PATCH] find-lang.sh: Support long languages names for QT
Most language abbreviations are just two characters but some are longer.
Allow an arbiraty number of character instead of exactly two in the names
of .qm files (QT translations). This brings the handling of .qm files in
line with all other file types.
Resolves: #1642
---
scripts/find-lang.sh | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/scripts/find-lang.sh b/scripts/find-lang.sh
index f2aa7d8951..b97210b117 100755
--- a/scripts/find-lang.sh
+++ b/scripts/find-lang.sh
@@ -249,13 +249,13 @@ s:%lang(C) ::
find "$TOP_DIR" -type f -o -type l|sed '
s:'"$TOP_DIR"'::
-'"$NO_ALL_NAME$QT"'s:\(.*/'"$NAME"'_\([a-zA-Z]\{2\}\([_@].*\)\?\)\.qm$\):%lang(\2) \1:
-'"$ALL_NAME$QT"'s:^\([^%].*/\([a-zA-Z]\{2\}[_@].*\)\.qm$\):%lang(\2) \1:
-'"$ALL_NAME$QT"'s:^\([^%].*/\([a-zA-Z]\{2\}\)\.qm$\):%lang(\2) \1:
-'"$ALL_NAME$QT"'s:^\([^%].*/[^/_]\+_\([a-zA-Z]\{2\}[_@].*\)\.qm$\):%lang(\2) \1:
-'"$ALL_NAME$QT"'s:^\([^%].*/[^/_]\+_\([a-zA-Z]\{2\}\)\.qm$\):%lang(\2) \1:
-'"$ALL_NAME$QT"'s:^\([^%].*/[^/]\+_\([a-zA-Z]\{2\}[_@].*\)\.qm$\):%lang(\2) \1:
-'"$ALL_NAME$QT"'s:^\([^%].*/[^/]\+_\([a-zA-Z]\{2\}\)\.qm$\):%lang(\2) \1:
+'"$NO_ALL_NAME$QT"'s:\(.*/'"$NAME"'_\([a-zA-Z]\+\([_@].*\)\?\)\.qm$\):%lang(\2) \1:
+'"$ALL_NAME$QT"'s:^\([^%].*/\([a-zA-Z]\+[_@].*\)\.qm$\):%lang(\2) \1:
+'"$ALL_NAME$QT"'s:^\([^%].*/\([a-zA-Z]\+\)\.qm$\):%lang(\2) \1:
+'"$ALL_NAME$QT"'s:^\([^%].*/[^/_]\+_\([a-zA-Z]\+[_@].*\)\.qm$\):%lang(\2) \1:
+'"$ALL_NAME$QT"'s:^\([^%].*/[^/_]\+_\([a-zA-Z]\+\)\.qm$\):%lang(\2) \1:
+'"$ALL_NAME$QT"'s:^\([^%].*/[^/]\+_\([a-zA-Z]\+[_@].*\)\.qm$\):%lang(\2) \1:
+'"$ALL_NAME$QT"'s:^\([^%].*/[^/]\+_\([a-zA-Z]\+\)\.qm$\):%lang(\2) \1:
s:^[^%].*::
s:%lang(C) ::
/^$/d' >> $MO_NAME

@ -1,334 +0,0 @@
commit 39595ccee321497dc3b08c7cab8a10304345429c
Author: Radovan Sroka <rsroka@redhat.com>
Date: Tue Oct 27 16:18:04 2020 +0100
Added fapolicyd rpm plugin
Fapolicyd (File Access Policy Daemon) implements application whitelisting
to decide file access rights. Applications that are known via a reputation
source are allowed access while unknown applications are not.
The rpm plugin allows us to use rpm database as a source of trust.
We used dnf plugin since the beggining but it only provides notification
when transaction ends. With "integrity checking" requirement we need
a continual addition of files which are installed during the system
update. With fapolicyd rpm plugin we can allow using of recently
added/updated files in scriptlets during rpm transaction.
The fapolicyd plugin gathers metadata of currently installed files.
It sends the information about files and about ongoing rpm transaction
to the fapolicyd daemon. The information is written to Linux pipe which
is placed in /var/run/fapolicyd/fapolicyd.fifo.
The data format is "%s %lu %64s\n". [path, size, sha256]
The fapolicyd rpm plugin can be enabled with "--with-fapolicyd"
configure option.
Related PRs:
https://github.com/linux-application-whitelisting/fapolicyd/pull/105
https://github.com/linux-application-whitelisting/fapolicyd/pull/106
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
Backported into 4.16.1.3, together with commit
6d61b7118adcc14631b7ee5163a481472af940b8 (covscan fix)
diff -up rpm-4.16.1.3/configure.ac.orig rpm-4.16.1.3/configure.ac
--- rpm-4.16.1.3/configure.ac.orig 2021-03-22 11:05:07.311635968 +0100
+++ rpm-4.16.1.3/configure.ac 2021-07-22 16:18:29.352006782 +0200
@@ -891,6 +891,14 @@ AS_IF([test "$enable_plugins" != no],[
AM_CONDITIONAL(IMA, [test "x$ac_cv_func_lsetxattr" = xyes])
#=================
+# Check for fapolicyd support
+AC_ARG_WITH(fapolicyd,
+AS_HELP_STRING([--with-fapolicyd],[build with File Access Policy Daemon support]),
+with_fapolicyd=$withval,
+with_fapolicyd=auto)
+AM_CONDITIONAL(FAPOLICYD,[test "$with_fapolicyd" = yes])
+
+#=================
# Check for audit library.
AC_ARG_WITH(audit,
AS_HELP_STRING([--with-audit],[Linux audit plugin]),
diff -up rpm-4.16.1.3/doc/Makefile.am.orig rpm-4.16.1.3/doc/Makefile.am
--- rpm-4.16.1.3/doc/Makefile.am.orig 2020-06-23 14:13:01.895628382 +0200
+++ rpm-4.16.1.3/doc/Makefile.am 2021-07-22 16:18:29.352006782 +0200
@@ -25,6 +25,9 @@ endif
if IMA
man_man8_DATA += rpm-plugin-ima.8
endif
+if FAPOLICYD
+man_man8_DATA += rpm-plugin-fapolicyd.8
+endif
if SELINUX
man_man8_DATA += rpm-plugin-selinux.8
endif
@@ -37,6 +40,8 @@ endif
EXTRA_DIST += rpm-plugins.8 rpm-plugin-prioreset.8 rpm-plugin-syslog.8
EXTRA_DIST += rpm-plugin-audit.8 rpm-plugin-systemd-inhibit.8
EXTRA_DIST += rpm-plugin-ima.8 rpm-plugin-selinux.8 rpm2archive.8
+EXTRA_DIST += rpm-plugin-fapolicyd.8
+
man_fr_man8dir = $(mandir)/fr/man8
man_fr_man8_DATA = fr/rpm.8
diff -up rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8
--- rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig 2021-07-22 16:18:29.353006800 +0200
+++ rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8 2021-07-22 16:18:29.353006800 +0200
@@ -0,0 +1,21 @@
+'\" t
+.TH "RPM-FAPOLICYD" "8" "28 Jan 2021" "Red Hat, Inc."
+.SH NAME
+rpm-plugin-fapolicyd \- Fapolicyd plugin for the RPM Package Manager
+
+.SH Description
+
+The plugin gathers metadata of currently installed files. It sends the
+information about files and about ongoing rpm transaction to the fapolicyd daemon.
+The information is written to Linux pipe which is placed in
+/var/run/fapolicyd/fapolicyd.fifo.
+
+.SH Configuration
+
+There are currently no options for this plugin in particular. See
+.BR rpm-plugins (8)
+on how to control plugins in general.
+
+.SH SEE ALSO
+.IR fapolicyd (8)
+.IR rpm-plugins (8)
diff -up rpm-4.16.1.3/macros.in.orig rpm-4.16.1.3/macros.in
--- rpm-4.16.1.3/macros.in.orig 2021-07-22 16:18:20.525844141 +0200
+++ rpm-4.16.1.3/macros.in 2021-07-22 16:19:36.196238525 +0200
@@ -1208,6 +1208,7 @@ package or when debugging this package.\
%__transaction_selinux %{__plugindir}/selinux.so
%__transaction_syslog %{__plugindir}/syslog.so
%__transaction_ima %{__plugindir}/ima.so
+%__transaction_fapolicyd %{__plugindir}/fapolicyd.so
%__transaction_prioreset %{__plugindir}/prioreset.so
%__transaction_audit %{__plugindir}/audit.so
diff -up rpm-4.16.1.3/Makefile.am.orig rpm-4.16.1.3/Makefile.am
--- rpm-4.16.1.3/Makefile.am.orig 2021-07-22 16:18:29.350006745 +0200
+++ rpm-4.16.1.3/Makefile.am 2021-07-22 16:19:18.223907346 +0200
@@ -14,6 +14,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
--with-audit \
--with-selinux \
--with-imaevm \
+ --with-fapolicyd \
--disable-dependency-tracking
include $(top_srcdir)/rpm.am
diff -up rpm-4.16.1.3/plugins/fapolicyd.c.orig rpm-4.16.1.3/plugins/fapolicyd.c
--- rpm-4.16.1.3/plugins/fapolicyd.c.orig 2021-07-22 16:18:29.356006855 +0200
+++ rpm-4.16.1.3/plugins/fapolicyd.c 2021-07-22 16:18:35.380117862 +0200
@@ -0,0 +1,191 @@
+#include "system.h"
+
+#include <rpm/rpmts.h>
+#include <rpm/rpmlog.h>
+#include "lib/rpmplugin.h"
+
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+struct fapolicyd_data {
+ int fd;
+ long changed_files;
+ const char * fifo_path;
+};
+
+static struct fapolicyd_data fapolicyd_state = {
+ .fd = -1,
+ .changed_files = 0,
+ .fifo_path = "/run/fapolicyd/fapolicyd.fifo",
+};
+
+static rpmRC open_fifo(struct fapolicyd_data* state)
+{
+ int fd = -1;
+ struct stat s;
+
+ fd = open(state->fifo_path, O_RDWR);
+ if (fd == -1) {
+ rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
+ goto bad;
+ }
+
+ if (stat(state->fifo_path, &s) == -1) {
+ rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno));
+ goto bad;
+ }
+
+ if (!S_ISFIFO(s.st_mode)) {
+ rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path);
+ goto bad;
+ }
+
+ /* keep only file's permition bits */
+ mode_t mode = s.st_mode & ~S_IFMT;
+
+ /* we require pipe to have 0660 permission */
+ if (mode != 0660) {
+ rpmlog(RPMLOG_ERR, "File: %s has %o instead of 0660 \n",
+ state->fifo_path,
+ mode );
+ goto bad;
+ }
+
+ state->fd = fd;
+ /* considering success */
+ return RPMRC_OK;
+
+ bad:
+ if (fd >= 0)
+ close(fd);
+ return RPMRC_FAIL;
+}
+
+static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
+{
+ ssize_t len = strlen(str);
+ ssize_t written = 0;
+ ssize_t n = 0;
+
+ while (written < len) {
+ if ((n = write(state->fd, str + written, len - written)) < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ rpmlog(RPMLOG_DEBUG, "Write: %s -> %s\n", state->fifo_path, strerror(errno));
+ goto bad;
+ }
+ written += n;
+ }
+
+ return RPMRC_OK;
+
+ bad:
+ return RPMRC_FAIL;
+}
+
+static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
+{
+ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
+ goto end;
+
+ if (!rstreq(rpmtsRootDir(ts), "/"))
+ goto end;
+
+ (void) open_fifo(&fapolicyd_state);
+
+ end:
+ return RPMRC_OK;
+}
+
+static void fapolicyd_cleanup(rpmPlugin plugin)
+{
+ if (fapolicyd_state.fd > 0)
+ (void) close(fapolicyd_state.fd);
+
+ fapolicyd_state.fd = -1;
+}
+
+static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
+{
+ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
+ goto end;
+
+ /* we are ready */
+ if (fapolicyd_state.fd > 0) {
+ /* send a signal that transaction is over */
+ (void) write_fifo(&fapolicyd_state, "1\n");
+ /* flush cache */
+ (void) write_fifo(&fapolicyd_state, "2\n");
+ }
+
+ end:
+ return RPMRC_OK;
+}
+
+static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
+ int type)
+{
+ if (fapolicyd_state.fd == -1)
+ goto end;
+
+ if (fapolicyd_state.changed_files > 0) {
+ /* send signal to flush cache */
+ (void) write_fifo(&fapolicyd_state, "2\n");
+
+ /* optimize flushing */
+ /* flush only when there was an actual change */
+ fapolicyd_state.changed_files = 0;
+ }
+
+ end:
+ return RPMRC_OK;
+}
+
+static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
+ const char *path, const char *dest,
+ mode_t file_mode, rpmFsmOp op)
+{
+ /* not ready */
+ if (fapolicyd_state.fd == -1)
+ goto end;
+
+ rpmFileAction action = XFO_ACTION(op);
+
+ /* Ignore skipped files and unowned directories */
+ if (XFA_SKIPPING(action) || (op & FAF_UNOWNED)) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping early: path %s dest %s\n",
+ path, dest);
+ goto end;
+ }
+
+ if (!S_ISREG(rpmfiFMode(fi))) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping non regular: path %s dest %s\n",
+ path, dest);
+ goto end;
+ }
+
+ fapolicyd_state.changed_files++;
+
+ char buffer[4096];
+
+ rpm_loff_t size = rpmfiFSize(fi);
+ char * sha = rpmfiFDigestHex(fi, NULL);
+
+ snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
+ (void) write_fifo(&fapolicyd_state, buffer);
+
+ free(sha);
+
+ end:
+ return RPMRC_OK;
+}
+
+struct rpmPluginHooks_s fapolicyd_hooks = {
+ .init = fapolicyd_init,
+ .cleanup = fapolicyd_cleanup,
+ .scriptlet_pre = fapolicyd_scriptlet_pre,
+ .tsm_post = fapolicyd_tsm_post,
+ .fsm_file_prepare = fapolicyd_fsm_file_prepare,
+};
diff -up rpm-4.16.1.3/plugins/Makefile.am.orig rpm-4.16.1.3/plugins/Makefile.am
--- rpm-4.16.1.3/plugins/Makefile.am.orig 2021-07-22 16:18:23.022890155 +0200
+++ rpm-4.16.1.3/plugins/Makefile.am 2021-07-22 16:18:55.797494098 +0200
@@ -43,6 +43,12 @@ ima_la_LIBADD = $(top_builddir)/lib/libr
plugins_LTLIBRARIES += ima.la
endif
+if FAPOLICYD
+fapolicyd_la_sources = fapolicyd.c
+fapolicyd_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
+plugins_LTLIBRARIES += fapolicyd.la
+endif
+
if AUDIT
audit_la_sources = audit.c
audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@

@ -1,197 +0,0 @@
From ba659220886c1a315f50fb91b9af4615b1a8757e Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 16 Aug 2021 18:21:02 +0200
Subject: [PATCH] Add support for RPMDBI_BASENAMES on file queries
There are legitimate reasons (such as rhbz#1940895 or the included test)
for wanting the former behavior where all file states were considered in
file queries prior to commit 9ad57bda4a82b9847826daa766b4421d877bb3d9,
so celebrate the tenth anniversary of that commit by adding a CLI switch
(a new package selector --path), as contemplated back then.
Update the man page for --file to reflect it's current behavior and make
--path that more obvious.
Resolves: rhbz#1940895
Combined with:
d1aebda01033bc8ba0d748b49f6fad9a5c0caa3f
f62b6d27cd741406a52a7e9c5b1d6f581dbd3af8
Backported for 4.16.1.3.
---
doc/rpm.8 | 9 ++++++--
lib/poptQV.c | 6 +++++-
lib/query.c | 7 +++++--
lib/rpmcli.h | 1 +
tests/rpmquery.at | 52 +++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/doc/rpm.8 b/doc/rpm.8
index 80055b675..ab7364cf6 100644
--- a/doc/rpm.8
+++ b/doc/rpm.8
@@ -57,7 +57,7 @@ rpm \- RPM Package Manager
.PP
[\fB\fIPACKAGE_NAME\fB\fR]
- [\fB-a,--all [\fISELECTOR\fR]\fR] [\fB-f,--file \fIFILE\fB\fR]
+ [\fB-a,--all [\fISELECTOR\fR]\fR] [\fB-f,--file \fIFILE\fB\fR] [\fB--path \fIPATH\fB\fR]
[\fB-g,--group \fIGROUP\fB\fR] [\fB-p,--package \fIPACKAGE_FILE\fB\fR]
[\fB--hdrid \fISHA1\fB\fR] [\fB--pkgid \fIMD5\fB\fR] [\fB--tid \fITID\fB\fR]
[\fB--querybynumber \fIHDRNUM\fB\fR] [\fB--triggeredby \fIPACKAGE_NAME\fB\fR]
@@ -569,7 +569,7 @@ starts with "b".
List duplicated packages.
.TP
\fB-f, --file \fIFILE\fB\fR
-Query package owning \fIFILE\fR.
+Query package owning installed \fIFILE\fR.
.TP
\fB--filecaps\fR
List file names with POSIX1.e capabilities.
@@ -612,6 +612,11 @@ that will be expanded to paths that are substituted in place of
the package manifest as additional \fIPACKAGE_FILE\fR
arguments to the query.
.TP
+\fB--path \fIPATH\fB\fR
+Query package(s) owning \fIPATH\fR, whether the file is installed or not.
+Multiple packages may own a \fIPATH\fR, but the file is only owned by the
+package installed last.
+.TP
\fB--pkgid \fIMD5\fB\fR
Query package that contains a given package identifier, i.e. the
\fIMD5\fR digest of the combined header and
diff --git a/lib/poptQV.c b/lib/poptQV.c
index d9d1fad75..9b6101009 100644
--- a/lib/poptQV.c
+++ b/lib/poptQV.c
@@ -27,6 +27,7 @@ struct rpmQVKArguments_s rpmQVKArgs;
#define POPT_WHATENHANCES -1014
#define POPT_WHATOBSOLETES -1015
#define POPT_WHATCONFLICTS -1016
+#define POPT_QUERYBYPATH -1017
/* ========== Query/Verify/Signature source args */
static void rpmQVSourceArgCallback( poptContext con,
@@ -58,6 +59,7 @@ static void rpmQVSourceArgCallback( poptContext con,
case POPT_WHATSUPPLEMENTS: qva->qva_source |= RPMQV_WHATSUPPLEMENTS; break;
case POPT_WHATENHANCES: qva->qva_source |= RPMQV_WHATENHANCES; break;
case POPT_TRIGGEREDBY: qva->qva_source |= RPMQV_TRIGGEREDBY; break;
+ case POPT_QUERYBYPATH: qva->qva_source |= RPMQV_PATH_ALL; break;
case POPT_QUERYBYPKGID: qva->qva_source |= RPMQV_PKGID; break;
case POPT_QUERYBYHDRID: qva->qva_source |= RPMQV_HDRID; break;
case POPT_QUERYBYTID: qva->qva_source |= RPMQV_TID; break;
@@ -80,7 +82,9 @@ struct poptOption rpmQVSourcePoptTable[] = {
{ "checksig", 'K', POPT_ARGFLAG_DOC_HIDDEN, NULL, 'K',
N_("rpm checksig mode"), NULL },
{ "file", 'f', 0, 0, 'f',
- N_("query/verify package(s) owning file"), "FILE" },
+ N_("query/verify package(s) owning installed file"), "FILE" },
+ { "path", '\0', 0, 0, POPT_QUERYBYPATH,
+ N_("query/verify package(s) owning path, installed or not"), "PATH" },
{ "group", 'g', 0, 0, 'g',
N_("query/verify package(s) in group"), "GROUP" },
{ "package", 'p', 0, 0, 'p',
diff --git a/lib/query.c b/lib/query.c
index fdabe6e52..9a71f0dc5 100644
--- a/lib/query.c
+++ b/lib/query.c
@@ -445,6 +445,7 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
}
/* fallthrough on absolute and relative paths */
case RPMQV_PATH:
+ case RPMQV_PATH_ALL:
{ char * fn;
for (s = arg; *s != '\0'; s++)
@@ -463,8 +464,10 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
fn = xstrdup(arg);
(void) rpmCleanPath(fn);
- /* XXX Add a switch to enable former BASENAMES behavior? */
- mi = rpmtsInitIterator(ts, RPMDBI_INSTFILENAMES, fn, 0);
+ rpmDbiTagVal tag = RPMDBI_INSTFILENAMES;
+ if (qva->qva_source == RPMQV_PATH_ALL)
+ tag = RPMDBI_BASENAMES;
+ mi = rpmtsInitIterator(ts, tag, fn, 0);
if (mi == NULL)
mi = rpmtsInitIterator(ts, RPMDBI_PROVIDENAME, fn, 0);
diff --git a/lib/rpmcli.h b/lib/rpmcli.h
index 4886c2453..3961418e7 100644
--- a/lib/rpmcli.h
+++ b/lib/rpmcli.h
@@ -101,6 +101,7 @@ enum rpmQVSources_e {
RPMQV_SPECBUILTRPMS, /*!< ... from pkgs which would be built from spec */
RPMQV_WHATOBSOLETES, /*!< ... from obsoletes db search. */
RPMQV_WHATCONFLICTS, /*!< ... from conflicts db search. */
+ RPMQV_PATH_ALL, /*!< ... from file path db search (all states). */
};
typedef rpmFlags rpmQVSources;
diff --git a/tests/rpmquery.at b/tests/rpmquery.at
index 9a4f1cb76..335d5ee0d 100644
--- a/tests/rpmquery.at
+++ b/tests/rpmquery.at
@@ -201,6 +201,58 @@ runroot rpm \
AT_CLEANUP
+# ------------------------------
+# query a package by a file
+AT_SETUP([rpm -qf])
+AT_KEYWORDS([query])
+AT_CHECK([
+RPMDB_INIT
+runroot rpm \
+ --nodeps \
+ -i /data/RPMS/hello-1.0-1.i386.rpm
+runroot rpm \
+ -qf /usr/local/bin/hello
+],
+[0],
+[hello-1.0-1.i386
+],
+[])
+AT_CLEANUP
+
+AT_SETUP([rpm -qf on non-installed file])
+AT_KEYWORDS([query])
+AT_CHECK([
+RPMDB_INIT
+runroot rpm \
+ --nodeps \
+ --excludedocs \
+ -i /data/RPMS/hello-1.0-1.i386.rpm
+runroot rpm \
+ -qf /usr/share/doc/hello-1.0/FAQ
+],
+[1],
+[],
+[error: file /usr/share/doc/hello-1.0/FAQ: No such file or directory
+])
+AT_CLEANUP
+
+AT_SETUP([rpm -q --path on non-installed file])
+AT_KEYWORDS([query])
+AT_CHECK([
+RPMDB_INIT
+runroot rpm \
+ --nodeps \
+ --excludedocs \
+ -i /data/RPMS/hello-1.0-1.i386.rpm
+runroot rpm \
+ -q --path /usr/share/doc/hello-1.0/FAQ
+],
+[0],
+[hello-1.0-1.i386
+],
+[])
+AT_CLEANUP
+
# ------------------------------
AT_SETUP([integer array query])
AT_KEYWORDS([query])
--
2.35.1

@ -1,217 +0,0 @@
From 7b1fc619a5c828828dad7c1f61f525d957b9e2c5 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Wed, 27 Jan 2021 17:32:51 +0100
Subject: [PATCH] Add %bcond macro for defining build conditionals
Move documentation from comments to reference manual
Fixes: https://github.com/rpm-software-management/rpm/issues/941
(cherry picked from commit a99b6373af0774f4bef62aa89defc84cfcacc078)
---
macros.in | 54 +++++++----------------
tests/Makefile.am | 1 +
tests/data/SPECS/bcondtest.spec | 33 +++++++++++++++
tests/rpmbuild.at | 73 ++++++++++++++++++++++++++++++++
5 files changed, 157 insertions(+), 42 deletions(-)
create mode 100644 tests/data/SPECS/bcondtest.spec
diff --git a/macros.in b/macros.in
index 7c458f5d8a..35462c933c 100644
--- a/macros.in
+++ b/macros.in
@@ -78,47 +78,25 @@
%defined() %{expand:%%{?%{1}:1}%%{!?%{1}:0}}
%undefined() %{expand:%%{?%{1}:0}%%{!?%{1}:1}}
-# Shorthand for %{defined with_...}
+# Handle conditional builds.
+# (see 'conditionalbuilds' in the manual)
+#
+# Internally, the `--with foo` option defines the macro `_with_foo` and the
+# `--without foo` option defines the macro `_without_foo`.
+# Based on those and a default (used when neither is given), bcond macros
+# define the macro `with_foo`, which should later be checked:
+
+%bcond() %[ (%2)\
+ ? "%{expand:%%{!?_without_%{1}:%%global with_%{1} 1}}"\
+ : "%{expand:%%{?_with_%{1}:%%global with_%{1} 1}}"\
+]
+%bcond_with() %bcond %{1} 0
+%bcond_without() %bcond %{1} 1
+
+# Shorthands for %{defined with_...}:
%with() %{expand:%%{?with_%{1}:1}%%{!?with_%{1}:0}}
%without() %{expand:%%{?with_%{1}:0}%%{!?with_%{1}:1}}
-# Handle conditional builds. %bcond_with is for case when feature is
-# default off and needs to be activated with --with ... command line
-# switch. %bcond_without is for the dual case.
-#
-# %bcond_with foo defines symbol with_foo if --with foo was specified on
-# command line.
-# %bcond_without foo defines symbol with_foo if --without foo was *not*
-# specified on command line.
-#
-# For example (spec file):
-#
-# (at the beginning)
-# %bcond_with extra_fonts
-# %bcond_without static
-# (and later)
-# %if %{with extra_fonts}
-# ...
-# %else
-# ...
-# %endif
-# %if ! %{with static}
-# ...
-# %endif
-# %if %{with static}
-# ...
-# %endif
-# %{?with_static: ... }
-# %{!?with_static: ... }
-# %{?with_extra_fonts: ... }
-# %{!?with_extra_fonts: ... }
-
-#
-# The bottom line: never use without_foo, _with_foo nor _without_foo, only
-# with_foo. This way changing default set of bconds for given spec is just
-# a matter of changing single line in it and syntax is more readable.
-%bcond_with() %{expand:%%{?_with_%{1}:%%global with_%{1} 1}}
-%bcond_without() %{expand:%%{!?_without_%{1}:%%global with_%{1} 1}}
#
#==============================================================================
# ---- Required rpmrc macros.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 66cee3273b..6d41ef93c5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -40,6 +40,7 @@ EXTRA_DIST += $(TESTSUITE_AT)
## testsuite data
EXTRA_DIST += data/SPECS/attrtest.spec
+EXTRA_DIST += data/SPECS/bcondtest.spec
EXTRA_DIST += data/SPECS/buildrequires.spec
EXTRA_DIST += data/SPECS/docmiss.spec
EXTRA_DIST += data/SPECS/hello.spec
diff --git a/tests/data/SPECS/bcondtest.spec b/tests/data/SPECS/bcondtest.spec
new file mode 100644
index 0000000000..7172a31d29
--- /dev/null
+++ b/tests/data/SPECS/bcondtest.spec
@@ -0,0 +1,33 @@
+Name: bcondtest
+Version: 1.0
+Release: 1
+Group: Testing
+License: CC0
+BuildArch: noarch
+Summary: Test package for the bcond macro
+
+%bcond normally_on 1
+%bcond normally_off 0
+%bcond both_features %[%{with normally_on} && %{with normally_off}]
+
+%if %{with normally_on}
+Provides: has_bcond(normally_on)
+%endif
+%if %{with normally_off}
+Provides: has_bcond(normally_off)
+%endif
+%if %{with both_features}
+Provides: has_bcond(both_features)
+%endif
+
+%description
+%{summary}
+
+%install
+mkdir -p %{buildroot}/opt
+touch %{buildroot}/opt/file
+
+%files
+/opt/file
+
+%changelog
diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at
index 30d8e6895d..f378a4af2a 100644
--- a/tests/rpmbuild.at
+++ b/tests/rpmbuild.at
@@ -1801,3 +1801,76 @@ runroot rpmbuild -ba --quiet \
[],
[])
AT_CLEANUP
+
+AT_SETUP([bcond macro])
+AT_KEYWORDS([bcond build])
+RPMDB_INIT
+
+# basic bcond behavior with --eval
+AT_CHECK([
+runroot rpm \
+ --eval "%bcond normally_on 1" \
+ --eval "%bcond normally_off 0" \
+ --eval "%bcond both_features %[[%{with normally_on} && %{with normally_off}]]" \
+ --eval "%{with normally_on}" \
+ --eval "%{with normally_off}" \
+ --eval "%{with both_features}"
+],
+[0],
+[
+
+
+1
+0
+0
+],
+[])
+
+# bcond behavior, without CLI options
+AT_CHECK([
+runroot rpmbuild -bb --quiet /data/SPECS/bcondtest.spec
+runroot rpm -q --provides -p /build/RPMS/noarch/bcondtest-1.0-1.noarch.rpm |
+ grep has_bcond | sort
+],
+[0],
+[has_bcond(normally_on)
+],
+[])
+
+# bcond behavior, --with
+AT_CHECK([
+runroot rpmbuild -bb --quiet --with normally_on --with normally_off \
+ /data/SPECS/bcondtest.spec
+runroot rpm -q --provides -p /build/RPMS/noarch/bcondtest-1.0-1.noarch.rpm |
+ grep has_bcond | sort
+],
+[0],
+[has_bcond(both_features)
+has_bcond(normally_off)
+has_bcond(normally_on)
+],
+[])
+
+# bcond behavior, --without
+AT_CHECK([
+runroot rpmbuild -bb --quiet --without normally_on --without normally_off \
+ /data/SPECS/bcondtest.spec
+runroot rpm -q --provides -p /build/RPMS/noarch/bcondtest-1.0-1.noarch.rpm |
+ grep has_bcond | sort
+],
+[0],
+[],
+[])
+
+# bcond behavior, CLI overriding a complex defailt
+AT_CHECK([
+runroot rpmbuild -bb --quiet --with both_features /data/SPECS/bcondtest.spec
+runroot rpm -q --provides -p /build/RPMS/noarch/bcondtest-1.0-1.noarch.rpm |
+ grep has_bcond | sort
+],
+[0],
+[has_bcond(both_features)
+has_bcond(normally_on)
+],
+[])
+AT_CLEANUP

@ -1,32 +0,0 @@
From a26f6655546158153807017e7ded2aff5e4e10e4 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 31 Jan 2022 11:13:35 +0200
Subject: [PATCH] Bump hash for rpmdb cookie to SHA256 to appease FIPS
The rpmdb cookie is not a security feature, but as these existing
hashes are more convenient than coming up with our own... we then
run into the great big wall of FIPS which in its current incarnation
disallows use of SHA1. And so rpmdbCookie() fails under current FIPS.
Just bumping the algorithm to SHA256 seems the path of lowest
resistance, whether that algo makes sense for this purpose or not.
---
lib/rpmdb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 01d49a641..00bd4236f 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -2642,7 +2642,7 @@ char *rpmdbCookie(rpmdb db)
rpmdbIndexIterator ii = rpmdbIndexIteratorInit(db, RPMDBI_NAME);
if (ii) {
- DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
+ DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA256, RPMDIGEST_NONE);
const void *key = 0;
size_t keylen = 0;
while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) {
--
2.34.1

@ -1,24 +0,0 @@
From 4420c78beb86cc67392274bf351478a3375626a2 Mon Sep 17 00:00:00 2001
From: yangchenguang <89123114+yangchenguang94@users.noreply.github.com>
Date: Wed, 13 Jul 2022 16:52:07 +0800
Subject: [PATCH] Fix query arguments with ^ not working
when querying packages in the RPM database.
Rersolves: #2104
---
lib/rpmdb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index fa8f3c9b9c..fd2b0671ae 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -1133,6 +1133,7 @@ static char * mireDup(rpmTagVal tag, rpmMireMode *modep,
switch (*s) {
case '.':
case '+':
+ case '^':
if (!brackets) *t++ = '\\';
break;
case '*':

@ -1,24 +0,0 @@
From 19d73f67883c011cc74326a5dc34f7009efa60e1 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 6 Sep 2022 13:15:44 +0300
Subject: [PATCH] Fix buffer overrun from commit
4420c78beb86cc67392274bf351478a3375626a2
The newly handled ^ needs to be accounted for when allocating memory.
Found when testing #1936, goes to show what a useful thing that is.
---
lib/rpmdb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index fd2b0671ae..b3c5da62d5 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -1107,6 +1107,7 @@ static char * mireDup(rpmTagVal tag, rpmMireMode *modep,
case '.':
case '+':
case '*':
+ case '^':
if (!brackets) nb++;
break;
case '\\':

@ -1,11 +0,0 @@
--- rpm-4.16.1.3/tests/Makefile.am.orig 2023-05-03 12:44:36.287582896 +0200
+++ rpm-4.16.1.3/tests/Makefile.am 2023-05-03 12:46:34.182938006 +0200
@@ -170,7 +170,7 @@
for d in dev etc magic tmp var; do if [ ! -d testing/$${d} ]; then mkdir testing/$${d}; fi; done
for node in urandom stdin stderr stdout null full; do ln -s /dev/$${node} testing/dev/$${node}; done
for cf in hosts resolv.conf passwd shadow group gshadow mtab ; do [ -f /etc/$${cf} ] && ln -s /etc/$${cf} testing/etc/$${cf}; done
- for prog in gzip cat patch tar sh ln chmod rm mkdir uname grep sed find file ionice mktemp nice cut sort diff touch install wc coreutils xargs; do p=`which $${prog}`; if [ "$${p}" != "" ]; then ln -s $${p} testing/$(bindir)/; fi; done
+ for prog in gzip cat patch tar sh ln chmod rm mkdir uname grep sed find file ionice mktemp nice cut sort diff touch install wc coreutils xargs debugedit find-debuginfo find-debuginfo.sh ; do p=`which $${prog}`; if [ "$${p}" != "" ]; then ln -s $${p} testing/$(bindir)/; fi; done
for d in /proc /sys /selinux /etc/selinux; do if [ -d $${d} ]; then ln -s $${d} testing/$${d}; fi; done
(cd testing/magic && file -C)
chmod -R u-w testing/

@ -1,167 +0,0 @@
From 534fd1f0c84b12ba6080a46e07c57ef913c77cba Mon Sep 17 00:00:00 2001
From: Radovan Sroka <rsroka@redhat.com>
Date: Thu, 25 Aug 2022 15:38:01 +0200
Subject: [PATCH] fapolicyd: Make write() nonblocking
- switch to read only and non blocking mode for pipe
- add 1 minute loop to wait for pipe to reappear
Sometimes during the system update/upgrade fapolicyd
get restarted e.g. when systemd gets updated.
That can lead to the situation where fapolicyd pipe
has been removed and created again.
In such cases rpm-plugin-fapolicyd gets stuck on
write() to the pipe which does not exist anymore.
After switching to non blocking file descriptor
we can try to reopen the pipe if there is an error
from write(). Assuming that a new pipe should appear
when fapolicyd daemon starts again.
If not then after 1 minute of waiting we expect
fapolicyd daemon to be not active and we let the
transaction continue.
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
---
plugins/fapolicyd.c | 74 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 65 insertions(+), 9 deletions(-)
diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
index 1ff50c30f..6c6322941 100644
--- a/plugins/fapolicyd.c
+++ b/plugins/fapolicyd.c
@@ -27,7 +27,7 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
int fd = -1;
struct stat s;
- fd = open(state->fifo_path, O_RDWR);
+ fd = open(state->fifo_path, O_WRONLY|O_NONBLOCK);
if (fd == -1) {
rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
goto bad;
@@ -55,15 +55,26 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
}
state->fd = fd;
+
/* considering success */
return RPMRC_OK;
bad:
if (fd >= 0)
close(fd);
+
+ state->fd = -1;
return RPMRC_FAIL;
}
+static void close_fifo(struct fapolicyd_data* state)
+{
+ if (state->fd > 0)
+ (void) close(state->fd);
+
+ state->fd = -1;
+}
+
static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
{
ssize_t len = strlen(str);
@@ -86,6 +97,54 @@ static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
return RPMRC_FAIL;
}
+static void try_to_write_to_fifo(struct fapolicyd_data* state, const char * str)
+{
+ int reload = 0;
+ int printed = 0;
+
+ /* 1min/60s */
+ const int timeout = 60;
+
+ /* wait up to X seconds */
+ for (int i = 0; i < timeout; i++) {
+
+ if (reload) {
+ if (!printed) {
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: waiting for the service connection to resume, it can take up to %d seconds\n", timeout);
+ printed = 1;
+ }
+
+ (void) close_fifo(state);
+ (void) open_fifo(state);
+ }
+
+ if (state->fd >= 0) {
+ if (write_fifo(state, str) == RPMRC_OK) {
+
+ /* write was successful after few reopens */
+ if (reload)
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has resumed\n");
+
+ break;
+ }
+ }
+
+ /* failed write or reopen */
+ reload = 1;
+ sleep(1);
+
+ /* the last iteration */
+ /* consider failure */
+ if (i == timeout-1) {
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has not resumed\n");
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: continuing without the service\n");
+ }
+
+ }
+
+}
+
+
static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
{
if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
@@ -102,10 +161,7 @@ static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
static void fapolicyd_cleanup(rpmPlugin plugin)
{
- if (fapolicyd_state.fd > 0)
- (void) close(fapolicyd_state.fd);
-
- fapolicyd_state.fd = -1;
+ (void) close_fifo(&fapolicyd_state);
}
static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
@@ -116,9 +172,9 @@ static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
/* we are ready */
if (fapolicyd_state.fd > 0) {
/* send a signal that transaction is over */
- (void) write_fifo(&fapolicyd_state, "1\n");
+ (void) try_to_write_to_fifo(&fapolicyd_state, "1\n");
/* flush cache */
- (void) write_fifo(&fapolicyd_state, "2\n");
+ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n");
}
end:
@@ -133,7 +189,7 @@ static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
if (fapolicyd_state.changed_files > 0) {
/* send signal to flush cache */
- (void) write_fifo(&fapolicyd_state, "2\n");
+ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n");
/* optimize flushing */
/* flush only when there was an actual change */
@@ -176,7 +232,7 @@ static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
char * sha = rpmfiFDigestHex(fi, NULL);
snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
- (void) write_fifo(&fapolicyd_state, buffer);
+ (void) try_to_write_to_fifo(&fapolicyd_state, buffer);
free(sha);
--
2.37.3

@ -1,20 +0,0 @@
--- rpm.orig/macros.in 2022-06-30 11:37:18.975312592 +0100
+++ rpm-4.16.1.3/macros.in 2022-06-30 11:37:43.145158323 +0100
@@ -167,6 +167,9 @@
# A spec file can %%define _find_debuginfo_opts to pass options to
# the script. See the script for details.
#
+# Vendor spec files (eg redhat-rpm-config:macros) can %%define
+# _find_debuginfo_vendor_opts to pass options to the script.
+#
%__debug_install_post \
%{_rpmconfigdir}/find-debuginfo.sh \\\
%{?_smp_build_ncpus:-j%{_smp_build_ncpus}} \\\
@@ -179,6 +182,7 @@
%{?_unique_debug_srcs:--unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}"} \\\
%{?_find_debuginfo_dwz_opts} \\\
%{?_find_debuginfo_opts} \\\
+ %{?_find_debuginfo_vendor_opts} \\\
%{?_debugsource_packages:-S debugsourcefiles.list} \\\
"%{_builddir}/%{?buildsubdir}"\
%{nil}

@ -1,288 +0,0 @@
From b66422161d68ed7f7b1cb30e4db900bf42bed146 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 29 Nov 2021 14:01:39 +0200
Subject: [PATCH 1/4] Add Python bindings for rpmfilesFSignature()
Only, use more descriptive names than the C-side counterparts.
Python has nice facilities for dealing with binary data so return it
as such rather than converting to hex.
Backported for 4.16.1.3 (removed rpmfilesVSignature()).
---
python/rpmfiles-py.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/python/rpmfiles-py.c b/python/rpmfiles-py.c
index 27666021d..48189a0ac 100644
--- a/python/rpmfiles-py.c
+++ b/python/rpmfiles-py.c
@@ -152,6 +152,22 @@ static PyObject *rpmfile_digest(rpmfileObject *s)
Py_RETURN_NONE;
}
+static PyObject *bytebuf(const unsigned char *buf, size_t len)
+{
+ if (buf) {
+ PyObject *o = PyBytes_FromStringAndSize((const char *)buf, len);
+ return o;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *rpmfile_imasig(rpmfileObject *s)
+{
+ size_t len = 0;
+ const unsigned char *sig = rpmfilesFSignature(s->files, s->ix, &len);
+ return bytebuf(sig, len);
+}
+
static PyObject *rpmfile_class(rpmfileObject *s)
{
return utf8FromString(rpmfilesFClass(s->files, s->ix));
@@ -278,6 +294,8 @@ static PyGetSetDef rpmfile_getseters[] = {
"language the file provides (typically for doc files)" },
{ "caps", (getter) rpmfile_caps, NULL,
"file capabilities" },
+ { "imasig", (getter) rpmfile_imasig, NULL,
+ "IMA signature" },
{ NULL, NULL, NULL, NULL }
};
--
2.35.1
From 9c4622998d3d0666edbea3ed1ae518502c3ed987 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 7 Feb 2022 11:52:55 +0200
Subject: [PATCH 2/4] Add a testcase for --dump query
---
tests/rpmquery.at | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tests/rpmquery.at b/tests/rpmquery.at
index 9a4f1cb76..9bd391ac5 100644
--- a/tests/rpmquery.at
+++ b/tests/rpmquery.at
@@ -83,6 +83,24 @@ hello.spec
[ignore])
AT_CLEANUP
+AT_SETUP([rpm -qp --dump])
+AT_KEYWORDS([query])
+AT_CHECK([
+RPMDB_INIT
+runroot rpm \
+ -qp --dump \
+ /data/RPMS/hello-2.0-1.x86_64.rpm
+],
+[0],
+[/usr/bin/hello 7120 1489670606 c89fa87aeb1143969c0b6be9334b21d932f77f74e8f60120b5de316406369cf0 0100751 root root 0 0 0 X
+/usr/share/doc/hello-2.0 4096 1489670606 0000000000000000000000000000000000000000000000000000000000000000 040755 root root 0 0 0 X
+/usr/share/doc/hello-2.0/COPYING 48 908894882 fac3b28492ecdc16da172a6f1a432ceed356ca4d9248157b2a962b395e37b3b0 0100644 root root 0 1 0 X
+/usr/share/doc/hello-2.0/FAQ 36 908895030 678b87e217a415f05e43460e2c7b668245b412e2b4f18a75aa7399d9774ed0b4 0100644 root root 0 1 0 X
+/usr/share/doc/hello-2.0/README 39 908884468 d63fdc6c986106f57230f217d36b2395d83ecf491d2b7187af714dc8db9629e9 0100644 root root 0 1 0 X
+],
+[])
+AT_CLEANUP
+
# ------------------------------
AT_SETUP([rpmspec -q])
AT_KEYWORDS([query])
--
2.35.1
From 9b2bc10881db7691439005fd74ea53d75b15ac76 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 10 Feb 2022 11:15:04 +0200
Subject: [PATCH 3/4] Ensure sane string lengths for file digests from header
---
lib/rpmfi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index af428468c..2dffab3aa 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -1501,6 +1501,10 @@ static uint8_t *hex2bin(Header h, rpmTagVal tag, rpm_count_t num, size_t len)
t += len;
continue;
}
+ if (strlen(s) != len * 2) {
+ bin = rfree(bin);
+ break;
+ }
for (int j = 0; j < len; j++, t++, s += 2)
*t = (rnibble(s[0]) << 4) | rnibble(s[1]);
}
--
2.35.1
From ddfed9e1842a1b60a8c40de3a18add6f6d68c515 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 29 Nov 2021 14:01:39 +0200
Subject: [PATCH 4/4] Fix IMA signature fubar, take III (#1833, RhBug:2018937)
At least ECDSA and RSA signatures can vary in length, but the IMA code
assumes constant lengths and thus may either place invalid signatures on
disk from either truncating or overshooting, and segfault if the stars are
just so.
As we can't assume static lengths and attempts to use maximum length
have proven problematic for other reasons, use a data structure that
can actually handle variable length data properly: store offsets into
the decoded binary blob and use them to calculate lengths when needed,
empty data is simply consequtive identical offsets. This avoids a whole
class of silly overflow issues with multiplying, makes zero-length data
actually presentable in the data structure and saves memory too.
Add tests to show behavior with variable length signatures and missing
signatures.
Additionally update the signing code to store the largest IMA signature
length rather than what happened to be last to be on the safe side.
We can't rely on this value due to invalid packages being out there,
but then we need to calculate the lengths on rpmfiles populate so there's
not a lot to gain anyhow.
Fixes: #1833
Backported for 4.16.1.3. Note that the test case has been removed due
to it including a binary file (test package) for which we'd have to use
-Sgit with %autopatch and thus depend on git-core at build time.
Nevertheless, we do have this BZ covered in our internal test suite, so
no need for it anyway.
---
lib/rpmfi.c | 61 +++++++++++++++++++++++++++++++++++++++------
sign/rpmsignfiles.c | 5 +++-
2 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index 2dffab3aa..77e73442c 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -115,7 +115,7 @@ struct rpmfiles_s {
struct fingerPrint_s * fps; /*!< File fingerprint(s). */
int digestalgo; /*!< File digest algorithm */
- int signaturelength; /*!< File signature length */
+ uint32_t *signatureoffs; /*!< File signature offsets */
unsigned char * digests; /*!< File digests in binary. */
unsigned char * signatures; /*!< File signatures in binary. */
@@ -574,10 +574,15 @@ const unsigned char * rpmfilesFSignature(rpmfiles fi, int ix, size_t *len)
const unsigned char *signature = NULL;
if (fi != NULL && ix >= 0 && ix < rpmfilesFC(fi)) {
- if (fi->signatures != NULL)
- signature = fi->signatures + (fi->signaturelength * ix);
+ size_t slen = 0;
+ if (fi->signatures != NULL && fi->signatureoffs != NULL) {
+ uint32_t off = fi->signatureoffs[ix];
+ slen = fi->signatureoffs[ix+1] - off;
+ if (slen > 0)
+ signature = fi->signatures + off;
+ }
if (len)
- *len = fi->signaturelength;
+ *len = slen;
}
return signature;
}
@@ -1257,6 +1262,7 @@ rpmfiles rpmfilesFree(rpmfiles fi)
fi->flangs = _free(fi->flangs);
fi->digests = _free(fi->digests);
fi->signatures = _free(fi->signatures);
+ fi->signatureoffs = _free(fi->signatureoffs);
fi->fcaps = _free(fi->fcaps);
fi->cdict = _free(fi->cdict);
@@ -1485,6 +1491,48 @@ err:
return;
}
+/*
+ * Convert a tag of variable len hex strings to binary presentation,
+ * accessed via offsets to a contiguous binary blob. Empty values
+ * are represented by identical consequtive offsets. The offsets array
+ * always has one extra element to allow calculating the size of the
+ * last element.
+ */
+static uint8_t *hex2binv(Header h, rpmTagVal tag, rpm_count_t num,
+ uint32_t **offsetp)
+{
+ struct rpmtd_s td;
+ uint8_t *bin = NULL;
+ uint32_t *offs = NULL;
+
+ if (headerGet(h, tag, &td, HEADERGET_MINMEM) && rpmtdCount(&td) == num) {
+ const char *s;
+ int i = 0;
+ uint8_t *t = bin = xmalloc(((rpmtdSize(&td) / 2) + 1));
+ offs = xmalloc((num + 1) * sizeof(*offs));
+
+ while ((s = rpmtdNextString(&td))) {
+ uint32_t slen = strlen(s);
+ uint32_t len = slen / 2;
+ if (slen % 2) {
+ bin = rfree(bin);
+ offs = rfree(offs);
+ goto exit;
+ }
+ offs[i] = t - bin;
+ for (int j = 0; j < len; j++, t++, s += 2)
+ *t = (rnibble(s[0]) << 4) | rnibble(s[1]);
+ i++;
+ }
+ offs[i] = t - bin;
+ *offsetp = offs;
+ }
+
+exit:
+ rpmtdFreeData(&td);
+ return bin;
+}
+
/* Convert a tag of hex strings to binary presentation */
static uint8_t *hex2bin(Header h, rpmTagVal tag, rpm_count_t num, size_t len)
{
@@ -1580,9 +1628,8 @@ static int rpmfilesPopulate(rpmfiles fi, Header h, rpmfiFlags flags)
fi->signatures = NULL;
/* grab hex signatures from header and store in binary format */
if (!(flags & RPMFI_NOFILESIGNATURES)) {
- fi->signaturelength = headerGetNumber(h, RPMTAG_FILESIGNATURELENGTH);
- fi->signatures = hex2bin(h, RPMTAG_FILESIGNATURES,
- totalfc, fi->signaturelength);
+ fi->signatures = hex2binv(h, RPMTAG_FILESIGNATURES,
+ totalfc, &fi->signatureoffs);
}
/* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */
diff --git a/sign/rpmsignfiles.c b/sign/rpmsignfiles.c
index b143c5b9b..372ba634c 100644
--- a/sign/rpmsignfiles.c
+++ b/sign/rpmsignfiles.c
@@ -98,8 +98,9 @@ rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass)
td.count = 1;
while (rpmfiNext(fi) >= 0) {
+ uint32_t slen = 0;
digest = rpmfiFDigest(fi, NULL, NULL);
- signature = signFile(algoname, digest, diglen, key, keypass, &siglen);
+ signature = signFile(algoname, digest, diglen, key, keypass, &slen);
if (!signature) {
rpmlog(RPMLOG_ERR, _("signFile failed\n"));
goto exit;
@@ -110,6 +111,8 @@ rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass)
goto exit;
}
signature = _free(signature);
+ if (slen > siglen)
+ siglen = slen;
}
if (siglen > 0) {
--
2.35.1

@ -1,88 +0,0 @@
From f5695d04f56e27d9cf947c0502eb549c28aa817e Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 25 May 2021 14:07:18 +0300
Subject: [PATCH] Fix regression reading rpm v3 and other rare packages (#1635)
Commit d6a86b5e69e46cc283b1e06c92343319beb42e21 introduced far stricter
checks on what tags are allowed in signature and main headers than rpm
had previously seen, and unsurprisingly this introduced some regressions
on less common cases:
- On rpm v3 packages and some newer 3rd party created packages (such as
install4j < 9.0.2), RPMTAG_ARCHIVESIZE resides in the main header
to begin with
- In rpm 4.13 - 4.14, file IMA signatures were incorrectly placed in
the main header.
As a quirk, permit the existence of RPMTAG_ARCHIVESIZE,
RPMTAG_FILESIGNATURES and RPMTAG_FILESIGNATURELENGTH in the main header
too provided that the corresponding signature tag is not there (so
they can reside in either but not both headers).
Initial workaround patch by Demi Marie Obenour.
Fixes: #1635
Backported for 4.16.1.3.
---
lib/package.c | 35 ++++++++++++++++++++---------------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/lib/package.c b/lib/package.c
index 36ed5abc6..8c2b66b0b 100644
--- a/lib/package.c
+++ b/lib/package.c
@@ -35,21 +35,22 @@ struct taglate_s {
rpmTagVal stag;
rpmTagVal xtag;
rpm_count_t count;
+ int quirk;
} const xlateTags[] = {
- { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1 },
- { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0 },
- { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16 },
- { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0 },
- /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0 }, */ /* long obsolete, dont use */
- { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1 },
- { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0 },
- { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1 },
- { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1 },
- { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1 },
- { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0 },
- { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0 },
- { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1 },
- { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1 },
+ { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1, 0 },
+ { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0, 0 },
+ { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16, 0 },
+ { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0, 0 },
+ /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0, 0 }, */ /* long obsolete, dont use */
+ { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1, 1 },
+ { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0, 1 },
+ { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1, 1 },
+ { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1, 0 },
+ { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1, 0 },
+ { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0, 0 },
+ { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0, 0 },
+ { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1, 0 },
+ { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1, 0 },
{ 0 }
};
@@ -67,8 +68,12 @@ rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg)
for (xl = xlateTags; xl->stag; xl++) {
/* There mustn't be one in the main header */
- if (headerIsEntry(h, xl->xtag))
+ if (headerIsEntry(h, xl->xtag)) {
+ /* Some tags may exist in either header, but never both */
+ if (xl->quirk && !headerIsEntry(sigh, xl->stag))
+ continue;
goto exit;
+ }
}
rpmtdReset(&td);
--
2.35.1

@ -1,123 +0,0 @@
From 8c37dff4ce9c887eda5ad61f78001e87473002ed Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 16 Nov 2021 11:49:18 +0200
Subject: [PATCH] Fix spurious %transfiletriggerpostun execution
(RhBug:2023311)
If a package has multiple %transfiletriggerpostun triggers, any one
of them matching would cause all of them to run, due to disconnect
in the intel gathering stage: we'd gather all the headers with matching
files into a lump, and then add any postun triggers found in them,
but this loses the triggering file information and causes all postuns
to run.
The triggers need to be added while looping over the file matches,
like runFileTriggers() does. Doing so actually simplifies the code.
These should really be unified to use the same code, but leaving
that exercise to another rainy day.
Combined with 0988ccb53abf426587d228df5c60c4042da71999 (fix-up).
---
lib/rpmtriggers.c | 65 ++++++++++++++++++++++++-----------------------
1 file changed, 33 insertions(+), 32 deletions(-)
diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c
index fc809a65e..8d8f57450 100644
--- a/lib/rpmtriggers.c
+++ b/lib/rpmtriggers.c
@@ -97,19 +97,39 @@ static void rpmtriggersSortAndUniq(rpmtriggers trigs)
}
}
+static void addTriggers(rpmts ts, Header trigH, rpmsenseFlags filter,
+ const char *prefix)
+{
+ int tix = 0;
+ rpmds ds;
+ rpmds triggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0);
+
+ while ((ds = rpmdsFilterTi(triggers, tix))) {
+ if ((rpmdsNext(ds) >= 0) && (rpmdsFlags(ds) & filter) &&
+ strcmp(prefix, rpmdsN(ds)) == 0) {
+ struct rpmtd_s priorities;
+
+ if (headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES,
+ &priorities, HEADERGET_MINMEM)) {
+ rpmtdSetIndex(&priorities, tix);
+ rpmtriggersAdd(ts->trigs2run, headerGetInstance(trigH),
+ tix, *rpmtdGetUint32(&priorities));
+ }
+ }
+ rpmdsFree(ds);
+ tix++;
+ }
+ rpmdsFree(triggers);
+}
+
void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
{
- rpmdbMatchIterator mi;
rpmdbIndexIterator ii;
- Header trigH;
const void *key;
size_t keylen;
rpmfiles files;
- rpmds rpmdsTriggers;
- rpmds rpmdsTrigger;
ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMDBI_TRANSFILETRIGGERNAME);
- mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES);
files = rpmteFiles(te);
/* Iterate over file triggers in rpmdb */
@@ -121,39 +141,20 @@ void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
rpmfi fi = rpmfilesFindPrefix(files, pfx);
while (rpmfiNext(fi) >= 0) {
if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) {
- /* If yes then store it */
- rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii),
- rpmdbIndexIteratorNumPkgs(ii));
+ unsigned int npkg = rpmdbIndexIteratorNumPkgs(ii);
+ const unsigned int *offs = rpmdbIndexIteratorPkgOffsets(ii);
+ /* Save any postun triggers matching this prefix */
+ for (int i = 0; i < npkg; i++) {
+ Header h = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offs[i]);
+ addTriggers(ts, h, RPMSENSE_TRIGGERPOSTUN, pfx);
+ headerFree(h);
+ }
break;
}
}
rpmfiFree(fi);
}
rpmdbIndexIteratorFree(ii);
-
- if (rpmdbGetIteratorCount(mi)) {
- /* Filter triggers and save only trans postun triggers into ts */
- while ((trigH = rpmdbNextIterator(mi)) != NULL) {
- int tix = 0;
- rpmdsTriggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0);
- while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, tix))) {
- if ((rpmdsNext(rpmdsTrigger) >= 0) &&
- (rpmdsFlags(rpmdsTrigger) & RPMSENSE_TRIGGERPOSTUN)) {
- struct rpmtd_s priorities;
-
- headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES,
- &priorities, HEADERGET_MINMEM);
- rpmtdSetIndex(&priorities, tix);
- rpmtriggersAdd(ts->trigs2run, rpmdbGetIteratorOffset(mi),
- tix, *rpmtdGetUint32(&priorities));
- }
- rpmdsFree(rpmdsTrigger);
- tix++;
- }
- rpmdsFree(rpmdsTriggers);
- }
- }
- rpmdbFreeIterator(mi);
rpmfilesFree(files);
}
--
2.35.1

@ -1,13 +0,0 @@
diff -up rpm-4.16.1.3/tools/hashtab.c.orig rpm-4.16.1.3/tools/hashtab.c
--- rpm-4.16.1.3/tools/hashtab.c.orig 2021-07-01 14:51:24.576237269 +0200
+++ rpm-4.16.1.3/tools/hashtab.c 2021-07-01 15:02:42.005754968 +0200
@@ -292,7 +292,8 @@ htab_expand (htab)
}
while (p < olimit);
- free (oentries);
+ if (oentries != htab->entries)
+ free(oentries);
return 1;
}

@ -1,286 +0,0 @@
commit c7d7c5acd0c14d0450016887cba1d86483086794
Author: Michal Domonkos <mdomonko@redhat.com>
Date: Mon Jun 21 10:05:10 2021 +0200
Add quoting to literal curly brackets
These curly brackets are already treated as literals by the shell, so
let's make that explicit for clarity, and silence a ShellCheck warning
at the same time.
More info: https://github.com/koalaman/shellcheck/wiki/SC1083
Found by ShellCheck.
Adjusted for 4.16.1.3
diff -up rpm-4.16.1.3/scripts/check-rpaths-worker.orig rpm-4.16.1.3/scripts/check-rpaths-worker
--- rpm-4.16.1.3/scripts/check-rpaths-worker.orig 2021-06-29 15:34:31.671003589 +0200
+++ rpm-4.16.1.3/scripts/check-rpaths-worker 2021-06-29 15:34:51.993414093 +0200
@@ -120,13 +120,13 @@ for i; do
(/lib64/*|/usr/lib64/*|/usr/X11R6/lib64/*|/usr/local/lib64/*)
badness=0;;
- (\$ORIGIN|\${ORIGINX}|\$ORIGIN/*|\${ORIGINX}/*)
+ (\$ORIGIN|\$\{ORIGINX\}|\$ORIGIN/*|\$\{ORIGINX\}/*)
test $allow_ORIGIN -eq 0 && badness=8 || {
badness=0
new_allow_ORIGIN=1
}
;;
- (/*\$PLATFORM*|/*\${PLATFORM}*|/*\$LIB*|/*\${LIB}*)
+ (/*\$PLATFORM*|/*\$\{PLATFORM\}*|/*\$LIB*|/*\$\{LIB\}*)
badness=0;;
(/lib|/usr/lib|/usr/X11R6/lib)
From d8dc4fd37b1d90cd97de7fcf484d449ec132c9b3 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Wed, 9 Jun 2021 21:31:40 +0200
Subject: [PATCH 1/7] Fix memory leak in sqlexec()
Callers are supposed to free the error strings themselves:
https://www.sqlite.org/capi3ref.html#sqlite3_exec
Found by Coverity.
---
lib/backend/sqlite.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c
index 7c2de45aa..dbefeb163 100644
--- a/lib/backend/sqlite.c
+++ b/lib/backend/sqlite.c
@@ -233,6 +233,7 @@ static int sqlexec(sqlite3 *sdb, const char *fmt, ...)
rpmlog(RPMLOG_DEBUG, "%s: %d\n", cmd, rc);
sqlite3_free(cmd);
+ sqlite3_free(err);
return rc ? RPMRC_FAIL : RPMRC_OK;
}
--
2.31.1
From 5baf73feb4951cc3b3f553a4b18d3b3599cbf87c Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 25 Jun 2021 11:21:46 +0200
Subject: [PATCH 2/7] Always free the arg list passed to rpmGlob()
Even though the actual implementation of rpmGlob() does not allocate the
passed arg list (av) if the return code (rc) is non-zero or arg count
(ac) is 0, it's the responsibility of the caller (rpmInstall() here) to
free that memory, so make sure we do that irrespectively of the above
conditions.
Found by Coverity.
---
lib/rpminstall.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpminstall.c b/lib/rpminstall.c
index 724126e94..302ec0ba1 100644
--- a/lib/rpminstall.c
+++ b/lib/rpminstall.c
@@ -461,6 +461,7 @@ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv)
rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp);
}
eiu->numFailed++;
+ argvFree(av);
continue;
}
--
2.31.1
From 3c8b01b67ec907afaaffe71691fa41b878578527 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 14 Jun 2021 10:21:25 +0200
Subject: [PATCH 3/7] Fix resource leak in Fts_children()
This function is not used anywhere within our codebase (and neither is
it part of the public API) so it's basically a no-op... Still, rather
than yanking it completely, let's just silence the Coverity error here.
Found by Coverity.
---
misc/fts.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/misc/fts.c b/misc/fts.c
index d3ebb2946..caf27495d 100644
--- a/misc/fts.c
+++ b/misc/fts.c
@@ -585,8 +585,10 @@ Fts_children(FTS * sp, int instr)
if ((fd = __open(".", O_RDONLY, 0)) < 0)
return (NULL);
sp->fts_child = fts_build(sp, instr);
- if (__fchdir(fd))
+ if (__fchdir(fd)) {
+ (void)__close(fd);
return (NULL);
+ }
(void)__close(fd);
return (sp->fts_child);
}
--
2.31.1
From 39b7bf8579e0522cf16347b3a7e332d3b6d742c6 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 14 Jun 2021 12:34:23 +0200
Subject: [PATCH 4/7] Fix memory leak in fts_build()
Turns out this leak is already fixed in glibc's current version of fts.c
(where our copy originates from), so let's just backport that.
Original commit in glibc:
https://sourceware.org/git/?p=glibc.git;\
a=commit;h=db67c2c98b89a5723af44df54f38b779de8d4a65
Found by Coverity.
---
misc/fts.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/misc/fts.c b/misc/fts.c
index caf27495d..f7fce0eaa 100644
--- a/misc/fts.c
+++ b/misc/fts.c
@@ -855,6 +855,7 @@ mem1: saved_errno = errno;
fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
cur->fts_info = FTS_ERR;
SET(FTS_STOP);
+ fts_lfree(head);
return (NULL);
}
@@ -862,6 +863,7 @@ mem1: saved_errno = errno;
if (!nitems) {
if (type == BREAD)
cur->fts_info = FTS_DP;
+ fts_lfree(head);
return (NULL);
}
--
2.31.1
From 9c093c4f092dd6bd1e0c8d2b852a72b74db076c2 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Tue, 15 Jun 2021 13:34:21 +0200
Subject: [PATCH 5/7] Fix memory leak in decodePkts()
Found by Coverity.
---
rpmio/rpmpgp.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
index c59185dce..ee5c81e24 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -1371,9 +1371,13 @@ static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
crc = pgpCRC(dec, declen);
if (crcpkt != crc) {
ec = PGPARMOR_ERR_CRC_CHECK;
+ _free(dec);
goto exit;
}
- if (pkt) *pkt = dec;
+ if (pkt)
+ *pkt = dec;
+ else
+ _free(dec);
if (pktlen) *pktlen = declen;
ec = PGPARMOR_PUBKEY; /* XXX ASCII Pubkeys only, please. */
goto exit;
--
2.31.1
From 590b2fc06252567eb7d57197dc361a8b459d62a3 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 21 Jun 2021 17:51:14 +0200
Subject: [PATCH 6/7] Fix memory leak with multiple %lang-s in one line
We permit two equivalent forms of specifying a list of languages per
file:
%lang(xx,yy,zz) /path/to/file
%lang(xx) %lang(yy) %lang(zz) /path/to/file
The leak was when parsing the second form.
Found by Coverity.
---
build/files.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/build/files.c b/build/files.c
index f8153ad2b..0c8859f6c 100644
--- a/build/files.c
+++ b/build/files.c
@@ -777,6 +777,8 @@ static rpmRC parseForLang(char * buf, FileEntry cur)
if (*pe == ',') pe++; /* skip , if present */
}
+
+ q = _free(q);
}
rc = RPMRC_OK;
--
2.31.1
From b7a1e996326ee29a163d67ceb1e6127fdc251c14 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 25 Jun 2021 15:15:08 +0200
Subject: [PATCH 7/7] Fix memory leaks in Lua rex extension
This covers the following usage:
expr = rex.newPOSIX(<regex>)
expr:match(<string>) # A leak occurred here
expr:gmatch(<string>, <func>) # A leak occurred here
Found by Coverity.
---
luaext/lrexlib.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/luaext/lrexlib.c b/luaext/lrexlib.c
index 09c5a6454..0f29b6371 100644
--- a/luaext/lrexlib.c
+++ b/luaext/lrexlib.c
@@ -80,6 +80,7 @@ static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match,
static int rex_match(lua_State *L)
{
+ int rc = 0;
int res;
#ifdef REG_BASIC
size_t len;
@@ -109,9 +110,10 @@ static int rex_match(lua_State *L)
lua_pushstring(L, "n");
lua_pushnumber(L, ncapt);
lua_rawset(L, -3);
- return 3;
- } else
- return 0;
+ rc = 3;
+ }
+ free(match);
+ return rc;
}
static int rex_gmatch(lua_State *L)
@@ -158,6 +160,7 @@ static int rex_gmatch(lua_State *L)
break;
}
lua_pushnumber(L, nmatch);
+ free(match);
return 1;
}
--
2.31.1

@ -1,51 +0,0 @@
From f1634250587479d664b34b6de1a6546b2c2b9de5 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Mon, 18 Jan 2021 15:02:34 +0100
Subject: [PATCH] rpm2archive: Add more error handling
Cleanly error out if file can't be written instead of segfaulting
Resolves: #1091
---
rpm2archive.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/rpm2archive.c b/rpm2archive.c
index 646f1663d..15c5da016 100644
--- a/rpm2archive.c
+++ b/rpm2archive.c
@@ -119,9 +119,14 @@ static int process_package(rpmts ts, char * filename)
/* create archive */
a = archive_write_new();
- archive_write_add_filter_gzip(a);
- archive_write_set_format_pax_restricted(a);
-
+ if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) {
+ fprintf(stderr, "Error: Could not create gzip output filter\n");
+ exit(EXIT_FAILURE);
+ }
+ if (archive_write_set_format_pax_restricted(a) != ARCHIVE_OK) {
+ fprintf(stderr, "Error: Format pax restricted is not supported\n");
+ exit(EXIT_FAILURE);
+ }
if (!strcmp(filename, "-")) {
if (isatty(STDOUT_FILENO)) {
fprintf(stderr, "Error: refusing to output archive data to a terminal.\n");
@@ -130,9 +135,11 @@ static int process_package(rpmts ts, char * filename)
archive_write_open_fd(a, STDOUT_FILENO);
} else {
char * outname = rstrscat(NULL, filename, ".tgz", NULL);
- archive_write_open_filename(a, outname);
+ if (archive_write_open_filename(a, outname) != ARCHIVE_OK) {
+ fprintf(stderr, "Error: Can't open output file: %s\n", outname);
+ exit(EXIT_FAILURE);
+ }
_free(outname);
- // XXX error handling
}
entry = archive_entry_new();
--
2.38.1

@ -1,173 +0,0 @@
From d8a169164cf40fc1cf6448792c1fa991f19bb375 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Thu, 22 Apr 2021 14:50:34 +0200
Subject: [PATCH] Add --nocompression option to rpm2archive
Also use popt for the command line handling. As we are using librpm
anyway there is no reason to keep the dependencies low (as with
rpm2cpio).
Resolves: #1530
---
doc/rpm2archive.8 | 16 ++++++++++---
rpm2archive.c | 60 ++++++++++++++++++++++++++++++++++-------------
2 files changed, 57 insertions(+), 19 deletions(-)
diff --git a/doc/rpm2archive.8 b/doc/rpm2archive.8
index 8bd6d4ed9d..3895d01981 100644
--- a/doc/rpm2archive.8
+++ b/doc/rpm2archive.8
@@ -3,10 +3,10 @@
.SH NAME
rpm2archive \- Create tar archive from RPM Package Manager (RPM) package.
.SH SYNOPSIS
-\fBrpm2archive\fP [filename]
+\fBrpm2archive\fP \fB{-n|--nocompression}\fR \fB\fIFILES\fB\fR
.SH DESCRIPTION
-\fBrpm2archive\fP converts the .rpm files specified as arguments to gz
-compressed tar files with suffix ".tgz".
+\fBrpm2archive\fP converts the .rpm files specified as arguments to
+tar files. By default they are gzip compressed and saved with postfix ".tgz".
If '-' is given as argument, an rpm stream is read from standard in and
written to standard out.
@@ -16,6 +16,16 @@ containing files greater than 4GB which are not supported by cpio. Unless
\fBrpm2cpio\fP \fBrpm2archive\fP needs a working rpm installation which limits
its usefulness for some disaster recovery scenarios.
+.SH "OPTIONS"
+.TP
+\fB\-n, --nocompression\fR
+Generate uncompressed tar archive and use ".tar" as postfix of the
+file name.
+.PP
+
+.SH EXAMPLES
+.PP
+
.br
.I "\fBrpm2archive glint-1.0-1.i386.rpm ; tar -xvz glint-1.0-1.i386.rpm.tgz\fP"
.br
diff --git a/rpm2archive.c b/rpm2archive.c
index d96db006ea..cb39c7a712 100644
--- a/rpm2archive.c
+++ b/rpm2archive.c
@@ -10,6 +10,8 @@
#include <rpm/rpmts.h>
+#include <popt.h>
+
#include <archive.h>
#include <archive_entry.h>
#include <unistd.h>
@@ -18,6 +20,16 @@
#define BUFSIZE (128*1024)
+int compress = 1;
+
+static struct poptOption optionsTable[] = {
+ { "nocompression", 'n', POPT_ARG_VAL, &compress, 0,
+ N_("create uncompressed tar file"),
+ NULL },
+ POPT_AUTOHELP
+ POPT_TABLEEND
+};
+
static void fill_archive_entry(struct archive * a, struct archive_entry * entry, rpmfi fi)
{
archive_entry_clear(entry);
@@ -60,7 +72,7 @@ static void write_file_content(struct archive * a, char * buf, rpmfi fi)
}
}
-static int process_package(rpmts ts, char * filename)
+static int process_package(rpmts ts, const char * filename)
{
FD_t fdi;
FD_t gzdi;
@@ -119,9 +131,11 @@ static int process_package(rpmts ts, char * filename)
/* create archive */
a = archive_write_new();
- if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) {
- fprintf(stderr, "Error: Could not create gzip output filter\n");
- exit(EXIT_FAILURE);
+ if (compress) {
+ if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) {
+ fprintf(stderr, "%s\n", archive_error_string(a));
+ exit(EXIT_FAILURE);
+ }
}
if (archive_write_set_format_pax_restricted(a) != ARCHIVE_OK) {
fprintf(stderr, "Error: Format pax restricted is not supported\n");
@@ -142,7 +156,12 @@ static int process_package(rpmts ts, char * filename)
}
archive_write_open_fd(a, STDOUT_FILENO);
} else {
- char * outname = rstrscat(NULL, filename, ".tgz", NULL);
+ char * outname = rstrscat(NULL, filename, NULL);
+ if (compress) {
+ outname = rstrscat(&outname, ".tgz", NULL);
+ } else {
+ outname = rstrscat(&outname, ".tar", NULL);
+ }
if (archive_write_open_filename(a, outname) != ARCHIVE_OK) {
fprintf(stderr, "Error: Can't open output file: %s\n", outname);
exit(EXIT_FAILURE);
@@ -203,21 +222,22 @@ static int process_package(rpmts ts, char * filename)
return rc;
}
-int main(int argc, char *argv[])
+int main(int argc, const char *argv[])
{
- int rc = 0, i;
+ int rc = 0;
+ poptContext optCon;
+ const char *fn;
xsetprogname(argv[0]); /* Portability call -- see system.h */
rpmReadConfigFiles(NULL, NULL);
- if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help"))) {
- fprintf(stderr, "Usage: %s [file.rpm ...]\n", argv[0]);
+ optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
+ poptSetOtherOptionHelp(optCon, "[OPTIONS]* <FILES>");
+ if (argc < 2 || poptGetNextOpt(optCon) == 0) {
+ poptPrintUsage(optCon, stderr, 0);
exit(EXIT_FAILURE);
}
- if (argc == 1)
- argv[argc++] = "-"; /* abuse NULL pointer at the end of argv */
-
rpmts ts = rpmtsCreate();
rpmVSFlags vsflags = 0;
@@ -227,13 +247,21 @@ int main(int argc, char *argv[])
vsflags |= RPMVSF_NOHDRCHK;
(void) rpmtsSetVSFlags(ts, vsflags);
- for (i = 1; i < argc; i++) {
+ /* if no file name is given use stdin/stdout */
+ if (!poptPeekArg(optCon)) {
+ rc = process_package(ts, "-");
+ if (rc != 0)
+ goto exit;
+ }
- rc = process_package(ts, argv[i]);
+ while ((fn = poptGetArg(optCon)) != NULL) {
+ rc = process_package(ts, fn);
if (rc != 0)
- return rc;
+ goto exit;
}
+ exit:
+ poptFreeContext(optCon);
(void) rpmtsFree(ts);
return rc;
}

@ -1,20 +0,0 @@
commit 23770e1a4f28c56a31fe600cae332c77333b60b6
Author: Demi Marie Obenour <athena@invisiblethingslab.com>
Date: Sat Mar 6 03:23:41 2021 -0500
rpmsign: support EdDSA signatures
They were previously rejected
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index 28cd91576..d8c84e937 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -155,6 +155,7 @@ static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen)
pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO);
switch (pubkey_algo) {
case PGPPUBKEYALGO_DSA:
+ case PGPPUBKEYALGO_EDDSA:
sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG;
break;
case PGPPUBKEYALGO_RSA:

@ -1,40 +0,0 @@
From 6cdcdd8770d1f0b9ba706dcc1e6392a59dbe3fe5 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Tue, 7 Dec 2021 08:08:37 +0100
Subject: [PATCH] Skip recorded symlinks in --setperms (RhBug:1900662)
If a package contains a symlink in the buildroot which is declared as a
ghost or config file but is a regular file or directory on the system
where it's installed, a --setperms call will reset its permissions to
those of a symlink (777 on Linux), which almost certainly is not the
correct thing to do.
To fix that, just skip files that were recorded as symlinks.
This is a special case of a general issue in --setperms; since file
permission semantics may change depending on the file type, to stay on
the safe side, any (ghost or config) file whose type changes after
installation should probably be skipped. However, symlinks are the most
prominent case here, so let's just focus on that now and avoid adding
too much cleverness to a popt alias (this got us into trouble not too
long ago, see commits 38c2f6e and 0d83637). We may revisit this in the
eventual C implementation.
---
rpmpopt.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/rpmpopt.in b/rpmpopt.in
index 27d298651..d5a6b140b 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" \
--
2.34.1

@ -1,39 +0,0 @@
From c771ae28e28b2971869b7801ffc7961f4dcb6544 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 10 Jun 2021 10:32:12 +0300
Subject: [PATCH] Support hash v8 databases from BDB < 4.6 in bdb_ro
In Hash v8 databases page type differs from newer ones to denote
the difference between sorted and unsorted pages.
Fixes reading rpm databases from older distros like SLES 11 and RHEL 5
(RhBug:1965147)
---
lib/backend/bdb_ro.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/backend/bdb_ro.c b/lib/backend/bdb_ro.c
index 2667ec845..695ef78e3 100644
--- a/lib/backend/bdb_ro.c
+++ b/lib/backend/bdb_ro.c
@@ -276,7 +276,7 @@ static int hash_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned i
pg = hash_bucket_to_page(cur->db, bucket);
if (bdb_getpage(cur->db, cur->page, pg))
return -1;
- if (cur->page[25] != 8 && cur->page[25] != 13)
+ if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2)
return -1;
cur->idx = (unsigned int)-2;
cur->numidx = *(uint16_t *)(cur->page + 20);
@@ -323,7 +323,7 @@ static int hash_next(struct bdb_cur *cur)
}
if (bdb_getpage(cur->db, cur->page, pg))
return -1;
- if (cur->page[25] != 8 && cur->page[25] != 13)
+ if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2)
return -1;
cur->numidx = *(uint16_t *)(cur->page + 20);
continue;
--
2.33.1

@ -1,32 +0,0 @@
commit cb6aa82dbc10d554f8d234e934ae7c77e39a3ce2
Author: Panu Matilainen <pmatilai@redhat.com>
Date: Tue Jan 12 13:35:23 2021 +0200
Unblock signals in forked scriptlets
Since commit c5f82d3f6223ebd0c5cc0a07ea60393ae7284929 we've blocked
most signals during transactions, which makes sense to rpm itself but
the signal mask is inherited to childs and carried even across exec(),
so all scriptlets are executing with those signals blocked as well.
Which in turn does not make sense, the scriptlets could run stuff that
actually depends on signal delivery (such as SIGALARM in RhBug:1913765).
Unblock all signals for forked scriptlet execution (Lua scriptlets are
totally different as they execute in-process for now)
diff --git a/lib/rpmscript.c b/lib/rpmscript.c
index 2ae3378f7..c69d29554 100644
--- a/lib/rpmscript.c
+++ b/lib/rpmscript.c
@@ -152,6 +152,11 @@ static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
FD_t scriptFd, FD_t out)
{
int xx;
+ sigset_t set;
+
+ /* Unmask all signals, the scripts may need them */
+ sigfillset(&set);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
/* SIGPIPE is ignored in rpm, reset to default for the scriptlet */
(void) signal(SIGPIPE, SIG_DFL);

@ -1,144 +0,0 @@
From 137ecc2e1841c2b27b99d4db9006253dd1c73dde Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 4 Jun 2021 23:30:49 +0200
Subject: [PATCH] Unbreak checking of installed rich dependencies
Commit ddb32b9187e9ce85819a84ca8d202131fd9f8b9f added an
extra check that tests if the provide we are checking really
intersects the dependency from rpmdb. Unfortunately the
rpmdsCompare() call does not understand rich dependencies and
will consider them as not intersecting.
Unbreak the check by not doing the intersection test for
rich dependencies. We'll improve this in a later commit.
Also add test cases for dependency problems with installed
rich dependencies.
---
lib/depends.c | 2 +-
tests/rpmdeps.at | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/lib/depends.c b/lib/depends.c
index c10ba4bda..fecbd9675 100644
--- a/lib/depends.c
+++ b/lib/depends.c
@@ -846,7 +846,7 @@ static void checkInstDeps(rpmts ts, depCache dcache, rpmte te,
rpmdsSetIx(ds, rpmdbGetIteratorFileNum(mi));
/* Is it in our range at all? (but file deps have no range) */
- if (depds)
+ if (depds && !rpmdsIsRich(ds))
match = rpmdsCompare(ds, depds);
if (match && unsatisfiedDepend(ts, dcache, ds) == is_problem) {
diff --git a/tests/rpmdeps.at b/tests/rpmdeps.at
index 67bde1dc8..8357af9df 100644
--- a/tests/rpmdeps.at
+++ b/tests/rpmdeps.at
@@ -732,3 +732,102 @@ runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm /build/RPMS/noarc
[],
[])
AT_CLEANUP
+
+# ------------------------------
+#
+AT_SETUP([install to break installed rich dependency])
+AT_KEYWORDS([install, boolean])
+RPMDB_INIT
+
+runroot rpmbuild --quiet -bb \
+ --define "pkg one" \
+ --define "cfls (deptest-three or deptest-five)" \
+ /data/SPECS/deptest.spec
+runroot rpmbuild --quiet -bb \
+ --define "pkg two" \
+ --define "reqs (deptest-five if deptest-four)" \
+ /data/SPECS/deptest.spec
+runroot rpmbuild --quiet -bb \
+ --define "pkg three" \
+ /data/SPECS/deptest.spec
+runroot rpmbuild --quiet -bb \
+ --define "pkg four" \
+ /data/SPECS/deptest.spec
+
+# installed conflict with "or" clause
+AT_CHECK([
+RPMDB_INIT
+
+runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm
+runroot rpm -U /build/RPMS/noarch/deptest-three-1.0-1.noarch.rpm
+],
+[1],
+[],
+[error: Failed dependencies:
+ (deptest-three or deptest-five) conflicts with (installed) deptest-one-1.0-1.noarch
+])
+
+# installed requires with "if" clause
+AT_CHECK([
+RPMDB_INIT
+
+runroot rpm -U /build/RPMS/noarch/deptest-two-1.0-1.noarch.rpm
+runroot rpm -U /build/RPMS/noarch/deptest-four-1.0-1.noarch.rpm
+],
+[1],
+[],
+[error: Failed dependencies:
+ (deptest-five if deptest-four) is needed by (installed) deptest-two-1.0-1.noarch
+])
+AT_CLEANUP
+
+# ------------------------------
+#
+AT_SETUP([erase to break installed rich dependency])
+AT_KEYWORDS([install, boolean])
+RPMDB_INIT
+
+runroot rpmbuild --quiet -bb \
+ --define "pkg one" \
+ --define "reqs (deptest-three or deptest-five)" \
+ /data/SPECS/deptest.spec
+runroot rpmbuild --quiet -bb \
+ --define "pkg two" \
+ --define "cfls (deptest-five unless deptest-four)" \
+ /data/SPECS/deptest.spec
+runroot rpmbuild --quiet -bb \
+ --define "pkg three" \
+ /data/SPECS/deptest.spec
+runroot rpmbuild --quiet -bb \
+ --define "pkg four" \
+ /data/SPECS/deptest.spec
+runroot rpmbuild --quiet -bb \
+ --define "pkg five" \
+ /data/SPECS/deptest.spec
+
+# installed requires with "or" clause
+AT_CHECK([
+RPMDB_INIT
+
+runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-three-1.0-1.noarch.rpm
+runroot rpm -e deptest-three
+],
+[1],
+[],
+[error: Failed dependencies:
+ (deptest-three or deptest-five) is needed by (installed) deptest-one-1.0-1.noarch
+])
+
+# installed conflicts with "unless" clause
+AT_CHECK([
+RPMDB_INIT
+
+runroot rpm -U /build/RPMS/noarch/deptest-two-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-four-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-five-1.0-1.noarch.rpm
+runroot rpm -e deptest-four
+],
+[1],
+[],
+[error: Failed dependencies:
+ (deptest-five unless deptest-four) conflicts with (installed) deptest-two-1.0-1.noarch
+])
+AT_CLEANUP
--
2.33.1

@ -1,401 +0,0 @@
From 32b21da4bae5b8fbe0f42c31b723c4963b4b2512 Mon Sep 17 00:00:00 2001
From: Demi Marie Obenour <demi@invisiblethingslab.com>
Date: Thu, 6 May 2021 18:34:45 -0400
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.
Combined with:
5ff86764b17f31535cb247543a90dd739076ec38
b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8
9f03f42e2614a68f589f9db8fe76287146522c0c
b6dffb6dc5ffa2ddc389743f0507876cab341315 (mem-leak fix)
ae3d2d234ae47ff85229d3fce97a266fa1aa5a61 (use-after-free fix)
Fixes CVE-2021-3521.
---
rpmio/rpmpgp.c | 122 +++++++++++++++---
sign/rpmgensig.c | 2 +-
tests/Makefile.am | 3 +
tests/data/keys/CVE-2021-3521-badbind.asc | 25 ++++
.../data/keys/CVE-2021-3521-nosubsig-last.asc | 25 ++++
tests/data/keys/CVE-2021-3521-nosubsig.asc | 37 ++++++
tests/rpmsigdig.at | 28 ++++
7 files changed, 224 insertions(+), 18 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 d0688ebe9..3372d577d 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -515,7 +515,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)
{
@@ -528,10 +528,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
int mpil = pgpMpiLen(p);
if (p + mpil > pend)
break;
- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
- if (sigalg->setmpi(sigalg, i, p))
- break;
- }
+ if (sigalg->setmpi(sigalg, i, p))
+ break;
p += mpil;
}
@@ -604,7 +602,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
}
p = ((uint8_t *)v) + sizeof(*v);
- 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;
@@ -662,7 +660,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
if (p > (h + hlen))
return 1;
- 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 key: V%d\n"), version);
@@ -1041,36 +1039,127 @@ 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;
+}
+
+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 = xcalloc(1, sizeof(*digp));
- digp->tag = 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 */
+ int xx = 1; /* assume failure */
+
+ if (!(prevtag == PGPTAG_PUBLIC_SUBKEY &&
+ selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING))
+ 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 {
@@ -1105,8 +1194,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);
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index e5d191cc0..988a0f611 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -351,7 +351,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);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f742a9e1d..328234278 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -107,6 +107,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 000000000..aea00f9d7
--- /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 000000000..aea00f9d7
--- /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 000000000..3a2e7417f
--- /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 e1a3ab062..705fc5870 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -240,6 +240,34 @@ gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918
[])
AT_CLEANUP
+AT_SETUP([rpmkeys --import invalid keys])
+AT_KEYWORDS([rpmkeys import])
+RPMDB_INIT
+
+AT_CHECK([
+runroot rpmkeys --import /data/keys/CVE-2021-3521-badbind.asc
+],
+[1],
+[],
+[error: /data/keys/CVE-2021-3521-badbind.asc: key 1 import failed.]
+)
+AT_CHECK([
+runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig.asc
+],
+[1],
+[],
+[error: /data/keys/CVE-2021-3521-nosubsig.asc: key 1 import failed.]
+)
+
+AT_CHECK([
+runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig-last.asc
+],
+[1],
+[],
+[error: /data/keys/CVE-2021-3521-nosubsig-last.asc: key 1 import failed.]
+)
+AT_CLEANUP
+
# ------------------------------
# Test pre-built package verification
AT_SETUP([rpmkeys -K <signed> 1])
--
2.34.1

@ -0,0 +1,12 @@
diff '--color=auto' -rup rpm-4.17.0-orig/macros.in rpm-4.17.0/macros.in
--- rpm-4.17.0-orig/macros.in 2021-08-20 04:44:56.264259007 -0400
+++ rpm-4.17.0/macros.in 2022-01-26 20:11:26.864195884 -0500
@@ -140,7 +140,7 @@
%_buildshell /bin/sh
# The location of the rpm database file(s).
-%_dbpath %{_var}/lib/rpm
+%_dbpath %{_usr}/lib/sysimage/rpm
# The location of the rpm database file(s) after "rpm --rebuilddb".
%_dbpath_rebuild %{_dbpath}

@ -1,78 +0,0 @@
From 96888e99c5103d9dea5230c917b946732de2d302 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 22 Sep 2022 11:54:47 +0300
Subject: [PATCH] Add a handler for libselinux log messages (RhBug:2123719,
RhBug:2050774)
libselinux logs to stderr by default, which up to now has been just fine
with us. However somewhere around libselinux 3.2 it begun issuing
log messages for events discovered in selinux_status_updated().
We only call that to see whether the status *was* updated behind our
back and are not interested in these audit-style messages for our
functionality, but to suppress them while preserving actually relevant
errors and warnings, we need to have a log callback of our own. Might as
well forward them to rpmlog then.
SELINUX_ERROR and SELINUX_WARNING are pretty obvious, of SELINUX_AVC
selinux_set_callback(3) says it should be treated as SELINUX_ERROR if
not audited. The rest we suppress to debug messages, they may be handy
for diagnostics some day.
Note that this intentionally avoids explicit SELINUX_POLICYLOAD and
SELINUX_SETENFORCE cases in the switch: we don't want to introduce
libselinux >= 3.2 dependency just because of this silly thing.
---
plugins/selinux.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/plugins/selinux.c b/plugins/selinux.c
index 747f62d05..0f10331f0 100644
--- a/plugins/selinux.c
+++ b/plugins/selinux.c
@@ -18,6 +18,35 @@ static inline rpmlogLvl loglvl(int iserror)
return iserror ? RPMLOG_ERR : RPMLOG_DEBUG;
}
+static int logcb(int type, const char *fmt, ...)
+{
+ char *buf = NULL;
+ va_list ap;
+ int lvl;
+
+ switch (type) {
+ case SELINUX_ERROR:
+ case SELINUX_AVC:
+ lvl = RPMLOG_ERR;
+ break;
+ case SELINUX_WARNING:
+ lvl = RPMLOG_WARNING;
+ break;
+ default:
+ lvl = RPMLOG_DEBUG;
+ break;
+ }
+
+ va_start(ap, fmt);
+ rvasprintf(&buf, fmt, ap);
+ va_end(ap);
+
+ rpmlog(lvl, "libselinux: type %d: %s", type, buf);
+ free(buf);
+
+ return 0;
+}
+
static void sehandle_fini(int close_status)
{
if (sehandle) {
@@ -44,6 +73,7 @@ static rpmRC sehandle_init(int open_status)
if (selinux_status_open(0) < 0) {
return RPMRC_FAIL;
}
+ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &logcb);
} else if (!selinux_status_updated() && sehandle) {
return RPMRC_OK;
}
--
2.38.1

@ -0,0 +1,11 @@
--- rpm-4.18.90/macros.in.orig 2023-04-17 14:48:14.802719586 +0200
+++ rpm-4.18.90/macros.in 2023-04-17 14:48:25.268852972 +0200
@@ -236,7 +236,7 @@
%clamp_mtime_to_source_date_epoch 0
# If enabled, dilute user() and group() requires into recommends
-#%_use_weak_usergroup_deps 1
+%_use_weak_usergroup_deps 1
# The directory where newly built binary packages will be written.
%_rpmdir %{_topdir}/RPMS

@ -0,0 +1,12 @@
diff -up rpm-4.18.92/macros.in.orig rpm-4.18.92/macros.in
--- rpm-4.18.92/macros.in.orig 2023-08-02 17:56:49.858065935 +0200
+++ rpm-4.18.92/macros.in 2023-08-02 17:57:01.967988065 +0200
@@ -138,7 +138,7 @@
# sysusers helper binary (or a replacement script), uncomment to disable
#%__systemd_sysusers @__SYSTEMD_SYSUSERS@
-%__systemd_sysusers %{_rpmconfigdir}/sysusers.sh
+#%__systemd_sysusers %{_rpmconfigdir}/sysusers.sh
#
# Path to script that creates debug symbols in a /usr/lib/debug

@ -0,0 +1,14 @@
diff -up rpm-4.18.1/macros.in.orig rpm-4.18.1/macros.in
--- rpm-4.18.1/macros.in.orig 2023-03-15 13:52:55.211928040 +0100
+++ rpm-4.18.1/macros.in 2023-03-15 13:55:04.113129930 +0100
@@ -746,7 +746,9 @@ package or when debugging this package.\
%{?_javaclasspath:CLASSPATH=\"%{_javaclasspath}\"\
export CLASSPATH}\
PKG_CONFIG_PATH=\"${PKG_CONFIG_PATH}:%{_libdir}/pkgconfig:%{_datadir}/pkgconfig\"\
- export PKG_CONFIG_PATH
+ export PKG_CONFIG_PATH\
+ CONFIG_SITE=${CONFIG_SITE:-NONE}\
+ export CONFIG_SITE
%___build_pre \
%{___build_pre_env} \

@ -0,0 +1,18 @@
[Unit]
Description=RPM database migration to /usr
ConditionPathExists=/var/lib/rpm/.migratedb
# This should run before any daemons that may open the rpmdb
DefaultDependencies=no
After=sysinit.target
Before=basic.target shutdown.target
Conflicts=shutdown.target
# In case /var is remote-mounted
RequiresMountsFor=/var
[Service]
Type=oneshot
ExecStart=/usr/lib/rpm/rpmdb_migrate
[Install]
WantedBy=basic.target

@ -1,19 +1,19 @@
[Unit] [Unit]
Description=RPM database rebuild Description=RPM database rebuild
ConditionPathExists=/var/lib/rpm/.rebuilddb ConditionPathExists=/usr/lib/sysimage/rpm/.rebuilddb
# This should run before any daemons that may open the rpmdb # This should run before any daemons that may open the rpmdb
DefaultDependencies=no DefaultDependencies=no
After=sysinit.target After=sysinit.target
Before=basic.target shutdown.target Before=basic.target shutdown.target
Conflicts=shutdown.target Conflicts=shutdown.target
# In case /var is remote-mounted # In case /usr is remote-mounted
RequiresMountsFor=/var RequiresMountsFor=/usr
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/usr/bin/rpmdb --rebuilddb ExecStart=/usr/bin/rpmdb --rebuilddb
ExecStartPost=rm -f /var/lib/rpm/.rebuilddb ExecStartPost=rm -f /usr/lib/sysimage/rpm/.rebuilddb
[Install] [Install]
WantedBy=basic.target WantedBy=basic.target

@ -0,0 +1,40 @@
#!/bin/bash
# Script to migrate rpmdb from /var/lib/rpm to new rpmdb path in /usr
# Copyright (C) 2022 Neal Gompa <ngompa@fedoraproject.org>.
#
# Fedora-License-Identifier: GPLv2+
# SPDX-2.0-License-Identifier: GPL-2.0+
# SPDX-3.0-License-Identifier: GPL-2.0-or-later
#
# This program is free software.
# For more information on the license, see COPYING or
# <https://www.gnu.org/licenses/gpl-2.0.en.html>.
# For more information on free software, see
# <https://www.gnu.org/philosophy/free-sw.en.html>.
set -euo pipefail
# Script to migrate the rpmdb to /usr
rpmdb_path="$(rpm --eval '%_dbpath')"
rpmdb_path_old="/var/lib/rpm"
rpmdb_path_new="${rpmdb_path}"
if [ "${rpmdb_path}" = "${rpmdb_path_old}" ]; then
echo "The rpmdb path is still in /var, exiting!"
exit 0
fi
if [ -L "${rpmdb_path_old}" ]; then
echo "The rpmdb has already been migrated, exiting!"
rm -v "${rpmdb_path_old}/.migratedb"
exit 0
fi
rpm --verbose --rebuilddb
rm -rfv ${rpmdb_path_old}
ln -srv ${rpmdb_path_new} ${rpmdb_path_old}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save