Compare commits

...

No commits in common. 'c9' and 'c8' have entirely different histories.
c9 ... c8

2
.gitignore vendored

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

@ -1 +1 @@
4c70c0dc08aec5ba29f3ee72eda774bd32230f77 SOURCES/rpm-4.16.1.3.tar.bz2
3f8c3ef08f93eaeef12008055a43f6872306f8a2 SOURCES/rpm-4.14.3.tar.bz2

@ -0,0 +1,93 @@
From 1da9e839bb573b9187403983f5a69853ab364306 Mon Sep 17 00:00:00 2001
From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
Date: Sun, 17 Mar 2019 06:47:26 +0100
Subject: [PATCH] Add flag to use strip -g instead of full strip on DSOs
(RhBug:1663264)
The find-debuginfo.sh flag -g had exactly this meaning. But from
version rpm-4.13.0-alpha flag -g changes its behavior. It affects
both libraries and executables.
For some packages the original behavior was preferred. That is why
the new find-debuginfo.sh flag --g-libs is created.
Options -g and --g-libs are mutually exclusive.
Adjusted for rpm-4.14.2 in RHEL
--- rpm-4.14.2/scripts/find-debuginfo.sh.orig 2019-04-24 15:14:29.351010878 +0200
+++ rpm-4.14.2/scripts/find-debuginfo.sh 2019-04-24 15:19:42.296240705 +0200
@@ -4,6 +4,7 @@
#
# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n]
# [--keep-section SECTION] [--remove-section SECTION]
+# [--g-libs]
# [-j N] [--jobs N]
# [-o debugfiles.list]
# [-S debugsourcefiles.list]
@@ -16,6 +17,8 @@
# [builddir]
#
# The -g flag says to use strip -g instead of full strip on DSOs or EXEs.
+# The --g-libs flag says to use strip -g instead of full strip ONLY on DSOs.
+# Options -g and --g-libs are mutually exclusive.
# The -r flag says to use eu-strip --reloc-debug-sections.
# Use --keep-section SECTION or --remove-section SECTION to explicitly
# keep a (non-allocated) section in the main executable or explicitly
@@ -68,6 +71,9 @@
# With -g arg, pass it to strip on libraries or executables.
strip_g=false
+# With --g-libs arg, pass it to strip on libraries.
+strip_glibs=false
+
# with -r arg, pass --reloc-debug-sections to eu-strip.
strip_r=false
@@ -135,6 +141,9 @@
unique_debug_src_base=$2
shift
;;
+ --g-libs)
+ strip_glibs=true
+ ;;
-g)
strip_g=true
;;
@@ -204,6 +213,11 @@
exit 2
fi
+if ("$strip_g" = "true") && ("$strip_glibs" = "true"); then
+ echo >&2 "*** ERROR: -g and --g-libs cannot be used together"
+ exit 2
+fi
+
i=0
while ((i < nout)); do
outs[$i]="$BUILDDIR/${outs[$i]}"
@@ -237,6 +251,9 @@
application/x-executable*) g=-g ;;
application/x-pie-executable*) g=-g ;;
esac
+ $strip_glibs && case "$(file -bi "$2")" in
+ application/x-sharedlib*) g=-g ;;
+ esac
eu-strip --remove-comment $r $g ${keep_remove_args} -f "$1" "$2" || exit
chmod 444 "$1" || exit
}
@@ -430,8 +430,12 @@
# libraries. Other executable ELF files (like kernel modules) don't need it.
if [ "$include_minidebug" = "true" -a "$strip_g" = "false" ]; then
skip_mini=true
+ if [ "$strip_glibs" = "false" ]; then
+ case "$(file -bi "$f")" in
+ application/x-sharedlib*) skip_mini=false ;;
+ esac
+ fi
case "$(file -bi "$f")" in
- application/x-sharedlib*) skip_mini=false ;;
application/x-executable*) skip_mini=false ;;
application/x-pie-executable*) skip_mini=false ;;
esac

@ -0,0 +1,44 @@
From f00bb5be9caa62220c6aeaf3f7264840d5c089e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
Date: Tue, 5 Feb 2019 18:15:47 +0100
Subject: [PATCH] Add limits to autopatch macro
Limits allow to apply only range of patches with given parameters.
Useful if something needs to be done between patch sets. Allows applying
of patches with different -pX parameter in one spec file.
Resolves: #626
Co-authored-by: Florian Festi <ffesti@redhat.com>
---
macros.in | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/macros.in b/macros.in
index 7b5b63020..912ad5997 100644
--- a/macros.in
+++ b/macros.in
@@ -1265,11 +1265,19 @@ else\
end}
# Automatically apply all patches
-%autopatch(vp:)\
+# -m<min> Apply patches with number >= min only
+# -M<max> Apply patches with number <= max only
+%autopatch(vp:m:M:)\
%{lua:\
local options = rpm.expand("%{!-v:-q} %{-p:-p%{-p*}} ")\
+local low_limit = tonumber(rpm.expand("%{-m:%{-m*}}"))\
+local high_limit = tonumber(rpm.expand("%{-M:%{-M*}}"))\
for i, p in ipairs(patches) do\
- print(rpm.expand("%apply_patch -m %{basename:"..p.."} "..options..p.." "..i.."\\n"))\
+ local inum = patch_nums[i]\
+ if ((not low_limit or inum>=low_limit) and (not high_limit or inum<=high_limit)) \
+ then\
+ print(rpm.expand("%apply_patch -m %{basename:"..p.."} "..options..p.." "..i.."\\n")) \
+ end\
end}
# One macro to (optionally) do it all.
--
2.26.2

@ -0,0 +1,32 @@
From 38c03ddb18e86c84d89af695f72442d8365eb64e Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Tue, 21 Jul 2020 10:45:20 +0200
Subject: [PATCH] Always close libelf handle (#1313)
Otherwise executables that are not proper elf files are leaking libelf
handles. This results in file being left open (mmap'ed) and fails the
build on NFS as those files can't be deleted properly there.
Resolves: rhbz#1840728
See also: https://bugzilla.redhat.com/show_bug.cgi?id=1840728
---
build/files.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build/files.c b/build/files.c
index f675306f7..62489c07c 100644
--- a/build/files.c
+++ b/build/files.c
@@ -1935,8 +1935,8 @@ static int generateBuildIDs(FileList fl, ARGV_t *files)
if (terminate)
rc = 1;
}
- elf_end (elf);
}
+ elf_end (elf);
close (fd);
}
}
--
2.26.2

@ -0,0 +1,37 @@
From c4f285cff8f830447857e52848ecf909cedb192a Mon Sep 17 00:00:00 2001
Message-Id: <c4f285cff8f830447857e52848ecf909cedb192a.1543566970.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 6 Nov 2018 12:22:55 +0200
Subject: [PATCH] Document --noverify in the man page (RhBug:1646458)
Should've been in commit 765e2c72ae8be369ada41d4747b8999519a0e327
---
doc/rpm.8 | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/doc/rpm.8 b/doc/rpm.8
index 5ab61b2ac..31c51d821 100644
--- a/doc/rpm.8
+++ b/doc/rpm.8
@@ -104,7 +104,7 @@ Scripts and triggers:
[\fB--ignoresize\fR] [\fB--ignorearch\fR] [\fB--ignoreos\fR]
[\fB--includedocs\fR] [\fB--justdb\fR]
[\fB--nodeps\fR] [\fB--nodigest\fR] [\fB--noplugins\fR]
- [\fB--nocaps\fR] [\fB--noorder\fR]
+ [\fB--nocaps\fR] [\fB--noorder\fR] [\fB--noverify\fR]
[\fB--nosignature\fR] [\fB--noscripts\fR] [\fB--notriggers\fR]
[\fB--oldpackage\fR] [\fB--percent\fR] [\fB--prefix \fINEWPATH\fB\fR]
[\fB--relocate \fIOLDPATH\fB=\fINEWPATH\fB\fR]
@@ -315,6 +315,9 @@ Don't set file capabilities.
Don't reorder the packages for an install. The list of
packages would normally be reordered to satisfy dependencies.
.TP
+\fB--noverify\fR
+Don't perform verify package files prior to installation.
+.TP
\fB--noplugins\fR
Do not load and execute plugins.
.TP
--
2.19.2

@ -0,0 +1,40 @@
From 91ed417e8cc0a4f1ed45b1d8f6242c2ef9f441d3 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Fri, 20 Aug 2021 15:14:16 +0200
Subject: [PATCH 1/5] Don't segfault on missing priority tag
(cherry picked from commit fd57fc716231c8296d340fdb4c0f6eac176f7f7c)
Fixes: RHEL-39894
---
lib/rpmtriggers.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c
index c652981be..a9e63a241 100644
--- a/lib/rpmtriggers.c
+++ b/lib/rpmtriggers.c
@@ -523,7 +523,8 @@ rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
if (matchFunc(ts, te, pfx, sense)) {
for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++) {
struct rpmtd_s priorities;
- unsigned int priority;
+ unsigned int priority = 0;
+ unsigned int *priority_ptr;
unsigned int offset = rpmdbIndexIteratorPkgOffset(ii, i);
unsigned int tix = rpmdbIndexIteratorTagNum(ii, i);
@@ -541,7 +542,9 @@ rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offset);
headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM);
rpmtdSetIndex(&priorities, tix);
- priority = *rpmtdGetUint32(&priorities);
+ priority_ptr = rpmtdGetUint32(&priorities);
+ if (priority_ptr)
+ priority = *priority_ptr;
headerFree(trigH);
/* Store file trigger in array */
--
2.47.0

@ -0,0 +1,152 @@
From 13f70e3710b2df49a923cc6450ff4a8f86e65666 Mon Sep 17 00:00:00 2001
Message-Id: <13f70e3710b2df49a923cc6450ff4a8f86e65666.1555050140.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 20 Mar 2019 12:38:00 +0200
Subject: [PATCH] Fix FA_TOUCH on files with suid/sgid bits and/or capabilities
FA_TOUCH used to set suffix to "" instead of NULL which causes fsmCommit()
to rename the file onto itself, which is a bit dumb but mostly harmless
with regular permission. On suid/sgid/capabilities we strip any extra
privileges on rename to make sure hardlinks are neutered, and because
rename occurs after other permissions etc setting, on FA_TOUCH those
extra privileges are stripped and much brokenness will follow.
A more minimal fix would be a strategically placed strcmp(), but NULL
is what the rest of the fsm expects for no suffix and differentiating
between empty and NULL suffix is too subtle for its own good as
witnessed here. So now, NULL suffix is no suffix again and the rest
of the code will do the right thing except where related to creation,
and creation is what FA_TOUCH wont do so lets just explicitly skip it
and restore the original code otherwise. The goto is ugly but reindenting
gets even uglier, shrug. Add a test-case to go with it.
This has been broken since its introduction in commit
79ca74e15e15c1d91a9a31a9ee90abc91736f390 so all current 4.14.x versions
are affected.
---
lib/fsm.c | 17 ++++++++++----
tests/data/SPECS/replacetest.spec | 2 +-
tests/rpmverify.at | 38 ++++++++++++++++++++++++++++++-
3 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/lib/fsm.c b/lib/fsm.c
index 8eb2c185c..432bcbd90 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -898,12 +898,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
action = rpmfsGetAction(fs, rpmfiFX(fi));
skip = XFA_SKIPPING(action);
- suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
if (action != FA_TOUCH) {
- fpath = fsmFsPath(fi, suffix);
+ suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
} else {
- fpath = fsmFsPath(fi, "");
+ suffix = NULL;
}
+ fpath = fsmFsPath(fi, suffix);
/* Remap file perms, owner, and group. */
rc = rpmfiStat(fi, 1, &sb);
@@ -926,6 +926,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
if (!skip) {
int setmeta = 1;
+ /* When touching we don't need any of this... */
+ if (action == FA_TOUCH)
+ goto touch;
+
/* Directories replacing something need early backup */
if (!suffix) {
rc = fsmBackup(fi, action);
@@ -934,7 +938,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
if (!suffix) {
rc = fsmVerify(fpath, fi);
} else {
- rc = (action == FA_TOUCH) ? 0 : RPMERR_ENOENT;
+ rc = RPMERR_ENOENT;
}
if (S_ISREG(sb.st_mode)) {
@@ -970,11 +974,14 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
if (!IS_DEV_LOG(fpath))
rc = RPMERR_UNKNOWN_FILETYPE;
}
+
+touch:
/* Set permissions, timestamps etc for non-hardlink entries */
if (!rc && setmeta) {
rc = fsmSetmeta(fpath, fi, plugins, action, &sb, nofcaps);
}
} else if (firsthardlink >= 0 && rpmfiArchiveHasContent(fi)) {
+ /* On FA_TOUCH no hardlinks are created thus this is skipped. */
/* we skip the hard linked file containing the content */
/* write the content to the first used instead */
char *fn = rpmfilesFN(files, firsthardlink);
@@ -987,7 +994,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
if (rc) {
if (!skip) {
/* XXX only erase if temp fn w suffix is in use */
- if (suffix && (action != FA_TOUCH)) {
+ if (suffix) {
(void) fsmRemove(fpath, sb.st_mode);
}
errno = saveerrno;
diff --git a/tests/data/SPECS/replacetest.spec b/tests/data/SPECS/replacetest.spec
index 54974567b..d5a1729d3 100644
--- a/tests/data/SPECS/replacetest.spec
+++ b/tests/data/SPECS/replacetest.spec
@@ -46,4 +46,4 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,%{user},%{grp},-)
-/opt/*
+%{?fileattr} /opt/*
diff --git a/tests/rpmverify.at b/tests/rpmverify.at
index 52ee2abfb..f7dd57531 100644
--- a/tests/rpmverify.at
+++ b/tests/rpmverify.at
@@ -575,3 +575,39 @@
],
[])
AT_CLEANUP
+
+AT_SETUP([Upgraded verification with min_writes 5 (suid files)])
+AT_KEYWORDS([upgrade verify min_writes])
+AT_CHECK([
+RPMDB_CLEAR
+RPMDB_INIT
+tf="${RPMTEST}"/opt/foo
+rm -rf "${tf}" "${tf}".rpm*
+rm -rf "${TOPDIR}"
+
+for v in "1.0" "2.0"; do
+ runroot rpmbuild --quiet -bb \
+ --define "ver $v" \
+ --define "filetype file" \
+ --define "filedata foo" \
+ --define "fileattr %attr(2755,-,-)" \
+ /data/SPECS/replacetest.spec
+done
+
+runroot rpm -U /build/RPMS/noarch/replacetest-1.0-1.noarch.rpm
+runroot rpm -Va --nouser --nogroup replacetest
+runroot rpm -U \
+ --define "_minimize_writes 1" \
+ /build/RPMS/noarch/replacetest-2.0-1.noarch.rpm
+runroot rpm -Va --nouser --nogroup replacetest
+chmod 777 "${tf}"
+runroot rpm -U \
+ --oldpackage \
+ --define "_minimize_writes 1" \
+ /build/RPMS/noarch/replacetest-1.0-1.noarch.rpm
+runroot rpm -Va --nouser --nogroup replacetest
+],
+[0],
+[],
+[])
+AT_CLEANUP
--
2.20.1

@ -0,0 +1,41 @@
From 1fd84fa0cfa6e493d1c15edfb7d9f0bb05e4f920 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Thu, 2 May 2019 17:17:56 +0200
Subject: [PATCH] Fix brp-strip-static-archive parallelism
The change made in fc2c986 can break for large values of %_smp_build_ncpus as
this many processes are able to overflow the following pipe.
Thanks to Denys Vlasenko for testing this.
This change solves this problem by running a whole processing pileline for each
parallel (file) process. This has also the benefit of running at least some
stip commands in parallel.
The -n param fro xargs was increased to 32 to further reduce the over head of
spawing the helpers as they are now needed for each run of the file command.
---
scripts/brp-strip-static-archive | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/scripts/brp-strip-static-archive b/scripts/brp-strip-static-archive
index 4dc449061..13d9a098b 100755
--- a/scripts/brp-strip-static-archive
+++ b/scripts/brp-strip-static-archive
@@ -13,10 +13,6 @@ Darwin*) exit 0 ;;
esac
# Strip static libraries.
-for f in `find "$RPM_BUILD_ROOT" -type f | \
- grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug" | \
- xargs -r -P$NCPUS -n16 file | sed 's/: */: /' | \
- grep 'current ar archive' | \
- sed -n -e 's/^\(.*\):[ ]*current ar archive/\1/p'`; do
- $STRIP -g "$f"
-done
+find "$RPM_BUILD_ROOT" -type f | \
+ grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug" | \
+ xargs -r -P$NCPUS -n32 sh -c "file \"\$@\" | sed 's/: */: /' | grep 'current ar archive' | sed -n -e 's/^\(.*\):[ ]*current ar archive/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0
--
2.21.0

@ -0,0 +1,102 @@
From 60066aba510b3ff4a7db092021aae71948e3f8be Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 4 Jun 2020 11:18:01 +0300
Subject: [PATCH] Fix python ts.addErase() not raising exception on not-found
packages
The code would only raise an exception if TransactionSetCore.addErase()
returned an error, but the catch is that with many kinds of argument
types we'd silently skip the whole addition because no headers were found.
This looks to be a regression introduced some eleven years ago in
commit 9b20c706a4f93266450fae2f94007343b2e8fd9e.
As a special case, a match iterator argument will not raise an exception
if it doesn't actually match anything.
Fixes: #1214
---
python/rpm/transaction.py | 26 +++++++++++++++-----------
tests/rpmpython.at | 22 ++++++++++++++++++++++
2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/python/rpm/transaction.py b/python/rpm/transaction.py
index 7c4a551d3..3c9ddb207 100644
--- a/python/rpm/transaction.py
+++ b/python/rpm/transaction.py
@@ -91,14 +91,22 @@ class TransactionSet(TransactionSetCore):
def addErase(self, item):
hdrs = []
- if isinstance(item, rpm.hdr):
- hdrs = [item]
- elif isinstance(item, rpm.mi):
+ # match iterators are passed on as-is
+ if isinstance(item, rpm.mi):
hdrs = item
- elif isinstance(item, int):
- hdrs = self.dbMatch(rpm.RPMDBI_PACKAGES, item)
- elif isinstance(item, _string_types):
- hdrs = self.dbMatch(rpm.RPMDBI_LABEL, item)
+ elif isinstance(item, rpm.hdr):
+ hdrs.append(item)
+ elif isinstance(item, (int, _string_types)):
+ if isinstance(item, int):
+ dbi = rpm.RPMDBI_PACKAGES
+ else:
+ dbi = rpm.RPMDBI_LABEL
+
+ for h in self.dbMatch(dbi, item):
+ hdrs.append(h)
+
+ if not hdrs:
+ raise rpm.error("package not installed")
else:
raise TypeError("invalid type %s" % type(item))
@@ -106,10 +114,6 @@ class TransactionSet(TransactionSetCore):
if not TransactionSetCore.addErase(self, h):
raise rpm.error("package not installed")
- # garbage collection should take care but just in case...
- if isinstance(hdrs, rpm.mi):
- del hdrs
-
def run(self, callback, data):
rc = TransactionSetCore.run(self, callback, data, self._probFilter)
diff --git a/tests/rpmpython.at b/tests/rpmpython.at
index 3a7c251f1..de39c8417 100644
--- a/tests/rpmpython.at
+++ b/tests/rpmpython.at
@@ -201,6 +201,28 @@ for e in ts:
[foo-1.0-1.noarch]
)
+RPMPY_TEST([add erasure to transaction],[
+ts = rpm.ts()
+for i in ['foo', 1234]:
+ myprint('addErase %s' % i)
+ try:
+ ts.addErase(i)
+ except rpm.error as err:
+ myprint(err)
+myprint('addErase mi')
+mi = ts.dbMatch('name', 'foo')
+try:
+ ts.addErase(mi)
+except rpm.error as err:
+ myprint(err)
+],
+[addErase foo
+package not installed
+addErase 1234
+package not installed
+addErase mi]
+)
+
RPMPY_TEST([add bogus package to transaction 1],[
ts = rpm.ts()
h = rpm.hdr()
--
2.26.2

@ -0,0 +1,50 @@
From ed6c5573c09611ff9522ed290ef9d1ba717d8019 Mon Sep 17 00:00:00 2001
Message-Id: <ed6c5573c09611ff9522ed290ef9d1ba717d8019.1574331915.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 21 Nov 2019 12:22:45 +0200
Subject: [PATCH] Fix resource leaks on zstd open error paths
If zstd stream initialization fails, the opened fd and the stream
itself are leaked. Handle error exit in a central label.
---
rpmio/rpmio.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c
index 243942411..10ba20cd6 100644
--- a/rpmio/rpmio.c
+++ b/rpmio/rpmio.c
@@ -1128,13 +1128,13 @@ static rpmzstd rpmzstdNew(int fdno, const char *fmode)
if ((flags & O_ACCMODE) == O_RDONLY) { /* decompressing */
if ((_stream = (void *) ZSTD_createDStream()) == NULL
|| ZSTD_isError(ZSTD_initDStream(_stream))) {
- return NULL;
+ goto err;
}
nb = ZSTD_DStreamInSize();
} else { /* compressing */
if ((_stream = (void *) ZSTD_createCStream()) == NULL
|| ZSTD_isError(ZSTD_initCStream(_stream, level))) {
- return NULL;
+ goto err;
}
nb = ZSTD_CStreamOutSize();
}
@@ -1149,6 +1149,14 @@ static rpmzstd rpmzstdNew(int fdno, const char *fmode)
zstd->b = xmalloc(nb);
return zstd;
+
+err:
+ fclose(fp);
+ if ((flags & O_ACCMODE) == O_RDONLY)
+ ZSTD_freeDStream(_stream);
+ else
+ ZSTD_freeCStream(_stream);
+ return NULL;
}
static FD_t zstdFdopen(FD_t fd, int fdno, const char * fmode)
--
2.23.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

@ -0,0 +1,53 @@
From 6b6c4d881dc6fc99f949dac4aaf9a513542f9956 Mon Sep 17 00:00:00 2001
Message-Id: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 3 Oct 2018 15:22:55 +0300
Subject: [PATCH 1/5] Honor PYTHON from configure when running tests
Pass PYTHON from configure down through all the nutty layers of make
to allow running test-suite with Python 3. In theory that is.
(cherry picked from commit dcd5ab67c40b543f22b07df8c1028c34b94a7929)
---
tests/Makefile.am | 1 +
tests/atlocal.in | 3 ++-
tests/local.at | 2 +-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index eaf817cc2..21ca216a8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -117,6 +117,7 @@ atlocal: atlocal.in Makefile
-e "s,[@]usrlibdir[@],$(libdir)," \
-e "s,[@]execprefix[@],$(exec_prefix)," \
-e "s,[@]RPMCONFIGDIR[@],$(rpmconfigdir)," \
+ -e "s,[@]PYTHON[@],$(PYTHON)," \
< $(srcdir)/atlocal.in > atlocal
DISTCLEANFILES = atlocal
EXTRA_DIST += atlocal.in
diff --git a/tests/atlocal.in b/tests/atlocal.in
index d7d837f45..3b1474b56 100644
--- rpm-4.14.3/tests/atlocal.in.orig 2020-04-28 14:19:26.866602968 +0200
+++ rpm-4.14.3/tests/atlocal.in 2020-04-28 14:21:07.977910054 +0200
@@ -3,7 +3,8 @@
PATH="${abs_builddir}/testing@rpmbindir@:${abs_builddir}/testing@usrbindir@:$PATH"
export PATH
-PYLIBDIR=`python2 -c "from distutils.sysconfig import get_python_lib; import sys; sys.stdout.write(get_python_lib(1,0,'@execprefix@'))"`
+PYTHON=@PYTHON@
+PYLIBDIR=$(${PYTHON} -c "from distutils.sysconfig import get_python_lib; import sys; sys.stdout.write(get_python_lib(1,0,'@execprefix@'))")
PYTHONPATH="${abs_builddir}/testing${PYLIBDIR}"
export PYTHONPATH
--- rpm-4.14.3/tests/local.at.orig 2020-04-28 14:28:33.106664317 +0200
+++ rpm-4.14.3/tests/local.at 2020-04-28 14:29:02.064038653 +0200
@@ -18,7 +18,7 @@
sys.stdout.write('%s\n' % msg)
$1
EOF
-python2 test.py
+${PYTHON} test.py test.py
]])
m4_define([RPMPY_CHECK],[

@ -0,0 +1,656 @@
From 84920f898315d09a57a3f1067433eaeb7de5e830 Mon Sep 17 00:00:00 2001
Message-Id: <84920f898315d09a57a3f1067433eaeb7de5e830.1554884444.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 22 Feb 2019 19:44:16 +0200
Subject: [PATCH] In Python 3, return all our string data as surrogate-escaped
utf-8 strings
In the almost ten years of rpm sort of supporting Python 3 bindings, quite
obviously nobody has actually tried to use them. There's a major mismatch
between what the header API outputs (bytes) and what all the other APIs
accept (strings), resulting in hysterical TypeErrors all over the place,
including but not limited to labelCompare() (RhBug:1631292). Also a huge
number of other places have been returning strings and silently assuming
utf-8 through use of Py_BuildValue("s", ...), which will just irrevocably
fail when non-utf8 data is encountered.
The politically Python 3-correct solution would be declaring all our data
as bytes with unspecified encoding - that's exactly what it historically is.
However doing so would by definition break every single rpm script people
have developed on Python 2. And when 99% of the rpm content in the world
actually is utf-8 encoded even if it doesn't say so (and in recent times
packages even advertise themselves as utf-8 encoded), the bytes-only route
seems a wee bit too draconian, even to this grumpy old fella.
Instead, route all our string returns through a single helper macro
which on Python 2 just does what we always did, but in Python 3 converts
the data to surrogate-escaped utf-8 strings. This makes stuff "just work"
out of the box pretty much everywhere even with Python 3 (including
our own test-suite!), while still allowing to handle the non-utf8 case.
Handling the non-utf8 case is a bit more uglier but still possible,
which is exactly how you want corner-cases to be. There might be some
uses for retrieving raw byte data from the header, but worrying about
such an API is a case for some other rainy day, for now we mostly only
care that stuff works again.
Also add test-cases for mixed data source labelCompare() and
non-utf8 insert to + retrieve from header.
---
python/header-py.c | 2 +-
python/rpmds-py.c | 8 ++++----
python/rpmfd-py.c | 6 +++---
python/rpmfi-py.c | 24 ++++++++++++------------
python/rpmfiles-py.c | 26 +++++++++++++-------------
python/rpmkeyring-py.c | 2 +-
python/rpmmacro-py.c | 2 +-
python/rpmmodule.c | 2 +-
python/rpmps-py.c | 8 ++++----
python/rpmstrpool-py.c | 2 +-
python/rpmsystem-py.h | 7 +++++++
python/rpmtd-py.c | 2 +-
python/rpmte-py.c | 16 ++++++++--------
python/rpmts-py.c | 11 ++++++-----
python/spec-py.c | 8 ++++----
tests/local.at | 1 +
tests/rpmpython.at | 34 ++++++++++++++++++++++++++++++++++
17 files changed, 102 insertions(+), 59 deletions(-)
diff --git a/python/header-py.c b/python/header-py.c
index c9d54e869..93c241cb7 100644
--- a/python/header-py.c
+++ b/python/header-py.c
@@ -231,7 +231,7 @@ static PyObject * hdrFormat(hdrObject * s, PyObject * args, PyObject * kwds)
return NULL;
}
- result = Py_BuildValue("s", r);
+ result = utf8FromString(r);
free(r);
return result;
diff --git a/python/rpmds-py.c b/python/rpmds-py.c
index 39b26628e..ecc9af9d5 100644
--- a/python/rpmds-py.c
+++ b/python/rpmds-py.c
@@ -31,19 +31,19 @@ rpmds_Ix(rpmdsObject * s)
static PyObject *
rpmds_DNEVR(rpmdsObject * s)
{
- return Py_BuildValue("s", rpmdsDNEVR(s->ds));
+ return utf8FromString(rpmdsDNEVR(s->ds));
}
static PyObject *
rpmds_N(rpmdsObject * s)
{
- return Py_BuildValue("s", rpmdsN(s->ds));
+ return utf8FromString(rpmdsN(s->ds));
}
static PyObject *
rpmds_EVR(rpmdsObject * s)
{
- return Py_BuildValue("s", rpmdsEVR(s->ds));
+ return utf8FromString(rpmdsEVR(s->ds));
}
static PyObject *
@@ -261,7 +261,7 @@ rpmds_subscript(rpmdsObject * s, PyObject * key)
ix = (int) PyInt_AsLong(key);
rpmdsSetIx(s->ds, ix);
- return Py_BuildValue("s", rpmdsDNEVR(s->ds));
+ return utf8FromString(rpmdsDNEVR(s->ds));
}
static PyMappingMethods rpmds_as_mapping = {
diff --git a/python/rpmfd-py.c b/python/rpmfd-py.c
index 85fb0cd24..4b05cce5f 100644
--- a/python/rpmfd-py.c
+++ b/python/rpmfd-py.c
@@ -327,17 +327,17 @@ static PyObject *rpmfd_get_closed(rpmfdObject *s)
static PyObject *rpmfd_get_name(rpmfdObject *s)
{
/* XXX: rpm returns non-paths with [mumble], python files use <mumble> */
- return Py_BuildValue("s", Fdescr(s->fd));
+ return utf8FromString(Fdescr(s->fd));
}
static PyObject *rpmfd_get_mode(rpmfdObject *s)
{
- return Py_BuildValue("s", s->mode);
+ return utf8FromString(s->mode);
}
static PyObject *rpmfd_get_flags(rpmfdObject *s)
{
- return Py_BuildValue("s", s->flags);
+ return utf8FromString(s->flags);
}
static PyGetSetDef rpmfd_getseters[] = {
diff --git a/python/rpmfi-py.c b/python/rpmfi-py.c
index 8d2f926d0..db405c231 100644
--- a/python/rpmfi-py.c
+++ b/python/rpmfi-py.c
@@ -41,19 +41,19 @@ rpmfi_DX(rpmfiObject * s, PyObject * unused)
static PyObject *
rpmfi_BN(rpmfiObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmfiBN(s->fi));
+ return utf8FromString(rpmfiBN(s->fi));
}
static PyObject *
rpmfi_DN(rpmfiObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmfiDN(s->fi));
+ return utf8FromString(rpmfiDN(s->fi));
}
static PyObject *
rpmfi_FN(rpmfiObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmfiFN(s->fi));
+ return utf8FromString(rpmfiFN(s->fi));
}
static PyObject *
@@ -98,7 +98,7 @@ rpmfi_Digest(rpmfiObject * s, PyObject * unused)
{
char *digest = rpmfiFDigestHex(s->fi, NULL);
if (digest) {
- PyObject *dig = Py_BuildValue("s", digest);
+ PyObject *dig = utf8FromString(digest);
free(digest);
return dig;
} else {
@@ -109,7 +109,7 @@ rpmfi_Digest(rpmfiObject * s, PyObject * unused)
static PyObject *
rpmfi_FLink(rpmfiObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmfiFLink(s->fi));
+ return utf8FromString(rpmfiFLink(s->fi));
}
static PyObject *
@@ -133,13 +133,13 @@ rpmfi_FMtime(rpmfiObject * s, PyObject * unused)
static PyObject *
rpmfi_FUser(rpmfiObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmfiFUser(s->fi));
+ return utf8FromString(rpmfiFUser(s->fi));
}
static PyObject *
rpmfi_FGroup(rpmfiObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmfiFGroup(s->fi));
+ return utf8FromString(rpmfiFGroup(s->fi));
}
static PyObject *
@@ -155,7 +155,7 @@ rpmfi_FClass(rpmfiObject * s, PyObject * unused)
if ((FClass = rpmfiFClass(s->fi)) == NULL)
FClass = "";
- return Py_BuildValue("s", FClass);
+ return utf8FromString(FClass);
}
static PyObject *
@@ -208,7 +208,7 @@ rpmfi_iternext(rpmfiObject * s)
Py_INCREF(Py_None);
PyTuple_SET_ITEM(result, 0, Py_None);
} else
- PyTuple_SET_ITEM(result, 0, Py_BuildValue("s", FN));
+ PyTuple_SET_ITEM(result, 0, utf8FromString(FN));
PyTuple_SET_ITEM(result, 1, PyLong_FromLongLong(FSize));
PyTuple_SET_ITEM(result, 2, PyInt_FromLong(FMode));
PyTuple_SET_ITEM(result, 3, PyInt_FromLong(FMtime));
@@ -222,12 +222,12 @@ rpmfi_iternext(rpmfiObject * s)
Py_INCREF(Py_None);
PyTuple_SET_ITEM(result, 10, Py_None);
} else
- PyTuple_SET_ITEM(result, 10, Py_BuildValue("s", FUser));
+ PyTuple_SET_ITEM(result, 10, utf8FromString(FUser));
if (FGroup == NULL) {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(result, 11, Py_None);
} else
- PyTuple_SET_ITEM(result, 11, Py_BuildValue("s", FGroup));
+ PyTuple_SET_ITEM(result, 11, utf8FromString(FGroup));
PyTuple_SET_ITEM(result, 12, rpmfi_Digest(s, NULL));
} else
@@ -313,7 +313,7 @@ rpmfi_subscript(rpmfiObject * s, PyObject * key)
ix = (int) PyInt_AsLong(key);
rpmfiSetFX(s->fi, ix);
- return Py_BuildValue("s", rpmfiFN(s->fi));
+ return utf8FromString(rpmfiFN(s->fi));
}
static PyMappingMethods rpmfi_as_mapping = {
diff --git a/python/rpmfiles-py.c b/python/rpmfiles-py.c
index bc07dbeaf..557246cae 100644
--- a/python/rpmfiles-py.c
+++ b/python/rpmfiles-py.c
@@ -41,37 +41,37 @@ static PyObject *rpmfile_dx(rpmfileObject *s)
static PyObject *rpmfile_name(rpmfileObject *s)
{
char * fn = rpmfilesFN(s->files, s->ix);
- PyObject *o = Py_BuildValue("s", fn);
+ PyObject *o = utf8FromString(fn);
free(fn);
return o;
}
static PyObject *rpmfile_basename(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesBN(s->files, s->ix));
+ return utf8FromString(rpmfilesBN(s->files, s->ix));
}
static PyObject *rpmfile_dirname(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesDN(s->files, rpmfilesDI(s->files, s->ix)));
+ return utf8FromString(rpmfilesDN(s->files, rpmfilesDI(s->files, s->ix)));
}
static PyObject *rpmfile_orig_name(rpmfileObject *s)
{
char * fn = rpmfilesOFN(s->files, s->ix);
- PyObject *o = Py_BuildValue("s", fn);
+ PyObject *o = utf8FromString(fn);
free(fn);
return o;
}
static PyObject *rpmfile_orig_basename(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesOBN(s->files, s->ix));
+ return utf8FromString(rpmfilesOBN(s->files, s->ix));
}
static PyObject *rpmfile_orig_dirname(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesODN(s->files, rpmfilesODI(s->files, s->ix)));
+ return utf8FromString(rpmfilesODN(s->files, rpmfilesODI(s->files, s->ix)));
}
static PyObject *rpmfile_mode(rpmfileObject *s)
{
@@ -105,17 +105,17 @@ static PyObject *rpmfile_nlink(rpmfileObject *s)
static PyObject *rpmfile_linkto(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesFLink(s->files, s->ix));
+ return utf8FromString(rpmfilesFLink(s->files, s->ix));
}
static PyObject *rpmfile_user(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesFUser(s->files, s->ix));
+ return utf8FromString(rpmfilesFUser(s->files, s->ix));
}
static PyObject *rpmfile_group(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesFGroup(s->files, s->ix));
+ return utf8FromString(rpmfilesFGroup(s->files, s->ix));
}
static PyObject *rpmfile_fflags(rpmfileObject *s)
@@ -145,7 +145,7 @@ static PyObject *rpmfile_digest(rpmfileObject *s)
NULL, &diglen);
if (digest) {
char * hex = pgpHexStr(digest, diglen);
- PyObject *o = Py_BuildValue("s", hex);
+ PyObject *o = utf8FromString(hex);
free(hex);
return o;
}
@@ -154,17 +154,17 @@ static PyObject *rpmfile_digest(rpmfileObject *s)
static PyObject *rpmfile_class(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesFClass(s->files, s->ix));
+ return utf8FromString(rpmfilesFClass(s->files, s->ix));
}
static PyObject *rpmfile_caps(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesFCaps(s->files, s->ix));
+ return utf8FromString(rpmfilesFCaps(s->files, s->ix));
}
static PyObject *rpmfile_langs(rpmfileObject *s)
{
- return Py_BuildValue("s", rpmfilesFLangs(s->files, s->ix));
+ return utf8FromString(rpmfilesFLangs(s->files, s->ix));
}
static PyObject *rpmfile_links(rpmfileObject *s)
diff --git a/python/rpmkeyring-py.c b/python/rpmkeyring-py.c
index d5f131e42..8968e0513 100644
--- a/python/rpmkeyring-py.c
+++ b/python/rpmkeyring-py.c
@@ -38,7 +38,7 @@ static PyObject *rpmPubkey_new(PyTypeObject *subtype,
static PyObject * rpmPubkey_Base64(rpmPubkeyObject *s)
{
char *b64 = rpmPubkeyBase64(s->pubkey);
- PyObject *res = Py_BuildValue("s", b64);
+ PyObject *res = utf8FromString(b64);
free(b64);
return res;
}
diff --git a/python/rpmmacro-py.c b/python/rpmmacro-py.c
index 3cb1a51f5..d8a365547 100644
--- a/python/rpmmacro-py.c
+++ b/python/rpmmacro-py.c
@@ -52,7 +52,7 @@ rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds)
if (rpmExpandMacros(NULL, macro, &str, 0) < 0)
PyErr_SetString(pyrpmError, "error expanding macro");
else
- res = Py_BuildValue("s", str);
+ res = utf8FromString(str);
free(str);
}
return res;
diff --git a/python/rpmmodule.c b/python/rpmmodule.c
index 3faad23c7..05032edc7 100644
--- a/python/rpmmodule.c
+++ b/python/rpmmodule.c
@@ -237,7 +237,7 @@ static void addRpmTags(PyObject *module)
PyModule_AddIntConstant(module, tagname, tagval);
pyval = PyInt_FromLong(tagval);
- pyname = Py_BuildValue("s", shortname);
+ pyname = utf8FromString(shortname);
PyDict_SetItem(dict, pyval, pyname);
Py_DECREF(pyval);
Py_DECREF(pyname);
diff --git a/python/rpmps-py.c b/python/rpmps-py.c
index bdc899a60..902b2ae63 100644
--- a/python/rpmps-py.c
+++ b/python/rpmps-py.c
@@ -18,12 +18,12 @@ static PyObject *rpmprob_get_type(rpmProblemObject *s, void *closure)
static PyObject *rpmprob_get_pkgnevr(rpmProblemObject *s, void *closure)
{
- return Py_BuildValue("s", rpmProblemGetPkgNEVR(s->prob));
+ return utf8FromString(rpmProblemGetPkgNEVR(s->prob));
}
static PyObject *rpmprob_get_altnevr(rpmProblemObject *s, void *closure)
{
- return Py_BuildValue("s", rpmProblemGetAltNEVR(s->prob));
+ return utf8FromString(rpmProblemGetAltNEVR(s->prob));
}
static PyObject *rpmprob_get_key(rpmProblemObject *s, void *closure)
@@ -38,7 +38,7 @@ static PyObject *rpmprob_get_key(rpmProblemObject *s, void *closure)
static PyObject *rpmprob_get_str(rpmProblemObject *s, void *closure)
{
- return Py_BuildValue("s", rpmProblemGetStr(s->prob));
+ return utf8FromString(rpmProblemGetStr(s->prob));
}
static PyObject *rpmprob_get_num(rpmProblemObject *s, void *closure)
@@ -59,7 +59,7 @@ static PyGetSetDef rpmprob_getseters[] = {
static PyObject *rpmprob_str(rpmProblemObject *s)
{
char *str = rpmProblemString(s->prob);
- PyObject *res = Py_BuildValue("s", str);
+ PyObject *res = utf8FromString(str);
free(str);
return res;
}
diff --git a/python/rpmstrpool-py.c b/python/rpmstrpool-py.c
index 356bd1de5..a56e2b540 100644
--- a/python/rpmstrpool-py.c
+++ b/python/rpmstrpool-py.c
@@ -44,7 +44,7 @@ static PyObject *strpool_id2str(rpmstrPoolObject *s, PyObject *item)
const char *str = rpmstrPoolStr(s->pool, id);
if (str)
- ret = PyBytes_FromString(str);
+ ret = utf8FromString(str);
else
PyErr_SetObject(PyExc_KeyError, item);
}
diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
index 955d60cd3..87c750571 100644
--- a/python/rpmsystem-py.h
+++ b/python/rpmsystem-py.h
@@ -19,4 +19,11 @@
#define PyInt_AsSsize_t PyLong_AsSsize_t
#endif
+/* In Python 3, we return all strings as surrogate-escaped utf-8 */
+#if PY_MAJOR_VERSION >= 3
+#define utf8FromString(_s) PyUnicode_DecodeUTF8(_s, strlen(_s), "surrogateescape")
+#else
+#define utf8FromString(_s) PyBytes_FromString(_s)
+#endif
+
#endif /* H_SYSTEM_PYTHON */
diff --git a/python/rpmtd-py.c b/python/rpmtd-py.c
index 247c7502a..23ca10517 100644
--- a/python/rpmtd-py.c
+++ b/python/rpmtd-py.c
@@ -17,7 +17,7 @@ PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass)
switch (tclass) {
case RPM_STRING_CLASS:
- res = PyBytes_FromString(rpmtdGetString(td));
+ res = utf8FromString(rpmtdGetString(td));
break;
case RPM_NUMERIC_CLASS:
res = PyLong_FromLongLong(rpmtdGetNumber(td));
diff --git a/python/rpmte-py.c b/python/rpmte-py.c
index 99ff2f496..2b3745754 100644
--- a/python/rpmte-py.c
+++ b/python/rpmte-py.c
@@ -54,49 +54,49 @@ rpmte_TEType(rpmteObject * s, PyObject * unused)
static PyObject *
rpmte_N(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteN(s->te));
+ return utf8FromString(rpmteN(s->te));
}
static PyObject *
rpmte_E(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteE(s->te));
+ return utf8FromString(rpmteE(s->te));
}
static PyObject *
rpmte_V(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteV(s->te));
+ return utf8FromString(rpmteV(s->te));
}
static PyObject *
rpmte_R(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteR(s->te));
+ return utf8FromString(rpmteR(s->te));
}
static PyObject *
rpmte_A(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteA(s->te));
+ return utf8FromString(rpmteA(s->te));
}
static PyObject *
rpmte_O(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteO(s->te));
+ return utf8FromString(rpmteO(s->te));
}
static PyObject *
rpmte_NEVR(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteNEVR(s->te));
+ return utf8FromString(rpmteNEVR(s->te));
}
static PyObject *
rpmte_NEVRA(rpmteObject * s, PyObject * unused)
{
- return Py_BuildValue("s", rpmteNEVRA(s->te));
+ return utf8FromString(rpmteNEVRA(s->te));
}
static PyObject *
diff --git a/python/rpmts-py.c b/python/rpmts-py.c
index 1ddfc9a1e..96e3bb28e 100644
--- a/python/rpmts-py.c
+++ b/python/rpmts-py.c
@@ -230,8 +230,9 @@ rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
PyEval_RestoreThread(cbInfo->_save);
- args = Py_BuildValue("(Oissi)", cbInfo->tso,
- rpmdsTagN(ds), rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
+ args = Py_BuildValue("(OiNNi)", cbInfo->tso,
+ rpmdsTagN(ds), utf8FromString(rpmdsN(ds)),
+ utf8FromString(rpmdsEVR(ds)), rpmdsFlags(ds));
result = PyEval_CallObject(cbInfo->cb, args);
Py_DECREF(args);
@@ -409,7 +410,7 @@ rpmts_HdrCheck(rpmtsObject * s, PyObject *obj)
rpmrc = headerCheck(s->ts, uh, uc, &msg);
Py_END_ALLOW_THREADS;
- return Py_BuildValue("(is)", rpmrc, msg);
+ return Py_BuildValue("(iN)", rpmrc, utf8FromString(msg));
}
static PyObject *
@@ -500,7 +501,7 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
/* Synthesize a python object for callback (if necessary). */
if (pkgObj == NULL) {
if (h) {
- pkgObj = Py_BuildValue("s", headerGetString(h, RPMTAG_NAME));
+ pkgObj = utf8FromString(headerGetString(h, RPMTAG_NAME));
} else {
pkgObj = Py_None;
Py_INCREF(pkgObj);
@@ -845,7 +846,7 @@ static PyObject *rpmts_get_tid(rpmtsObject *s, void *closure)
static PyObject *rpmts_get_rootDir(rpmtsObject *s, void *closure)
{
- return Py_BuildValue("s", rpmtsRootDir(s->ts));
+ return utf8FromString(rpmtsRootDir(s->ts));
}
static int rpmts_set_scriptFd(rpmtsObject *s, PyObject *value, void *closure)
diff --git a/python/spec-py.c b/python/spec-py.c
index 4efdbf4bf..70b796531 100644
--- a/python/spec-py.c
+++ b/python/spec-py.c
@@ -57,7 +57,7 @@ static PyObject *pkgGetSection(rpmSpecPkg pkg, int section)
{
char *sect = rpmSpecPkgGetSection(pkg, section);
if (sect != NULL) {
- PyObject *ps = PyBytes_FromString(sect);
+ PyObject *ps = utf8FromString(sect);
free(sect);
if (ps != NULL)
return ps;
@@ -158,7 +158,7 @@ static PyObject * getSection(rpmSpec spec, int section)
{
const char *sect = rpmSpecGetSection(spec, section);
if (sect) {
- return Py_BuildValue("s", sect);
+ return utf8FromString(sect);
}
Py_RETURN_NONE;
}
@@ -208,8 +208,8 @@ static PyObject * spec_get_sources(specObject *s, void *closure)
rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
- PyObject *srcUrl = Py_BuildValue("(sii)",
- rpmSpecSrcFilename(source, 1),
+ PyObject *srcUrl = Py_BuildValue("(Nii)",
+ utf8FromString(rpmSpecSrcFilename(source, 1)),
rpmSpecSrcNum(source),
rpmSpecSrcFlags(source));
if (!srcUrl) {
diff --git a/tests/local.at b/tests/local.at
index 02ead66c9..42eef1c75 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -10,6 +10,7 @@ rm -rf "${abs_builddir}"/testing`rpm --eval '%_dbpath'`/*
m4_define([RPMPY_RUN],[[
cat << EOF > test.py
+# coding=utf-8
import rpm, sys
dbpath=rpm.expandMacro('%_dbpath')
rpm.addMacro('_dbpath', '${abs_builddir}/testing%s' % dbpath)
diff --git a/tests/rpmpython.at b/tests/rpmpython.at
index ff77f868c..58f3e84a6 100644
--- a/tests/rpmpython.at
+++ b/tests/rpmpython.at
@@ -106,6 +106,25 @@ None
'rpm.hdr' object has no attribute '__foo__']
)
+RPMPY_TEST([non-utf8 data in header],[
+str = u'älämölö'
+enc = 'iso-8859-1'
+b = str.encode(enc)
+h = rpm.hdr()
+h['group'] = b
+d = h['group']
+try:
+ # python 3
+ t = bytes(d, 'utf-8', 'surrogateescape')
+except TypeError:
+ # python 2
+ t = bytes(d)
+res = t.decode(enc)
+myprint(str == res)
+],
+[True]
+)
+
RPMPY_TEST([invalid header data],[
h1 = rpm.hdr()
h1['basenames'] = ['bing', 'bang', 'bong']
@@ -125,6 +144,21 @@ for h in [h1, h2]:
/opt/bing,/opt/bang,/flopt/bong]
)
+RPMPY_TEST([labelCompare],[
+v = '1.0'
+r = '1'
+e = 3
+h = rpm.hdr()
+h['name'] = 'testpkg'
+h['version'] = v
+h['release'] = r
+h['epoch'] = e
+myprint(rpm.labelCompare((str(h['epoch']), h['version'], h['release']),
+ (str(e), v, r)))
+],
+[0]
+)
+
RPMPY_TEST([vfyflags API],[
ts = rpm.ts()
dlv = ts.getVfyFlags()
--
2.20.1

@ -0,0 +1,63 @@
From 9ad4b813483f8cf6c641f56387248b33b6dfc570 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 20 Feb 2019 15:28:30 +0200
Subject: [PATCH] Introduce patch_nums and source_nums Lua variables in spec
context
The pre-existing patches and sources variables only contains patch and
source filenames, but for some purposes we need access to the associated
patch/source number too. We could use the number as the table key, but
that would make the table unsorted. That we could handle in our own
macros, but would break compatibility for anybody doing custom stuff
with these. So it seems best to just add parallel arrays sharing the
same array indexes so that both values are as easily accessible,
depending on the need.
Inspired by Pascal "Pixel" Rigaux's similar patch in Mageia, which differs
in that the number-arrays are indexed by the filename and is unordered.
Compared to patches/sources this seemed against principle of least
surprise, and is slightly more cumbersome int the case we want the number
directly, such as in PR #626. The variable names differ so there
is no incompatibility to that downstream patch introduced.
---
build/parsePreamble.c | 9 +++++++++
build/spec.c | 3 ++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/build/parsePreamble.c b/build/parsePreamble.c
index 812c41f9f..9520bac4b 100644
--- a/build/parsePreamble.c
+++ b/build/parsePreamble.c
@@ -322,6 +322,15 @@ static int addSource(rpmSpec spec, Package pkg, const char *field, rpmTagVal tag
rpmluaSetVar(lua, var);
rpmluavFree(var);
rpmluaPop(lua);
+
+ what = (flag & RPMBUILD_ISPATCH) ? "patch_nums" : "source_nums";
+ rpmluaPushTable(lua, what);
+ var = rpmluavNew();
+ rpmluavSetListMode(var, 1);
+ rpmluavSetValueNum(var, p->num);
+ rpmluaSetVar(lua, var);
+ rpmluavFree(var);
+ rpmluaPop(lua);
}
#endif
free(body);
diff --git a/build/spec.c b/build/spec.c
index 80eaca611..55095c6ce 100644
--- a/build/spec.c
+++ b/build/spec.c
@@ -305,7 +305,8 @@ rpmSpec newSpec(void)
#ifdef WITH_LUA
/* make sure patches and sources tables always exist */
rpmlua lua = NULL; /* global state */
- const char * luavars[] = { "patches", "sources", NULL, };
+ const char * luavars[] = { "patches", "sources",
+ "patch_nums", "source_nums", NULL, };
for (const char **vp = luavars; vp && *vp; vp++) {
rpmluaDelVar(lua, *vp);
rpmluaPushTable(lua, *vp);
--
2.26.2

@ -0,0 +1,41 @@
From e811c7ec0b4d2685b63b61803e3952466b1a4ac6 Mon Sep 17 00:00:00 2001
Message-Id: <e811c7ec0b4d2685b63b61803e3952466b1a4ac6.1574335619.git.pmatilai@redhat.com>
From: marxin <mliska@suse.cz>
Date: Wed, 28 Nov 2018 10:52:01 +0100
Subject: [PATCH] Isolate %_smp_build_ncpus and use it for %_smp_mflags.
Refactor _smp_build_ncpus and use it in %_smp_mflags. Note that now
having a single CPU, %_smp_mflags is expanded to '-j1'.
XXX: hand-edited to remove double quotes as per upstream commit
9b6fdc65ef0507fff04a69c88e085a7a26711839 which isn't applicable
directly due to other changes
---
platform.in | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/platform.in b/platform.in
index 3eb67b55b..2dd951f87 100644
--- a/platform.in
+++ b/platform.in
@@ -50,11 +50,14 @@
# Maximum number of CPU's to use when building, 0 for unlimited.
#%_smp_ncpus_max 0
-%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\
+
+%_smp_build_ncpus %([ -z "$RPM_BUILD_NCPUS" ] \\\
&& RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"; \\\
ncpus_max=%{?_smp_ncpus_max}; \\\
if [ -n "$ncpus_max" ] && [ "$ncpus_max" -gt 0 ] && [ "$RPM_BUILD_NCPUS" -gt "$ncpus_max" ]; then RPM_BUILD_NCPUS="$ncpus_max"; fi; \\\
- if [ "$RPM_BUILD_NCPUS" -gt 1 ]; then echo "-j$RPM_BUILD_NCPUS"; fi)
+ echo "$RPM_BUILD_NCPUS";)
+
+%_smp_mflags -j%{_smp_build_ncpus}
#==============================================================================
# ---- Build policy macros.
--
2.23.0

@ -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

@ -0,0 +1,31 @@
From f23af97c4135013d3134a17c881014fb6e9589c8 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Tue, 30 Apr 2019 17:12:35 +0200
Subject: [PATCH] Make check-buildroot check the build files in parallel
Thanks to Denys Vlasenko for pointing this out in rhbz#1704353
---
scripts/check-buildroot | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/check-buildroot b/scripts/check-buildroot
index 0cfb34f39..f91dc767b 100755
--- a/scripts/check-buildroot
+++ b/scripts/check-buildroot
@@ -24,11 +24,12 @@ fi
tmp=$(mktemp ${TMPDIR:-/tmp}/cbr.XXXXXX)
trap "rm -f $tmp" EXIT
+NCPUS=${RPM_BUILD_NCPUS:-1}
find "$RPM_BUILD_ROOT" \! \( \
-name '*.pyo' -o -name '*.pyc' -o -name '*.elc' -o -name '.packlist' \
\) -type f -print0 | \
- LANG=C xargs -0r grep -F "$RPM_BUILD_ROOT" >$tmp
+ LANG=C xargs -0r -P$NCPUS -n16 grep -F "$RPM_BUILD_ROOT" >>$tmp
test -s "$tmp" && {
cat "$tmp"
--
2.21.0

@ -0,0 +1,28 @@
From 57b4f21634429ccd29d47cf93ec0841f70b68404 Mon Sep 17 00:00:00 2001
Message-Id: <57b4f21634429ccd29d47cf93ec0841f70b68404.1545311826.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 18 Sep 2018 11:02:36 +0300
Subject: [PATCH] Mark elements with associated problems as failed
An element with a problem can not possibly succeed so mark these failures
early. Doesn't make much of a difference as problems will prevent the
transaction from starting in the first place but it makes sense anyway.
---
lib/rpmte.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpmte.c b/lib/rpmte.c
index 4bdeeaf68..c5d614f67 100644
--- a/lib/rpmte.c
+++ b/lib/rpmte.c
@@ -703,6 +703,7 @@ static void appendProblem(rpmte te, rpmProblemType type,
if (te->probs == NULL)
te->probs = rpmpsCreate();
rpmpsAppendProblem(te->probs, p);
+ rpmteMarkFailed(te);
}
rpmProblemFree(p);
}
--
2.19.2

@ -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

@ -0,0 +1,76 @@
From 362c4401979f896de1e69a3e18d33954953912cc Mon Sep 17 00:00:00 2001
Message-Id: <362c4401979f896de1e69a3e18d33954953912cc.1554983588.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 11 Dec 2018 13:21:47 +0200
Subject: [PATCH] Only read through payload on verify if actually needed
If none of our verify items ranges over the payload, then why bother?
To do this, add an internal rpmvs API to get it's range, and use
that to decide whether trip over the payload is needed or not.
In addition, the payload digest tag needs to be grabbed outside of the
condition to avoid depending on other values. The details including
RPMVSF_NEEDPAYLOAD will be handled internally to rpmvs which makes it
actually nicer code-wise too.
---
lib/rpmchecksig.c | 8 ++++----
lib/rpmvs.c | 12 ++++++++++++
lib/rpmvs.h | 3 +++
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
index 1ba72a45e..810f7153d 100644
--- a/lib/rpmchecksig.c
+++ b/lib/rpmchecksig.c
@@ -187,11 +187,11 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd,
/* Finalize header range */
rpmvsFiniRange(vs, RPMSIG_HEADER);
- /* Unless disabled, read the payload, generating digest(s) on the fly. */
- if (!(rpmvsFlags(vs) & RPMVSF_NEEDPAYLOAD)) {
- /* Fish interesting tags from the main header. This is a bit hacky... */
- rpmvsAppendTag(vs, blob, RPMTAG_PAYLOADDIGEST);
+ /* Fish interesting tags from the main header. This is a bit hacky... */
+ rpmvsAppendTag(vs, blob, RPMTAG_PAYLOADDIGEST);
+ /* If needed and not explicitly disabled, read the payload as well. */
+ if (rpmvsRange(vs) & RPMSIG_PAYLOAD) {
/* Initialize digests ranging over the payload only */
rpmvsInitRange(vs, RPMSIG_PAYLOAD);
diff --git a/lib/rpmvs.c b/lib/rpmvs.c
index 622e48011..0d475af86 100644
--- a/lib/rpmvs.c
+++ b/lib/rpmvs.c
@@ -396,6 +396,18 @@ void rpmvsFiniRange(struct rpmvs_s *sis, int range)
}
}
+int rpmvsRange(struct rpmvs_s *vs)
+{
+ int range = 0;
+ for (int i = 0; i < vs->nsigs; i++) {
+ if (rpmsinfoDisabled(&vs->sigs[i], vs->vsflags))
+ continue;
+ range |= vs->sigs[i].range;
+ }
+
+ return range;
+}
+
static int sinfoCmp(const void *a, const void *b)
{
const struct rpmsinfo_s *sa = a;
--- rpm-4.14.3/lib/rpmvs.h.orig 2020-04-28 10:57:19.727347211 +0200
+++ rpm-4.14.3/lib/rpmvs.h 2020-04-28 10:57:43.622612015 +0200
@@ -66,6 +66,8 @@
void rpmvsFiniRange(struct rpmvs_s *sis, int range);
+int rpmvsRange(struct rpmvs_s *vs);
+
int rpmvsVerify(struct rpmvs_s *sis, int type,
rpmsinfoCb cb, void *cbdata);
--
2.20.1

@ -0,0 +1,27 @@
From d97d7b71de158660eb96b4f11d40b6626b85521a Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Tue, 16 Apr 2019 09:50:57 +0200
Subject: [PATCH] Pass RPM_BUILD_NCPUS to build scripts
Use %_smp_build_ncpus instead of the initial value
---
macros.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/macros.in b/macros.in
index fc587997d..a15e46f26 100644
--- a/macros.in
+++ b/macros.in
@@ -807,7 +807,8 @@ package or when debugging this package.\
RPM_OPT_FLAGS=\"%{optflags}\"\
RPM_ARCH=\"%{_arch}\"\
RPM_OS=\"%{_os}\"\
- export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\
+ RPM_BUILD_NCPUS=\"%{_smp_build_ncpus}\"\
+ export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS\
RPM_DOC_DIR=\"%{_docdir}\"\
export RPM_DOC_DIR\
RPM_PACKAGE_NAME=\"%{NAME}\"\
--
2.21.0

@ -76,11 +76,23 @@ index 39762c376..ddf5d7048 100644
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)
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 */
--- a/plugins/ima.c 2020-04-28 14:50:11.835399269 +0200
+++ b/plugins/ima.c 2023-12-13 11:19:58.835948660 +0100
@@ -39,7 +39,7 @@
return (memcmp(fsig, &zero_hdr, sizeof(zero_hdr)) == 0);
}
@ -89,12 +101,12 @@ index fe6d3ad7f..9c28a41a3 100644
const char *path,
const char *dest,
mode_t file_mode, rpmFsmOp op)
@@ -68,8 +68,13 @@
@@ -63,8 +63,14 @@
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;
- rpmlog(RPMLOG_ERR,
+ int xx;
+ if (fd >= 0)
+ xx = fsetxattr(fd, XATTR_NAME_IMA, fsig, len, 0);
@ -102,28 +114,13 @@ index fe6d3ad7f..9c28a41a3 100644
+ xx = lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0);
+ if (xx < 0) {
+ int is_err = errno != EOPNOTSUPP;
rpmlog(is_err?RPMLOG_ERR:RPMLOG_DEBUG,
+ 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,
rc = RPMRC_FAIL;
--- a/plugins/selinux.c 2023-12-13 11:21:54.935009141 +0100
+++ b/plugins/selinux.c 2023-12-13 11:22:23.172510285 +0100
@@ -149,7 +149,7 @@
return rc;
}
@ -132,9 +129,9 @@ index 32c3b7529..a7f20aeca 100644
const char *path, const char *dest,
mode_t file_mode, rpmFsmOp op)
{
@@ -194,13 +194,17 @@
@@ -159,14 +159,17 @@
if (sehandle && !XFA_SKIPPING(action)) {
char *scon = NULL;
security_context_t scon = NULL;
if (selabel_lookup_raw(sehandle, &scon, dest, file_mode) == 0) {
- int conrc = lsetfilecon(path, scon);
+ int conrc;
@ -146,13 +143,11 @@ index 32c3b7529..a7f20aeca 100644
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) : ""));
- rpmlog((rc != RPMRC_OK) ? RPMLOG_ERR : RPMLOG_DEBUG,
- "lsetfilecon: (%s, %s) %s\n",
- path, scon, (conrc < 0 ? strerror(errno) : ""));
+ rpmlog((rc != RPMRC_OK) ? RPMLOG_ERR : RPMLOG_DEBUG, "lsetfilecon: (%d %s, %s) %s\n",
+ fd, path, scon, (conrc < 0 ? strerror(errno) : ""));
freecon(scon);
} else {
--
2.41.0

@ -0,0 +1,41 @@
From aea53a4aead8bd71f519df35fcffd9eec76fbc01 Mon Sep 17 00:00:00 2001
Message-Id: <aea53a4aead8bd71f519df35fcffd9eec76fbc01.1554884465.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 26 Feb 2019 11:27:51 +0200
Subject: [PATCH] Return NULL string as None from utf8FromString()
Commit 84920f898315d09a57a3f1067433eaeb7de5e830 regressed dnf install
to segfault at the end due to some NULL string passed to strlen().
Check for NULL and return it as None, make it an inline function
to make this saner.
---
python/rpmsystem-py.h | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
index 87c750571..25938464a 100644
--- a/python/rpmsystem-py.h
+++ b/python/rpmsystem-py.h
@@ -19,11 +19,17 @@
#define PyInt_AsSsize_t PyLong_AsSsize_t
#endif
+static inline PyObject * utf8FromString(const char *s)
+{
/* In Python 3, we return all strings as surrogate-escaped utf-8 */
#if PY_MAJOR_VERSION >= 3
-#define utf8FromString(_s) PyUnicode_DecodeUTF8(_s, strlen(_s), "surrogateescape")
+ if (s != NULL)
+ return PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
#else
-#define utf8FromString(_s) PyBytes_FromString(_s)
+ if (s != NULL)
+ return PyBytes_FromString(s);
#endif
+ Py_RETURN_NONE;
+}
#endif /* H_SYSTEM_PYTHON */
--
2.20.1

@ -0,0 +1,37 @@
From cb6aa82dbc10d554f8d234e934ae7c77e39a3ce2 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 12 Jan 2021 13:35:23 +0200
Subject: [PATCH] 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)
---
lib/rpmscript.c | 5 +++++
1 file changed, 5 insertions(+)
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);
--
2.29.2

@ -0,0 +1,58 @@
From fc2c986d8f5e4174885ae377750185339636f062 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Mon, 15 Apr 2019 15:46:09 +0200
Subject: [PATCH] Use RPM_BUILD_NCPUS in brp-strip-static-archive
to speed the script up for large number of files to be looked at.
Use xargs -P instead of find -exec.
Add xargs to the test environment
Resolves rhbz1691822
---
scripts/brp-strip-static-archive | 8 +++++---
tests/Makefile.am | 2 +-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/scripts/brp-strip-static-archive b/scripts/brp-strip-static-archive
index ddd3b2422..4dc449061 100755
--- a/scripts/brp-strip-static-archive
+++ b/scripts/brp-strip-static-archive
@@ -5,6 +5,7 @@ if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then
fi
STRIP=${1:-strip}
+NCPUS=${RPM_BUILD_NCPUS:-1}
case `uname -a` in
Darwin*) exit 0 ;;
@@ -12,9 +13,10 @@ Darwin*) exit 0 ;;
esac
# Strip static libraries.
-for f in `find "$RPM_BUILD_ROOT" -type f -a -exec file {} \; | \
- grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug" | \
+for f in `find "$RPM_BUILD_ROOT" -type f | \
+ grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug" | \
+ xargs -r -P$NCPUS -n16 file | sed 's/: */: /' | \
grep 'current ar archive' | \
- sed -n -e 's/^\(.*\):[ ]*current ar archive/\1/p'`; do
+ sed -n -e 's/^\(.*\):[ ]*current ar archive/\1/p'`; do
$STRIP -g "$f"
done
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e2d759d82..ad9549a68 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -144,7 +144,7 @@ populate_testing:
for d in dev etc magic tmp var; do if [ ! -d testing/$${d} ]; then mkdir testing/$${d}; fi; done
for node in urandom stdin stderr stdout null full; do ln -s /dev/$${node} testing/dev/$${node}; done
for cf in hosts resolv.conf passwd shadow group gshadow mtab ; do [ -f /etc/$${cf} ] && ln -s /etc/$${cf} testing/etc/$${cf}; done
- for prog in gzip cat patch tar sh ln chmod rm mkdir uname grep sed find file ionice mktemp nice cut sort diff touch install wc coreutils; 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; 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)
HOME=$(abs_builddir)/testing gpg2 --import ${abs_srcdir}/data/keys/*.secret
--
2.21.0

@ -45,8 +45,8 @@ index daf572cf4..e74bb2201 100644
/**
* We pass these around as an array with a sentinel.
*/
--- rpm-4.16.1.3/lib/fsm.c.orig 2023-11-11 10:05:19.208206675 +0100
+++ rpm-4.16.1.3/lib/fsm.c 2023-11-11 10:05:43.559432708 +0100
--- rpm-4.14.3/lib/fsm.c.orig 2023-10-11 16:00:49.610090807 +0200
+++ rpm-4.14.3/lib/fsm.c 2023-10-11 16:01:16.976451270 +0200
@@ -5,9 +5,11 @@
#include "system.h"
@ -321,7 +321,8 @@ index daf572cf4..e74bb2201 100644
+ int fdno = *wfdp;
+
if (!oneshot) {
flush_io = (rpmExpandNumeric("%{?_flush_io}") > 0);
- flush_io = rpmExpandNumeric("%{?_flush_io}");
+ flush_io = (rpmExpandNumeric("%{?_flush_io}") > 0);
oneshot = 1;
}
if (flush_io) {
@ -512,7 +513,7 @@ index daf572cf4..e74bb2201 100644
if (rc < 0)
switch (errno) {
case ENOENT: rc = RPMERR_ENOENT; break;
@@ -365,148 +288,194 @@
@@ -365,172 +288,194 @@
return rc;
}
@ -637,51 +638,66 @@ index daf572cf4..e74bb2201 100644
- DNLI_t dnli = dnlInitIterator(files, fs, 0);
- struct stat sb;
- const char *dpath;
- int dc = rpmfilesDC(files);
+ char *sp = NULL, *bn;
+ char *apath = NULL;
+ int oflags = O_RDONLY;
int rc = 0;
- int i;
- size_t ldnlen = 0;
- const char * ldn = NULL;
- int ldnlen = 0;
- int ldnalloc = 0;
- char * ldn = NULL;
- short * dnlx = NULL;
-
- dnlx = (dc ? xcalloc(dc, sizeof(*dnlx)) : NULL);
-
- if (dnlx != NULL)
- while ((dpath = dnlNextIterator(dnli)) != NULL) {
- size_t dnlen = strlen(dpath);
- char * te, dn[dnlen+1];
-
- dc = dnli->isave;
- if (dc < 0) continue;
- dnlx[dc] = dnlen;
- if (dnlen <= 1)
- continue;
+ if (*dirfdp >= 0)
+ return rc;
- if (dnlen == ldnlen && rstreq(dpath, ldn))
- if (dnlen <= ldnlen && rstreq(dpath, ldn))
- continue;
+ int dirfd = fsmOpenat(-1, "/", oflags, 1);
+ int fd = dirfd; /* special case of "/" */
+ if (*dirfdp >= 0)
+ return rc;
- /* Copy as we need to modify the string */
- (void) stpcpy(dn, dpath);
+ char *path = xstrdup(p);
+ char *dp = path;
+ int dirfd = fsmOpenat(-1, "/", oflags, 1);
+ int fd = dirfd; /* special case of "/" */
- /* Assume '/' directory exists, "mkdir -p" for others if non-existent */
- for (i = 1, te = dn + 1; *te != '\0'; te++, i++) {
- if (*te != '/')
- continue;
+ char *path = xstrdup(p);
+ char *dp = path;
- *te = '\0';
+ while ((bn = strtok_r(dp, "/", &sp)) != NULL) {
+ fd = fsmOpenat(dirfd, bn, oflags, 1);
+ /* assemble absolute path for plugins benefit, sigh */
+ apath = rstrscat(&apath, "/", bn, NULL);
+
+ if (fd < 0 && errno == ENOENT && create) {
+ mode_t mode = S_IFDIR | (_dirPerms & 07777);
+ rc = fsmDoMkDir(plugins, dirfd, bn, apath, owned, mode, &fd);
+ }
- /* Already validated? */
- if (i < ldnlen &&
- (ldn[i] == '/' || ldn[i] == '\0') && rstreqn(dn, ldn, i))
- {
- *te = '/';
- /* Move pre-existing path marker forward. */
- dnlx[dc] = (te - dn);
- continue;
+ if (fd < 0 && errno == ENOENT && create) {
+ mode_t mode = S_IFDIR | (_dirPerms & 07777);
+ rc = fsmDoMkDir(plugins, dirfd, bn, apath, owned, mode, &fd);
+ }
+
+ fsmClose(&dirfd);
+ if (fd >= 0) {
+ dirfd = fd;
@ -689,21 +705,19 @@ index daf572cf4..e74bb2201 100644
+ if (!quiet) {
+ rpmlog(RPMLOG_ERR, _("failed to open dir %s of %s: %s\n"),
+ bn, p, strerror(errno));
+ }
}
+ rc = RPMERR_OPEN_FAILED;
+ break;
+ }
- /* Validate next component of path. */
- *te = '\0';
- rc = fsmStat(dn, 1, &sb); /* lstat */
- *te = '/';
+ dp = NULL;
+ }
-
- /* Directory already exists? */
- if (rc == 0 && S_ISDIR(sb.st_mode)) {
- continue;
- /* Move pre-existing path marker forward. */
- dnlx[dc] = (te - dn);
- } else if (rc == RPMERR_ENOENT) {
- *te = '\0';
- mode_t mode = S_IFDIR | (_dirPerms & 07777);
@ -719,6 +733,11 @@ index daf572cf4..e74bb2201 100644
- rc = rpmpluginsCallFsmFilePrepare(plugins, NULL, dn, dn,
- mode, op);
- }
+ dp = NULL;
+ }
- /* Run fsm file post hook for all plugins */
- rpmpluginsCallFsmFilePost(plugins, NULL, dn, mode, op, rc);
+ if (rc) {
+ fsmClose(&fd);
+ fsmClose(&dirfd);
@ -727,13 +746,6 @@ index daf572cf4..e74bb2201 100644
+ }
+ *dirfdp = dirfd;
- /* Run fsm file post hook for all plugins */
- rpmpluginsCallFsmFilePost(plugins, NULL, dn, mode, op, rc);
+ if (_fsm_debug) {
+ rpmlog(RPMLOG_DEBUG, " %8s (%s: %d) %s\n", __func__,
+ p, dirfd, (rc < 0 ? strerror(errno) : ""));
+ }
- if (!rc) {
- rpmlog(RPMLOG_DEBUG,
- "%s directory created with perms %04o\n",
@ -745,14 +757,25 @@ index daf572cf4..e74bb2201 100644
- break;
- }
- if (rc) break;
+ if (_fsm_debug) {
+ rpmlog(RPMLOG_DEBUG, " %8s (%s: %d) %s\n", __func__,
+ p, dirfd, (rc < 0 ? strerror(errno) : ""));
+ }
- /* Save last validated path. */
- if (ldnalloc < (dnlen + 1)) {
- ldnalloc = dnlen + 100;
- ldn = xrealloc(ldn, ldnalloc);
- }
- if (ldn != NULL) { /* XXX can't happen */
- strcpy(ldn, dn);
- ldnlen = dnlen;
- }
+ free(path);
+ free(apath);
+ return rc;
+}
- /* Save last validated path. */
- ldn = dpath;
- ldnlen = dnlen;
+
+static int fsmMkfifo(int dirfd, const char *path, mode_t mode)
+{
+ int rc = mkfifoat(dirfd, path, (mode & 07777));
@ -761,16 +784,14 @@ index daf572cf4..e74bb2201 100644
+ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%04o) %s\n",
+ __func__, dirfd, path, (unsigned)(mode & 07777),
+ (rc < 0 ? strerror(errno) : ""));
}
- dnlFreeIterator(dnli);
+ }
+
+ if (rc < 0)
+ rc = RPMERR_MKFIFO_FAILED;
return rc;
}
-static void removeSBITS(const char *path)
+
+ return rc;
+}
+
+static int fsmMknod(int dirfd, const char *path, mode_t mode, dev_t dev)
+{
+ /* FIX: check S_IFIFO or dev != 0 */
@ -780,14 +801,18 @@ index daf572cf4..e74bb2201 100644
+ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%o, 0x%x) %s\n",
+ __func__, dirfd, path, (unsigned)(mode & ~07777),
+ (unsigned)dev, (rc < 0 ? strerror(errno) : ""));
+ }
}
- free(dnlx);
- free(ldn);
- dnlFreeIterator(dnli);
+
+ if (rc < 0)
+ rc = RPMERR_MKNOD_FAILED;
+
+ return rc;
+}
+
return rc;
}
-static void removeSBITS(const char *path)
+static void removeSBITS(int dirfd, const char *path)
{
struct stat stb;
@ -807,7 +832,7 @@ index daf572cf4..e74bb2201 100644
}
#endif
}
@@ -522,13 +491,13 @@
@@ -546,13 +490,13 @@
(fpath ? fpath : ""));
}
@ -825,7 +850,7 @@ index daf572cf4..e74bb2201 100644
}
if (rc < 0)
@@ -536,96 +505,125 @@
@@ -560,96 +504,125 @@
return rc;
}
@ -994,7 +1019,7 @@ index daf572cf4..e74bb2201 100644
if (rc < 0) rc = RPMERR_UTIME_FAILED;
/* ...but utime error is not critical for directories */
if (rc && S_ISDIR(mode))
@@ -633,24 +631,24 @@
@@ -657,24 +630,24 @@
return rc;
}
@ -1023,7 +1048,7 @@ index daf572cf4..e74bb2201 100644
else
rc = RPMERR_UNLINK_FAILED;
free(rmpath);
@@ -659,7 +657,7 @@
@@ -683,7 +656,7 @@
if (S_ISDIR(dsb.st_mode)) return 0;
if (S_ISLNK(dsb.st_mode)) {
uid_t luid = dsb.st_uid;
@ -1032,7 +1057,7 @@ index daf572cf4..e74bb2201 100644
if (rc == RPMERR_ENOENT) rc = 0;
if (rc) return rc;
errno = saveerrno;
@@ -685,7 +683,7 @@
@@ -709,7 +682,7 @@
if (S_ISSOCK(dsb.st_mode)) return 0;
}
/* XXX shouldn't do this with commit/undo. */
@ -1041,7 +1066,7 @@ index daf572cf4..e74bb2201 100644
if (rc == 0) rc = RPMERR_ENOENT;
return (rc ? rc : RPMERR_ENOENT); /* XXX HACK */
}
@@ -699,7 +697,7 @@
@@ -723,7 +696,7 @@
/* Rename pre-existing modified or unmanaged file. */
@ -1050,7 +1075,7 @@ index daf572cf4..e74bb2201 100644
{
int rc = 0;
const char *suffix = NULL;
@@ -720,9 +718,10 @@
@@ -744,9 +717,10 @@
if (suffix) {
char * opath = fsmFsPath(fi, NULL);
char * path = fsmFsPath(fi, suffix);
@ -1063,7 +1088,7 @@ index daf572cf4..e74bb2201 100644
}
free(path);
free(opath);
@@ -730,7 +729,8 @@
@@ -754,7 +728,8 @@
return rc;
}
@ -1073,7 +1098,7 @@ index daf572cf4..e74bb2201 100644
rpmFileAction action, const struct stat * st,
int nofcaps)
{
@@ -738,27 +738,28 @@
@@ -762,27 +737,28 @@
const char *dest = rpmfiFN(fi);
if (!rc && !getuid()) {
@ -1108,7 +1133,7 @@ index daf572cf4..e74bb2201 100644
{
int rc = 0;
@@ -772,15 +773,18 @@
@@ -796,15 +772,18 @@
/* Rename temporary to final file name if needed. */
if (dest != *path) {
@ -1136,7 +1161,7 @@ index daf572cf4..e74bb2201 100644
}
}
@@ -831,191 +835,277 @@
@@ -855,184 +834,277 @@
}
}
@ -1209,6 +1234,10 @@ index daf572cf4..e74bb2201 100644
- /* Detect and create directories not explicitly in package. */
- rc = fsmMkdirs(files, fs, plugins);
-
- while (!rc) {
- /* Read next payload header. */
- rc = rpmfiNext(fi);
+ /* Collect state data for the whole operation */
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
@ -1222,20 +1251,13 @@ index daf572cf4..e74bb2201 100644
+ fp->suffix = tid;
+ fp->fpath = fsmFsPath(fi, fp->suffix);
- while (!rc) {
- /* Read next payload header. */
- rc = rpmfiNext(fi);
+ /* Remap file perms, owner, and group. */
+ rc = rpmfiStat(fi, 1, &fp->sb);
- if (rc < 0) {
- if (rc == RPMERR_ITER_END)
- rc = 0;
- break;
- }
+ /* Hardlinks are tricky and handled elsewhere for install */
+ fp->setmeta = (fp->skip == 0) &&
+ (fp->sb.st_nlink == 1 || fp->action == FA_TOUCH);
+ /* Remap file perms, owner, and group. */
+ rc = rpmfiStat(fi, 1, &fp->sb);
- action = rpmfsGetAction(fs, rpmfiFX(fi));
- skip = XFA_SKIPPING(action);
@ -1245,24 +1267,25 @@ index daf572cf4..e74bb2201 100644
- suffix = NULL;
- }
- fpath = fsmFsPath(fi, suffix);
+ setFileState(fs, fx);
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
+ /* Hardlinks are tricky and handled elsewhere for install */
+ fp->setmeta = (fp->skip == 0) &&
+ (fp->sb.st_nlink == 1 || fp->action == FA_TOUCH);
- /* Remap file perms, owner, and group. */
- rc = rpmfiStat(fi, 1, &sb);
+ setFileState(fs, fx);
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
- fsmDebug(fpath, action, &sb);
+ fp->stage = FILE_PRE;
+ }
+ fi = rpmfiFree(fi);
- fsmDebug(fpath, action, &sb);
+ if (rc)
+ goto exit;
- /* Exit on error. */
- if (rc)
- break;
+ fi = fsmIter(payload, files,
+ payload ? RPMFI_ITER_READ_ARCHIVE : RPMFI_ITER_FWD, &di);
+ if (rc)
+ goto exit;
- /* Run fsm file pre hook for all plugins */
- rc = rpmpluginsCallFsmFilePre(plugins, fi, fpath,
@ -1272,13 +1295,19 @@ index daf572cf4..e74bb2201 100644
- } else {
- setFileState(fs, rpmfiFX(fi));
- }
+ fi = fsmIter(payload, files,
+ payload ? RPMFI_ITER_READ_ARCHIVE : RPMFI_ITER_FWD, &di);
- if (!skip) {
- int setmeta = 1;
+ if (fi == NULL) {
+ rc = RPMERR_BAD_MAGIC;
+ goto exit;
+ }
- if (!skip) {
- int setmeta = 1;
- /* When touching we don't need any of this... */
- if (action == FA_TOUCH)
- goto touch;
+ /* Process the payload */
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
+ struct filedata_s *fp = &fdata[fx];
@ -1326,25 +1355,19 @@ index daf572cf4..e74bb2201 100644
rc = RPMERR_ENOENT;
}
/* See if the file was removed while our attention was elsewhere */
- if (rc == RPMERR_ENOENT && action == FA_TOUCH) {
- rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n", fpath);
- action = FA_CREATE;
- fsmDebug(fpath, action, &sb);
- if (S_ISREG(sb.st_mode)) {
+ /* See if the file was removed while our attention was elsewhere */
+ if (rc == RPMERR_ENOENT && fp->action == FA_TOUCH) {
+ rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n",
+ fp->fpath);
+ fp->action = FA_CREATE;
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
}
/* When touching we don't need any of this... */
- if (action == FA_TOUCH)
- goto touch;
+ }
+
+ /* When touching we don't need any of this... */
+ if (fp->action == FA_TOUCH)
+ goto setmeta;
- if (S_ISREG(sb.st_mode)) {
+
+ if (S_ISREG(fp->sb.st_mode)) {
if (rc == RPMERR_ENOENT) {
- rc = fsmMkfile(fi, fpath, files, psm, nodigest,
@ -1433,12 +1456,12 @@ index daf572cf4..e74bb2201 100644
- } else {
- /* Notify on success. */
- rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, rpmfiArchiveTell(fi));
-
- if (!skip) {
- /* Backup file if needed. Directories are handled earlier */
- if (suffix)
- rc = fsmBackup(fi, action);
-
- if (!rc)
- rc = fsmCommit(&fpath, fi, action, suffix);
+ if (!rc && fp->setmeta) {
@ -1530,7 +1553,7 @@ index daf572cf4..e74bb2201 100644
return rc;
}
@@ -1024,32 +1114,42 @@
@@ -1041,32 +1113,42 @@
int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
rpmpsm psm, char ** failedFile)
{
@ -1587,7 +1610,7 @@ index daf572cf4..e74bb2201 100644
/*
* Missing %ghost or %missingok entries are not errors.
@@ -1074,20 +1174,20 @@
@@ -1091,20 +1173,20 @@
if (rc) {
int lvl = strict_erasures ? RPMLOG_ERR : RPMLOG_WARNING;
rpmlog(lvl, _("%s %s: remove failed: %s\n"),
@ -1613,7 +1636,7 @@ index daf572cf4..e74bb2201 100644
if (rc == 0) {
/* Notify on success. */
@@ -1095,11 +1195,12 @@
@@ -1112,11 +1194,12 @@
rpm_loff_t amount = rpmfiFC(fi) - rpmfiFX(fi);
rpmpsmNotify(psm, RPMCALLBACK_UNINST_PROGRESS, amount);
}

@ -0,0 +1,29 @@
From 9aae21d7610a7e8067ae932f36d1c8bb8583fe59 Mon Sep 17 00:00:00 2001
From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
Date: Wed, 5 Jun 2019 06:07:00 +0200
Subject: [PATCH] Use [ ] in condition to avoid sub processes in
find-debuginfo.sh (#735)
Introduced in commit 1da9e83, spotted by covscan.
Modified to fix another covscan warning
---
scripts/find-debuginfo.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
index 23286139e..d75da1108 100755
--- a/scripts/find-debuginfo.sh
+++ b/scripts/find-debuginfo.sh
@@ -213,7 +213,7 @@ if test -n "$build_id_seed" -a "$no_recompute_build_id" = "true"; then
exit 2
fi
-if ("$strip_g" = "true") && ("$strip_glibs" = "true"); then
+if [ "$strip_g" = "true" ] && [ "$strip_glibs" = "true" ]; then
echo >&2 "*** ERROR: -g and --g-libs cannot be used together"
exit 2
fi
--
2.21.0

@ -0,0 +1,26 @@
From 09d181d78c16e1751779586c606e85c11f360407 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Tue, 25 Jun 2019 18:04:20 +0200
Subject: [PATCH] Use newline as a delimiter to avoid xargs messing up file
names with quotes
which is the default behaviour otherwise.
Fixes rhbz#1721348
---
scripts/brp-strip-static-archive | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/brp-strip-static-archive b/scripts/brp-strip-static-archive
index 13d9a098b..f7fb26b87 100755
--- a/scripts/brp-strip-static-archive
+++ b/scripts/brp-strip-static-archive
@@ -15,4 +15,4 @@ esac
# Strip static libraries.
find "$RPM_BUILD_ROOT" -type f | \
grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug" | \
- xargs -r -P$NCPUS -n32 sh -c "file \"\$@\" | sed 's/: */: /' | grep 'current ar archive' | sed -n -e 's/^\(.*\):[ ]*current ar archive/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0
+ xargs -d '\n' -r -P$NCPUS -n32 sh -c "file \"\$@\" | sed 's/: */: /' | grep 'current ar archive' | sed -n -e 's/^\(.*\):[ ]*current ar archive/\1/p' | xargs -d '\n' -I\{\} $STRIP -g \{\}" ARG0
--
2.21.0

@ -0,0 +1,38 @@
From 9cbc1fe444b048c3f7cf5ea09ab650d1c146d54a Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 20 Feb 2019 14:49:19 +0200
Subject: [PATCH] When doing the same thing more than once, use a loop...
No functional changes but this'll simplify the next commit quite a bit.
---
build/spec.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/build/spec.c b/build/spec.c
index e414e4102..80eaca611 100644
--- a/build/spec.c
+++ b/build/spec.c
@@ -303,15 +303,13 @@ rpmSpec newSpec(void)
spec->pool = rpmstrPoolCreate();
#ifdef WITH_LUA
- {
/* make sure patches and sources tables always exist */
rpmlua lua = NULL; /* global state */
- rpmluaDelVar(lua, "patches");
- rpmluaDelVar(lua, "sources");
- rpmluaPushTable(lua, "patches");
- rpmluaPushTable(lua, "sources");
- rpmluaPop(lua);
- rpmluaPop(lua);
+ const char * luavars[] = { "patches", "sources", NULL, };
+ for (const char **vp = luavars; vp && *vp; vp++) {
+ rpmluaDelVar(lua, *vp);
+ rpmluaPushTable(lua, *vp);
+ rpmluaPop(lua);
}
#endif
return spec;
--
2.26.2

@ -0,0 +1,44 @@
From 8fefd2bd21b30996ad0748eab6baadf915610642 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 13 Aug 2020 13:29:10 +0300
Subject: [PATCH] Work around buggy signature region preventing resigning
(RhBug:1851508)
Various proprietary packages in the wild have subtly malformed data
in the signature header, in particular wrt the immutable region size,
presumably from using some in-house/3rd party signing tools which do
not understand the immutable region business at all. This can prevent
resigning and signature deletion on such packages due to the more
thorough checking that rpmsign does.
As the old wisdom goes, be liberal in what you accept... we can easily
work around the crud by just taking a fresh copy of the contents that
are legit as such (otherwise the package would be uninstallable).
Adjusted for 4.14.3
--- rpm-4.14.3/sign/rpmgensig.c.orig 2020-10-29 16:00:38.785229048 +0100
+++ rpm-4.14.3/sign/rpmgensig.c 2020-10-29 16:08:55.997791345 +0100
@@ -401,12 +401,19 @@
if (headerGet(*hdrp, tag, utd, HEADERGET_DEFAULT)) {
oh = headerCopyLoad(utd->data);
- nh = headerCopy(oh);
- headerFree(oh);
rpmtdFreeData(utd);
+ } else {
+ /* XXX should we warn if the immutable region is corrupt/missing? */
+ oh = headerLink(*hdrp);
+ }
+
+ if (oh) {
+ /* Perform a copy to eliminate crud from buggy signing tools etc */
+ nh = headerCopy(oh);
headerFree(*hdrp);
*hdrp = headerLink(nh);
headerFree(nh);
+ headerFree(oh);
}
}

@ -0,0 +1,490 @@
From ce6e8556a8f93327d6de0446f21ac5e549861d82 Mon Sep 17 00:00:00 2001
Message-Id: <ce6e8556a8f93327d6de0446f21ac5e549861d82.1573552234.git.pmatilai@redhat.com>
From: Mark Wielaard <mark@klomp.org>
Date: Mon, 17 Jun 2019 11:23:24 +0200
Subject: [PATCH 1/3] debugedit: Refactor reading/writing of relocated values.
This refactors the reading and writing of relocated values into seperate
helper functions (setup_relbuf and update_rela_data). It will be easier
to reuse this code in case we want to read/write relocated values in other
sections than DEBUG_INFO. The only functional change is that we explicitly
track whether the relocation data is updated, and only explicitly update
and write out the relocation data if so. In the case there were no strp
or stmt updates, there will also not be any relocation updates, even if
there is relocation data available.
All new debugedit testcases pass before and after this refactoring.
---
tools/debugedit.c | 395 +++++++++++++++++++++++++---------------------
1 file changed, 216 insertions(+), 179 deletions(-)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 4be85b979..cf9cc3ca9 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -401,13 +401,18 @@ dwarf2_write_be32 (unsigned char *p, uint32_t v)
relend). Might just update the addend. So relocations need to be
updated at the end. */
+static bool rel_updated;
+
#define do_write_32_relocated(ptr,val) ({ \
if (relptr && relptr < relend && relptr->ptr == ptr) \
{ \
if (reltype == SHT_REL) \
do_write_32 (ptr, val - relptr->addend); \
else \
- relptr->addend = val; \
+ { \
+ relptr->addend = val; \
+ rel_updated = true; \
+ } \
} \
else \
do_write_32 (ptr,val); \
@@ -418,14 +423,18 @@ dwarf2_write_be32 (unsigned char *p, uint32_t v)
ptr += 4; \
})
-static struct
+typedef struct debug_section
{
const char *name;
unsigned char *data;
Elf_Data *elf_data;
size_t size;
int sec, relsec;
- } debug_sections[] =
+ REL *relbuf;
+ REL *relend;
+ } debug_section;
+
+static debug_section debug_sections[] =
{
#define DEBUG_INFO 0
#define DEBUG_ABBREV 1
@@ -458,6 +467,201 @@ static struct
{ NULL, NULL, NULL, 0, 0, 0 }
};
+static int
+rel_cmp (const void *a, const void *b)
+{
+ REL *rela = (REL *) a, *relb = (REL *) b;
+
+ if (rela->ptr < relb->ptr)
+ return -1;
+
+ if (rela->ptr > relb->ptr)
+ return 1;
+
+ return 0;
+}
+
+/* Returns a malloced REL array, or NULL when there are no relocations
+ for this section. When there are relocations, will setup relend,
+ as the last REL, and reltype, as SHT_REL or SHT_RELA. */
+static void
+setup_relbuf (DSO *dso, debug_section *sec, int *reltype)
+{
+ int ndx, maxndx;
+ GElf_Rel rel;
+ GElf_Rela rela;
+ GElf_Sym sym;
+ GElf_Addr base = dso->shdr[sec->sec].sh_addr;
+ Elf_Data *symdata = NULL;
+ int rtype;
+ REL *relbuf;
+ Elf_Scn *scn;
+ Elf_Data *data;
+ int i = sec->relsec;
+
+ /* No relocations, or did we do this already? */
+ if (i == 0 || sec->relbuf != NULL)
+ {
+ relptr = sec->relbuf;
+ relend = sec->relend;
+ return;
+ }
+
+ scn = dso->scn[i];
+ data = elf_getdata (scn, NULL);
+ assert (data != NULL && data->d_buf != NULL);
+ assert (elf_getdata (scn, data) == NULL);
+ assert (data->d_off == 0);
+ assert (data->d_size == dso->shdr[i].sh_size);
+ maxndx = dso->shdr[i].sh_size / dso->shdr[i].sh_entsize;
+ relbuf = malloc (maxndx * sizeof (REL));
+ *reltype = dso->shdr[i].sh_type;
+ if (relbuf == NULL)
+ error (1, errno, "%s: Could not allocate memory", dso->filename);
+
+ symdata = elf_getdata (dso->scn[dso->shdr[i].sh_link], NULL);
+ assert (symdata != NULL && symdata->d_buf != NULL);
+ assert (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata) == NULL);
+ assert (symdata->d_off == 0);
+ assert (symdata->d_size == dso->shdr[dso->shdr[i].sh_link].sh_size);
+
+ for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx)
+ {
+ if (dso->shdr[i].sh_type == SHT_REL)
+ {
+ gelf_getrel (data, ndx, &rel);
+ rela.r_offset = rel.r_offset;
+ rela.r_info = rel.r_info;
+ rela.r_addend = 0;
+ }
+ else
+ gelf_getrela (data, ndx, &rela);
+ gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym);
+ /* 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. */
+ if (sym.st_shndx != debug_sections[DEBUG_STR].sec
+ && sym.st_shndx != debug_sections[DEBUG_LINE].sec
+ && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
+ continue;
+ rela.r_addend += sym.st_value;
+ rtype = ELF64_R_TYPE (rela.r_info);
+ switch (dso->ehdr.e_machine)
+ {
+ case EM_SPARC:
+ case EM_SPARC32PLUS:
+ case EM_SPARCV9:
+ if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32)
+ goto fail;
+ break;
+ case EM_386:
+ if (rtype != R_386_32)
+ goto fail;
+ break;
+ case EM_PPC:
+ case EM_PPC64:
+ if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32)
+ goto fail;
+ break;
+ case EM_S390:
+ if (rtype != R_390_32)
+ goto fail;
+ break;
+ case EM_IA_64:
+ if (rtype != R_IA64_SECREL32LSB)
+ goto fail;
+ break;
+ case EM_X86_64:
+ if (rtype != R_X86_64_32)
+ goto fail;
+ break;
+ case EM_ALPHA:
+ if (rtype != R_ALPHA_REFLONG)
+ goto fail;
+ break;
+#if defined(EM_AARCH64) && defined(R_AARCH64_ABS32)
+ case EM_AARCH64:
+ if (rtype != R_AARCH64_ABS32)
+ goto fail;
+ break;
+#endif
+ case EM_68K:
+ if (rtype != R_68K_32)
+ goto fail;
+ break;
+#if defined(EM_RISCV) && defined(R_RISCV_32)
+ case EM_RISCV:
+ if (rtype != R_RISCV_32)
+ goto fail;
+ break;
+#endif
+ default:
+ fail:
+ error (1, 0, "%s: Unhandled relocation %d in %s section",
+ dso->filename, rtype, sec->name);
+ }
+ relend->ptr = sec->data
+ + (rela.r_offset - base);
+ relend->addend = rela.r_addend;
+ relend->ndx = ndx;
+ ++(relend);
+ }
+ if (relbuf == relend)
+ {
+ free (relbuf);
+ relbuf = NULL;
+ relend = NULL;
+ }
+ else
+ qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp);
+
+ sec->relbuf = relbuf;
+ sec->relend = relend;
+ relptr = relbuf;
+}
+
+/* Updates SHT_RELA section associated with the given section based on
+ the relbuf data. The relbuf data is freed at the end. */
+static void
+update_rela_data (DSO *dso, struct debug_section *sec)
+{
+ Elf_Data *symdata;
+ int relsec_ndx = sec->relsec;
+ Elf_Data *data = elf_getdata (dso->scn[relsec_ndx], NULL);
+ symdata = elf_getdata (dso->scn[dso->shdr[relsec_ndx].sh_link],
+ NULL);
+
+ relptr = sec->relbuf;
+ relend = sec->relend;
+ while (relptr < relend)
+ {
+ GElf_Sym sym;
+ GElf_Rela rela;
+ int ndx = relptr->ndx;
+
+ if (gelf_getrela (data, ndx, &rela) == NULL)
+ error (1, 0, "Couldn't get relocation: %s",
+ elf_errmsg (-1));
+
+ if (gelf_getsym (symdata, GELF_R_SYM (rela.r_info),
+ &sym) == NULL)
+ error (1, 0, "Couldn't get symbol: %s", elf_errmsg (-1));
+
+ rela.r_addend = relptr->addend - sym.st_value;
+
+ if (gelf_update_rela (data, ndx, &rela) == 0)
+ error (1, 0, "Couldn't update relocations: %s",
+ elf_errmsg (-1));
+
+ ++relptr;
+ }
+ elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
+
+ free (sec->relbuf);
+}
+
struct abbrev_attr
{
unsigned int attr;
@@ -1743,20 +1947,6 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
return ptr;
}
-static int
-rel_cmp (const void *a, const void *b)
-{
- REL *rela = (REL *) a, *relb = (REL *) b;
-
- if (rela->ptr < relb->ptr)
- return -1;
-
- if (rela->ptr > relb->ptr)
- return 1;
-
- return 0;
-}
-
static int
line_rel_cmp (const void *a, const void *b)
{
@@ -1871,132 +2061,7 @@ edit_dwarf2 (DSO *dso)
htab_t abbrev;
struct abbrev_tag tag, *t;
int phase;
- REL *relbuf = NULL;
-
- if (debug_sections[DEBUG_INFO].relsec)
- {
- int ndx, maxndx;
- GElf_Rel rel;
- GElf_Rela rela;
- GElf_Sym sym;
- GElf_Addr base = dso->shdr[debug_sections[DEBUG_INFO].sec].sh_addr;
- Elf_Data *symdata = NULL;
- int rtype;
-
- i = debug_sections[DEBUG_INFO].relsec;
- scn = dso->scn[i];
- data = elf_getdata (scn, NULL);
- assert (data != NULL && data->d_buf != NULL);
- assert (elf_getdata (scn, data) == NULL);
- assert (data->d_off == 0);
- assert (data->d_size == dso->shdr[i].sh_size);
- maxndx = dso->shdr[i].sh_size / dso->shdr[i].sh_entsize;
- relbuf = malloc (maxndx * sizeof (REL));
- reltype = dso->shdr[i].sh_type;
- if (relbuf == NULL)
- error (1, errno, "%s: Could not allocate memory", dso->filename);
-
- symdata = elf_getdata (dso->scn[dso->shdr[i].sh_link], NULL);
- assert (symdata != NULL && symdata->d_buf != NULL);
- assert (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata)
- == NULL);
- assert (symdata->d_off == 0);
- assert (symdata->d_size
- == dso->shdr[dso->shdr[i].sh_link].sh_size);
-
- for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx)
- {
- if (dso->shdr[i].sh_type == SHT_REL)
- {
- gelf_getrel (data, ndx, &rel);
- rela.r_offset = rel.r_offset;
- rela.r_info = rel.r_info;
- rela.r_addend = 0;
- }
- else
- gelf_getrela (data, ndx, &rela);
- gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym);
- /* 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. */
- if (sym.st_shndx != debug_sections[DEBUG_STR].sec
- && sym.st_shndx != debug_sections[DEBUG_LINE].sec
- && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
- continue;
- rela.r_addend += sym.st_value;
- rtype = ELF64_R_TYPE (rela.r_info);
- switch (dso->ehdr.e_machine)
- {
- case EM_SPARC:
- case EM_SPARC32PLUS:
- case EM_SPARCV9:
- if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32)
- goto fail;
- break;
- case EM_386:
- if (rtype != R_386_32)
- goto fail;
- break;
- case EM_PPC:
- case EM_PPC64:
- if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32)
- goto fail;
- break;
- case EM_S390:
- if (rtype != R_390_32)
- goto fail;
- break;
- case EM_IA_64:
- if (rtype != R_IA64_SECREL32LSB)
- goto fail;
- break;
- case EM_X86_64:
- if (rtype != R_X86_64_32)
- goto fail;
- break;
- case EM_ALPHA:
- if (rtype != R_ALPHA_REFLONG)
- goto fail;
- break;
-#if defined(EM_AARCH64) && defined(R_AARCH64_ABS32)
- case EM_AARCH64:
- if (rtype != R_AARCH64_ABS32)
- goto fail;
- break;
-#endif
- case EM_68K:
- if (rtype != R_68K_32)
- goto fail;
- break;
-#if defined(EM_RISCV) && defined(R_RISCV_32)
- case EM_RISCV:
- if (rtype != R_RISCV_32)
- goto fail;
- break;
-#endif
- default:
- fail:
- error (1, 0, "%s: Unhandled relocation %d in .debug_info section",
- dso->filename, rtype);
- }
- relend->ptr = debug_sections[DEBUG_INFO].data
- + (rela.r_offset - base);
- relend->addend = rela.r_addend;
- relend->ndx = ndx;
- ++relend;
- }
- if (relbuf == relend)
- {
- free (relbuf);
- relbuf = NULL;
- relend = NULL;
- }
- else
- qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp);
- }
+ bool info_rel_updated = false;
for (phase = 0; phase < 2; phase++)
{
@@ -2008,7 +2073,8 @@ edit_dwarf2 (DSO *dso)
break;
ptr = debug_sections[DEBUG_INFO].data;
- relptr = relbuf;
+ setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
+ rel_updated = false;
endsec = ptr + debug_sections[DEBUG_INFO].size;
while (ptr < endsec)
{
@@ -2096,6 +2162,10 @@ edit_dwarf2 (DSO *dso)
htab_delete (abbrev);
}
+ /* 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
@@ -2240,41 +2310,8 @@ edit_dwarf2 (DSO *dso)
dirty_section (DEBUG_INFO);
/* Update any debug_info relocations addends we might have touched. */
- if (relbuf != NULL && reltype == SHT_RELA)
- {
- Elf_Data *symdata;
- int relsec_ndx = debug_sections[DEBUG_INFO].relsec;
- data = elf_getdata (dso->scn[relsec_ndx], NULL);
- symdata = elf_getdata (dso->scn[dso->shdr[relsec_ndx].sh_link],
- NULL);
-
- relptr = relbuf;
- while (relptr < relend)
- {
- GElf_Sym sym;
- GElf_Rela rela;
- int ndx = relptr->ndx;
-
- if (gelf_getrela (data, ndx, &rela) == NULL)
- error (1, 0, "Couldn't get relocation: %s",
- elf_errmsg (-1));
-
- if (gelf_getsym (symdata, GELF_R_SYM (rela.r_info),
- &sym) == NULL)
- error (1, 0, "Couldn't get symbol: %s", elf_errmsg (-1));
-
- rela.r_addend = relptr->addend - sym.st_value;
-
- if (gelf_update_rela (data, ndx, &rela) == 0)
- error (1, 0, "Couldn't update relocations: %s",
- elf_errmsg (-1));
-
- ++relptr;
- }
- elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
- }
-
- free (relbuf);
+ if (info_rel_updated)
+ update_rela_data (dso, &debug_sections[DEBUG_INFO]);
}
return 0;
--
2.23.0

@ -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

@ -0,0 +1,221 @@
From eb3ee2ab221f12937fb35d304ba96d1f626aee4b Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 10 Oct 2017 15:04:38 +0300
Subject: [PATCH 2/5] 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.
Backported from commits:
5af8ab60c652cda0bffcd4d65130bb57b5666ff0
07f1d3132f0c7b7ecb69a47a9930edb534a9250e
Tests are excluded from this backport since they would need significant
rework, the use case will be covered by Beaker.
Fixes: RHEL-39896
---
lib/rpmfi.c | 61 +++++++++++++++++++++++++++++++++++++++------
sign/rpmsignfiles.c | 30 ++++++++--------------
2 files changed, 64 insertions(+), 27 deletions(-)
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index 6c631fdb5..0aacd9f85 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -117,7 +117,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. */
@@ -589,10 +589,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;
}
@@ -1276,6 +1281,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);
@@ -1504,6 +1510,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)
{
@@ -1595,9 +1643,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 61b73bd40..3b87ae875 100644
--- a/sign/rpmsignfiles.c
+++ b/sign/rpmsignfiles.c
@@ -33,7 +33,7 @@ static const char *hash_algo_name[] = {
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
static char *signFile(const char *algo, const char *fdigest, int diglen,
-const char *key, char *keypass)
+const char *key, char *keypass, uint32_t *siglenp)
{
char *fsignature;
unsigned char digest[diglen];
@@ -60,32 +60,18 @@ const char *key, char *keypass)
return NULL;
}
+ *siglenp = siglen + 1;
/* convert file signature binary to hex */
fsignature = pgpHexStr(signature, siglen+1);
return fsignature;
}
-static uint32_t signatureLength(const char *algo, int diglen, const char *key,
-char *keypass)
-{
- unsigned char digest[diglen];
- unsigned char signature[MAX_SIGNATURE_LENGTH];
-
- memset(digest, 0, diglen);
- memset(signature, 0, MAX_SIGNATURE_LENGTH);
- signature[0] = '\x03';
-
- uint32_t siglen = sign_hash(algo, digest, diglen, key, keypass,
- signature+1);
- return siglen + 1;
-}
-
rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
{
struct rpmtd_s digests;
int algo;
int diglen;
- uint32_t siglen;
+ uint32_t siglen = 0;
const char *algoname;
const char *digest;
char *signature;
@@ -109,12 +95,11 @@ rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
headerDel(h, RPMTAG_FILESIGNATURELENGTH);
headerDel(h, RPMTAG_FILESIGNATURES);
- siglen = signatureLength(algoname, diglen, key, keypass);
- headerPutUint32(h, RPMTAG_FILESIGNATURELENGTH, &siglen, 1);
headerGet(h, RPMTAG_FILEDIGESTS, &digests, HEADERGET_MINMEM);
while ((digest = rpmtdNextString(&digests))) {
- signature = signFile(algoname, digest, diglen, key, keypass);
+ uint32_t slen = 0;
+ signature = signFile(algoname, digest, diglen, key, keypass, &slen);
if (!signature) {
rpmlog(RPMLOG_ERR, _("signFile failed\n"));
rc = RPMRC_FAIL;
@@ -127,8 +112,13 @@ rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
goto exit;
}
free(signature);
+ if (slen > siglen)
+ siglen = slen;
}
+ if (siglen > 0)
+ headerPutUint32(h, RPMTAG_FILESIGNATURELENGTH, &siglen, 1);
+
exit:
rpmtdFreeData(&digests);
return rc;
--
2.47.0

@ -0,0 +1,304 @@
From 201a71ce18734b1cebc337225f345fd754a6414f Mon Sep 17 00:00:00 2001
Message-Id: <201a71ce18734b1cebc337225f345fd754a6414f.1573552234.git.pmatilai@redhat.com>
In-Reply-To: <ce6e8556a8f93327d6de0446f21ac5e549861d82.1573552234.git.pmatilai@redhat.com>
References: <ce6e8556a8f93327d6de0446f21ac5e549861d82.1573552234.git.pmatilai@redhat.com>
From: Mark Wielaard <mark@klomp.org>
Date: Mon, 17 Jun 2019 11:23:25 +0200
Subject: [PATCH 2/3] Handle .debug_macro in debugedit.
When compiling with -g3 gcc will generate a .debug_macro section
which has pointers to the .debug_str section. Since we might rewrite
the .debug_str section, we also need to update any .debug_macro
pointers.
Updated the debugedit.at testcase by building everything with -g
and add various checks to see the .debug_macro section looks OK
after running debugedit. Added a new rpmbuild.at testcase to check
handing of .debug_macro in the whole rpmbuild debuginfo pipeline
to double check the separate .debug file also contains the macros.
Original patch by Michael Schroeder <mls@suse.de>. Extended by
Mark Wielaard <mark@klomp.org> to deal with relocations and possible
multiple COMDAT .debug_macro sections.
---
tests/Makefile.am | 1 +
tests/data/SPECS/hello-g3.spec | 60 ++++++++++
tests/debugedit.at | 79 ++++++++++++-
tests/rpmbuild.at | 33 ++++++
tools/debugedit.c | 196 +++++++++++++++++++++++++++++++--
5 files changed, 356 insertions(+), 13 deletions(-)
create mode 100644 tests/data/SPECS/hello-g3.spec
[ test-suite part edited out, too painful to backport ]
diff --git a/tools/debugedit.c b/tools/debugedit.c
index cf9cc3ca9..84483ef5e 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -41,6 +41,7 @@
#include <gelf.h>
#include <dwarf.h>
+
/* Unfortunately strtab manipulation functions were only officially added
to elfutils libdw in 0.167. Before that there were internal unsupported
ebl variants. While libebl.h isn't supported we'll try to use it anyway
@@ -432,6 +433,7 @@ typedef struct debug_section
int sec, relsec;
REL *relbuf;
REL *relend;
+ struct debug_section *next; /* Only happens for COMDAT .debug_macro. */
} debug_section;
static debug_section debug_sections[] =
@@ -1989,11 +1991,35 @@ edit_dwarf2 (DSO *dso)
for (j = 0; debug_sections[j].name; ++j)
if (strcmp (name, debug_sections[j].name) == 0)
{
+ struct debug_section *debug_sec = &debug_sections[j];
if (debug_sections[j].data)
{
- error (0, 0, "%s: Found two copies of %s section",
- dso->filename, name);
- return 1;
+ if (j != DEBUG_MACRO)
+ {
+ error (0, 0, "%s: Found two copies of %s section",
+ dso->filename, name);
+ return 1;
+ }
+ else
+ {
+ /* In relocatable files .debug_macro 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";
+
+ struct debug_section *macro_sec = debug_sec;
+ while (macro_sec->next != NULL)
+ macro_sec = macro_sec->next;
+
+ macro_sec->next = sec;
+ debug_sec = sec;
+ }
}
scn = dso->scn[i];
@@ -2002,10 +2028,10 @@ edit_dwarf2 (DSO *dso)
assert (elf_getdata (scn, data) == NULL);
assert (data->d_off == 0);
assert (data->d_size == dso->shdr[i].sh_size);
- debug_sections[j].data = data->d_buf;
- debug_sections[j].elf_data = data;
- debug_sections[j].size = data->d_size;
- debug_sections[j].sec = i;
+ debug_sec->data = data->d_buf;
+ debug_sec->elf_data = data;
+ debug_sec->size = data->d_size;
+ debug_sec->sec = i;
break;
}
@@ -2028,7 +2054,26 @@ edit_dwarf2 (DSO *dso)
+ (dso->shdr[i].sh_type == SHT_RELA),
debug_sections[j].name) == 0)
{
- debug_sections[j].relsec = i;
+ if (j == DEBUG_MACRO)
+ {
+ /* Pick the correct one. */
+ int rel_target = dso->shdr[i].sh_info;
+ struct debug_section *macro_sec = &debug_sections[j];
+ while (macro_sec != NULL)
+ {
+ if (macro_sec->sec == rel_target)
+ {
+ macro_sec->relsec = i;
+ break;
+ }
+ macro_sec = macro_sec->next;
+ }
+ if (macro_sec == NULL)
+ error (0, 1, "No .debug_macro reloc section: %s",
+ dso->filename);
+ }
+ else
+ debug_sections[j].relsec = i;
break;
}
}
@@ -2062,6 +2107,7 @@ edit_dwarf2 (DSO *dso)
struct abbrev_tag tag, *t;
int phase;
bool info_rel_updated = false;
+ bool macro_rel_updated = false;
for (phase = 0; phase < 2; phase++)
{
@@ -2279,6 +2325,113 @@ edit_dwarf2 (DSO *dso)
}
}
+ /* 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)
+ {
+ 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;
+
+ while (ptr < endsec)
+ {
+ 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);
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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. */
@@ -2308,10 +2461,24 @@ edit_dwarf2 (DSO *dso)
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 debug_info relocations addends we might have touched. */
+ /* Update any relocations addends we might have touched. */
if (info_rel_updated)
update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+
+ if (macro_rel_updated)
+ {
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+ while (macro_sec != NULL)
+ {
+ update_rela_data (dso, macro_sec);
+ macro_sec = macro_sec->next;
+ }
+ }
}
return 0;
@@ -2843,6 +3010,17 @@ main (int argc, char *argv[])
destroy_lines (&dso->lines);
free (dso);
+ /* In case there were multiple (COMDAT) .debug_macro sections,
+ free them. */
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+ macro_sec = macro_sec->next;
+ while (macro_sec != NULL)
+ {
+ struct debug_section *next = macro_sec->next;
+ free (macro_sec);
+ macro_sec = next;
+ }
+
poptFreeContext (optCon);
return 0;
--
2.23.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

@ -0,0 +1,77 @@
From 172e1f5ec0e37c8aab91a2ae35bd73ea594432cb Mon Sep 17 00:00:00 2001
Message-Id: <172e1f5ec0e37c8aab91a2ae35bd73ea594432cb.1571920849.git.pmatilai@redhat.com>
In-Reply-To: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
References: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 4 Oct 2018 13:36:09 +0300
Subject: [PATCH 2/5] Use Python 3 -compatible exception syntax in tests
Makes a few tests pass that failed before, and others now fail
a little bit later...
(cherry picked from commit 511eef19298765e3639bccbe98bc3a50023f45b2)
---
tests/rpmpython.at | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/rpmpython.at b/tests/rpmpython.at
index 3a7c251f1..1daaf1216 100644
--- a/tests/rpmpython.at
+++ b/tests/rpmpython.at
@@ -96,7 +96,7 @@ for a in ['name', 'bugurl', '__class__', '__foo__', ]:
try:
x = getattr(h, a)
myprint(x)
- except AttributeError, exc:
+ except AttributeError as exc:
myprint(exc)
],
[testpkg-5:1.0-1.noarch
@@ -119,7 +119,7 @@ h2['dirindexes'] = [ 0, 0, 1 ]
for h in [h1, h2]:
try:
myprint(','.join(h['filenames']))
- except rpm.error, exc:
+ except rpm.error as exc:
myprint(exc)
],
[invalid header data
@@ -164,7 +164,7 @@ rpm.setLogFile(sink)
try:
h = ts.hdrFromFdno('${RPMDATA}/RPMS/hello-2.0-1.x86_64-signed.rpm')
myprint(h['arch'])
-except rpm.error, e:
+except rpm.error as e:
myprint(e)
],
[public key not available
@@ -183,7 +183,7 @@ ts.setKeyring(keyring)
try:
h = ts.hdrFromFdno('${RPMDATA}/RPMS/hello-2.0-1.x86_64-signed.rpm')
myprint(h['arch'])
-except rpm.error, e:
+except rpm.error as e:
myprint(e)
],
[x86_64]
@@ -207,7 +207,7 @@ h = rpm.hdr()
h['name'] = "foo"
try:
ts.addInstall(h, 'foo', 'u')
-except rpm.error, err:
+except rpm.error as err:
myprint(err)
for e in ts:
myprint(e.NEVRA())
@@ -228,7 +228,7 @@ h['dirnames'] = ['/opt' '/flopt']
h['dirindexes'] = [ 1, 2, 3 ]
try:
ts.addInstall(h, 'foo', 'u')
-except rpm.error, err:
+except rpm.error as err:
myprint(err)
for e in ts:
myprint(e.NEVRA())
--
2.21.0

@ -0,0 +1,44 @@
From 6525a9bf1529944741f273cb9fde5619f006a673 Mon Sep 17 00:00:00 2001
Message-Id: <6525a9bf1529944741f273cb9fde5619f006a673.1571920849.git.pmatilai@redhat.com>
In-Reply-To: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
References: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 4 Oct 2018 17:41:19 +0300
Subject: [PATCH 3/5] Fix couple of bytes vs strings issues in Python tests
For the purposes of rpmio testing and importing public key, we're
dealing with bytes rather than encoded strings. In the carefree days
of Python 2 such details didn't matter, in Python 3 they cause failures.
The signed package test still fails after this one but it's due to
a more general issue.
(cherry picked from commit 86f7898dd6a7fa8718c02675f5a7ee04ff987422)
---
tests/rpmpython.at | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/rpmpython.at b/tests/rpmpython.at
index 1daaf1216..ae020ae95 100644
--- a/tests/rpmpython.at
+++ b/tests/rpmpython.at
@@ -33,7 +33,7 @@ prexp(mname)
[])
RPMPY_TEST([basic rpmio],[
-msg = 'Killroy was here\n'
+msg = b'Killroy was here\n'
data = msg * 10
# TODO: test other compression types too if built in
for iot in [ 'fpio', 'fdio', 'ufdio', 'gzdio' ]:
@@ -173,7 +173,7 @@ except rpm.error as e:
RPMPY_TEST([reading a signed package file 2],[
-keydata = open('${RPMDATA}/keys/rpm.org-rsa-2048-test.pub').read()
+keydata = open('${RPMDATA}/keys/rpm.org-rsa-2048-test.pub', 'rb').read()
pubkey = rpm.pubkey(keydata)
keyring = rpm.keyring()
keyring.addKey(pubkey)
--
2.21.0

@ -0,0 +1,94 @@
From 9d01648f6752785be07a96498af0505d04170ec1 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 26 Jul 2024 10:43:50 +0200
Subject: [PATCH 3/5] Fix root relocation regression
When relocating the root directory, make sure we insert the new path's
dirname to dirNames[] even if the root itself is owned by the package.
This appears to have been the intention from the first version (largely
untouched since) of this code as we allow the root to pass through the
first checks (by setting len to 0 in that case) as well as the second
for loop where we do the relocations.
This allows fsm to properly create and remove the relocated directory
since we're now using fd-based calls (#1919) and the parent directory
needs to be opened first.
No need to do string comparison here, the empty basename signals that
we're processing the root directory, so just use that.
Building a relocatable package that owns the root directory seems to be
a handy way to create user-installable packages (see RHEL-28967) and it
happened to work before with the path-based calls so this technically
was a regression. Add a test that emulates this use case.
Backported from commits:
31c14ba6610568c2d634647fed1fb57221178da9
308ac60677732e9979b9ce11e5a3085906da1901
Tests are excluded from this backport since they would need significant
rework, the use case will be covered by Beaker.
Fixes: RHEL-49494
---
lib/relocation.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/lib/relocation.c b/lib/relocation.c
index 3ba4cfeab..8c35bc1a7 100644
--- a/lib/relocation.c
+++ b/lib/relocation.c
@@ -123,7 +123,7 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,
char ** baseNames;
char ** dirNames;
uint32_t * dirIndexes;
- rpm_count_t fileCount, dirCount;
+ rpm_count_t fileCount, dirCount, dirCountOrig;
int nrelocated = 0;
int fileAlloced = 0;
char * fn = NULL;
@@ -162,7 +162,7 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,
baseNames = bnames.data;
dirIndexes = dindexes.data;
fileCount = rpmtdCount(&bnames);
- dirCount = rpmtdCount(&dnames);
+ dirCount = dirCountOrig = rpmtdCount(&dnames);
/* XXX TODO: use rpmtdDup() instead */
dirNames = dnames.data = duparray(dnames.data, dirCount);
dnames.flags |= RPMTD_PTR_ALLOCED;
@@ -179,8 +179,9 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,
rpmFileTypes ft;
int fnlen;
+ size_t baselen = strlen(baseNames[i]);
size_t len = maxlen +
- strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;
+ strlen(dirNames[dirIndexes[i]]) + baselen + 1;
if (len >= fileAlloced) {
fileAlloced = len * 2;
fn = xrealloc(fn, fileAlloced);
@@ -242,8 +243,9 @@ assert(fn != NULL); /* XXX can't happen */
continue;
}
- /* Relocation on full paths only, please. */
- if (fnlen != len) continue;
+ /* Relocation on '/' and full paths only, please. */
+ if (baselen && fnlen != len)
+ continue;
rpmlog(RPMLOG_DEBUG, "relocating %s to %s\n",
fn, relocations[j].newPath);
@@ -294,7 +296,7 @@ assert(fn != NULL); /* XXX can't happen */
}
/* Finish off by relocating directories. */
- for (i = dirCount - 1; i >= 0; i--) {
+ for (i = dirCountOrig - 1; i >= 0; i--) {
for (j = numRelocations - 1; j >= 0; j--) {
if (relocations[j].oldPath == NULL) /* XXX can't happen */
--
2.47.0

@ -0,0 +1,114 @@
From df089e178da0918dc74a8572a99324b0987bce30 Mon Sep 17 00:00:00 2001
Message-Id: <df089e178da0918dc74a8572a99324b0987bce30.1554983206.git.pmatilai@redhat.com>
In-Reply-To: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
References: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 18 Mar 2019 15:56:34 +0200
Subject: [PATCH 3/3] Verify packages before signing (RhBug:1646388)
Permitting corrupted packages to be signed is bad business for everybody
involved, this is something we should've always done. Besides being an
actual security risk, it can lead to odd results with verification
especially with the payload digest on signed packages.
One point worth noting is that this means that pre 4.14-packages cannot
be signed in FIPS mode now because there's no way to validate the package
payload range due to MD5 being disabled. This seems like a feature and
not a limitation, so disabler for the verify step intentionally left out.
Optimally we'd verify the package on the same read that's passed
to gpg but for simplicitys sake that's left as an future exercise,
now we simply read the package twice.
---
sign/rpmgensig.c | 32 ++++++++++++++++++++++++++++++++
tests/rpmsigdig.at | 20 ++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index 2bcbab768..5be542001 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -21,6 +21,7 @@
#include "lib/rpmlead.h"
#include "lib/signature.h"
+#include "lib/rpmvs.h"
#include "sign/rpmsignfiles.h"
#include "debug.h"
@@ -489,6 +490,31 @@ static rpmRC includeFileSignatures(Header *sigp, Header *hdrp)
#endif
}
+static int msgCb(struct rpmsinfo_s *sinfo, void *cbdata)
+{
+ char **msg = cbdata;
+ if (sinfo->rc && *msg == NULL)
+ *msg = rpmsinfoMsg(sinfo);
+ return (sinfo->rc != RPMRC_FAIL);
+}
+
+/* Require valid digests on entire package for signing. */
+static int checkPkg(FD_t fd, char **msg)
+{
+ int rc;
+ struct rpmvs_s *vs = rpmvsCreate(RPMSIG_DIGEST_TYPE, 0, NULL);
+ off_t offset = Ftell(fd);
+
+ Fseek(fd, 0, SEEK_SET);
+ rc = rpmpkgRead(vs, fd, NULL, NULL, msg);
+ if (!rc)
+ rc = rpmvsVerify(vs, RPMSIG_DIGEST_TYPE, msgCb, msg);
+ Fseek(fd, offset, SEEK_SET);
+
+ rpmvsFree(vs);
+ return rc;
+}
+
/** \ingroup rpmcli
* Create/modify elements in signature header.
* @param rpm path to package
@@ -519,6 +545,12 @@ static int rpmSign(const char *rpm, int deleting, int signfiles)
if (manageFile(&fd, rpm, O_RDWR))
goto exit;
+ /* Ensure package is intact before attempting to sign */
+ if ((rc = checkPkg(fd, &msg))) {
+ rpmlog(RPMLOG_ERR, "not signing corrupt package %s: %s\n", rpm, msg);
+ goto exit;
+ }
+
if ((rc = rpmLeadRead(fd, &msg)) != RPMRC_OK) {
rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, msg);
goto exit;
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
index 413c3d2c8..e93420306 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -472,3 +472,23 @@ run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64-sign
[],
[])
AT_CLEANUP
+
+AT_SETUP([rpmsign --addsign <corrupted>])
+AT_KEYWORDS([rpmsign signature])
+AT_CHECK([
+RPMDB_CLEAR
+RPMDB_INIT
+rm -rf "${TOPDIR}"
+
+pkg="hello-2.0-1.x86_64.rpm"
+cp "${RPMTEST}"/data/RPMS/${pkg} "${RPMTEST}"/tmp/${pkg}
+dd if=/dev/zero of="${RPMTEST}"/tmp/${pkg} \
+ conv=notrunc bs=1 seek=333 count=4 2> /dev/null
+run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}/tmp/${pkg}"
+],
+[1],
+[/home/pmatilai/repos/rpm/tests/testing/tmp/hello-2.0-1.x86_64.rpm:
+],
+[error: not signing corrupt package /home/pmatilai/repos/rpm/tests/testing/tmp/hello-2.0-1.x86_64.rpm: MD5 digest: BAD (Expected 007ca1d8b35cca02a1854ba301c5432e != 137ca1d8b35cca02a1854ba301c5432e)
+])
+AT_CLEANUP
--
2.20.1

@ -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

@ -0,0 +1,30 @@
From 00a0afd5e079a73ef6871f1538f34fa4e67892e6 Mon Sep 17 00:00:00 2001
Message-Id: <00a0afd5e079a73ef6871f1538f34fa4e67892e6.1573552234.git.pmatilai@redhat.com>
In-Reply-To: <ce6e8556a8f93327d6de0446f21ac5e549861d82.1573552234.git.pmatilai@redhat.com>
References: <ce6e8556a8f93327d6de0446f21ac5e549861d82.1573552234.git.pmatilai@redhat.com>
From: Mark Wielaard <mark@klomp.org>
Date: Mon, 17 Jun 2019 11:23:26 +0200
Subject: [PATCH 3/3] debugedit: Make sure .debug_line old/new idx start equal.
Found by running the debugedit tests under valgrind.
If the old and new .debug_line offset isn't changed then we might
write out an uninitialized new_idx.
---
tools/debugedit.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/debugedit.c b/tools/debugedit.c
index 84483ef5e..9f8dcd0fb 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1177,6 +1177,7 @@ get_line_table (DSO *dso, size_t off, struct line_table **table)
*table = NULL;
t->old_idx = off;
+ t->new_idx = off;
t->size_diff = 0;
t->replace_dirs = false;
t->replace_files = false;
--
2.23.0

@ -0,0 +1,109 @@
From 0b1456ed4c00a021389acea4b6b10d475986b660 Mon Sep 17 00:00:00 2001
Message-Id: <0b1456ed4c00a021389acea4b6b10d475986b660.1571920849.git.pmatilai@redhat.com>
In-Reply-To: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
References: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 4 Oct 2018 18:05:37 +0300
Subject: [PATCH 4/5] Bump the minimum Python version requirement to 2.7
Older Python versions are long since past their EOL, we don't need to
support them either. Python 2.7 is also the least incompatible version
compared to Python 3, going forward. Nuke the now unnecessary compat
macros.
(cherry picked from commit 3f3cb3eabf7bb49dcc6e691601f89500b3487e06)
---
configure.ac | 2 +-
python/header-py.c | 4 ++--
python/rpmsystem-py.h | 33 ---------------------------------
python/spec-py.c | 2 +-
4 files changed, 4 insertions(+), 37 deletions(-)
diff --git a/configure.ac b/configure.ac
index 34ea85f9f..4d1a48e5f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -800,7 +800,7 @@ esac],
WITH_PYTHON_SUBPACKAGE=0
AS_IF([test "$enable_python" = yes],[
- AM_PATH_PYTHON([2.6],[
+ AM_PATH_PYTHON([2.7],[
PKG_CHECK_MODULES([PYTHON], [python-${PYTHON_VERSION}], [WITH_PYTHON_SUBPACKAGE=1])
AC_SUBST(PYTHON_CFLAGS)
AC_SUBST(PYTHON_LIB)
diff --git a/python/header-py.c b/python/header-py.c
index 628b48534..c9d54e869 100644
--- a/python/header-py.c
+++ b/python/header-py.c
@@ -376,8 +376,8 @@ static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
if (obj == NULL) {
h = headerNew();
- } else if (CAPSULE_CHECK(obj)) {
- h = CAPSULE_EXTRACT(obj, "rpm._C_Header");
+ } else if (PyCapsule_CheckExact(obj)) {
+ h = PyCapsule_GetPointer(obj, "rpm._C_Header");
headerLink(h);
} else if (hdrObject_Check(obj)) {
h = headerCopy(((hdrObject*) obj)->h);
diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
index c8423e3dc..955d60cd3 100644
--- a/python/rpmsystem-py.h
+++ b/python/rpmsystem-py.h
@@ -9,39 +9,6 @@
#include <Python.h>
#include <structmember.h>
-#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) < 0x0205
-typedef ssize_t Py_ssize_t;
-typedef Py_ssize_t (*lenfunc)(PyObject *);
-#endif
-
-/* Compatibility macros for Python < 2.6 */
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size) \
- PyObject_HEAD_INIT(type) size,
-#endif
-
-#ifndef Py_TYPE
-#define Py_TYPE(o) ((o)->ob_type)
-#endif
-
-#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) < 0x0206
-#define PyBytes_Check PyString_Check
-#define PyBytes_FromString PyString_FromString
-#define PyBytes_FromStringAndSize PyString_FromStringAndSize
-#define PyBytes_Size PyString_Size
-#define PyBytes_AsString PyString_AsString
-#endif
-
-#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) >= 0x0207
-#define CAPSULE_BUILD(ptr,name) PyCapsule_New(ptr, name, NULL)
-#define CAPSULE_CHECK(obj) PyCapsule_CheckExact(obj)
-#define CAPSULE_EXTRACT(obj,name) PyCapsule_GetPointer(obj, name)
-#else
-#define CAPSULE_BUILD(ptr,name) PyCObject_FromVoidPtr(ptr, NULL)
-#define CAPSULE_CHECK(obj) PyCObject_Check(obj)
-#define CAPSULE_EXTRACT(obj,name) PyCObject_AsVoidPtr(obj)
-#endif
-
/* For Python 3, use the PyLong type throughout in place of PyInt */
#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
diff --git a/python/spec-py.c b/python/spec-py.c
index fa7e58928..4efdbf4bf 100644
--- a/python/spec-py.c
+++ b/python/spec-py.c
@@ -34,7 +34,7 @@ static PyObject *makeHeader(Header h)
PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm");
if (rpmmod == NULL) return NULL;
- PyObject *ptr = CAPSULE_BUILD(h, "rpm._C_Header");
+ PyObject *ptr = PyCapsule_New(h, "rpm._C_Header", NULL);
PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr);
Py_XDECREF(ptr);
Py_XDECREF(rpmmod);
--
2.21.0

@ -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

@ -0,0 +1,215 @@
From 1e6cdb256c06b084501f5016d10bb5c8465c8287 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 19 Aug 2024 11:03:10 +0300
Subject: [PATCH 4/5] Report unsafe symlinks during installation as a specific
case
RPM refuses to follow non root owned symlinks pointing to files owned by
another user for security reasons. This case was lumped in with
O_DIRECTORY behavior, leading to confusing error message as the symlink
often indeed points at a directory. Emit a more meaningful error message
when encountering unsafe symlinks.
We already detect the error condition in the main if block here, might
as well set the error code right there and then so we don't need to
redetect later. We previously only tested for the unsafe link condition
when our O_DIRECTORY equivalent was set, but that seems wrong. Probably
doesn't matter with the existing callers, but we really must not
follow those unsafe symlinks no matter what.
Co-authored-by: Florian Festi <ffesti@redhat.com>
Backported from commits:
14516542c113560dc0070df2f9102568a7a71b58
535eacc96ae6fe5289a2917bb0af43e491b0f4f4
Tests are excluded from this backport since they would need significant
rework, the use case will be covered by Beaker.
Fixes: RHEL-39897
---
lib/fsm.c | 70 +++++++++++++++++++++++++++--------------------------
lib/rpmfi.c | 1 +
2 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/lib/fsm.c b/lib/fsm.c
index 9dd50b784..720d4a2ec 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -65,7 +65,7 @@ struct filedata_s {
* things around needlessly
*/
static const char * fileActionString(rpmFileAction a);
-static int fsmOpenat(int dirfd, const char *path, int flags, int dir);
+static int fsmOpenat(int *fdp, int dirfd, const char *path, int flags, int dir);
static int fsmClose(int *wfdp);
/** \ingroup payload
@@ -98,9 +98,9 @@ static int fsmLink(int odirfd, const char *opath, int dirfd, const char *path)
#ifdef WITH_CAP
static int cap_set_fileat(int dirfd, const char *path, cap_t fcaps)
{
- int rc = -1;
- int fd = fsmOpenat(dirfd, path, O_RDONLY|O_NOFOLLOW, 0);
- if (fd >= 0) {
+ int fd = -1;
+ int rc = fsmOpenat(&fd, dirfd, path, O_RDONLY|O_NOFOLLOW, 0);
+ if (!rc) {
rc = cap_set_fd(fd, fcaps);
fsmClose(&fd);
}
@@ -299,12 +299,12 @@ static int fsmMkdir(int dirfd, const char *path, mode_t mode)
return rc;
}
-static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
+static int fsmOpenat(int *wfdp, 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;
+ int rc = 0;
/*
* Only ever follow symlinks by root or target owner. Since we can't
@@ -313,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) {
- ffd = openat(dirfd, path, flags);
+ int ffd = openat(dirfd, path, flags);
if (ffd >= 0) {
if (fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) {
if (fstat(ffd, &sb) == 0) {
@@ -322,17 +322,26 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
}
}
}
- if (ffd != fd)
+ /* Symlink with non-matching owners */
+ if (ffd != fd) {
close(ffd);
+ rc = RPMERR_INVALID_SYMLINK;
+ }
}
}
/* O_DIRECTORY equivalent */
- if (dir && ((fd != ffd) || (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)))) {
- errno = ENOTDIR;
+ if (!rc && dir && fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode))
+ rc = RPMERR_ENOTDIR;
+
+ if (!rc && fd < 0)
+ rc = RPMERR_OPEN_FAILED;
+
+ if (rc)
fsmClose(&fd);
- }
- return fd;
+
+ *wfdp = fd;
+ return rc;
}
static int fsmDoMkDir(rpmPlugins plugins, int dirfd, const char *dn,
@@ -351,9 +360,7 @@ static int fsmDoMkDir(rpmPlugins plugins, int dirfd, const char *dn,
rc = fsmMkdir(dirfd, dn, mode);
if (!rc) {
- *fdp = fsmOpenat(dirfd, dn, O_RDONLY|O_NOFOLLOW, 1);
- if (*fdp == -1)
- rc = RPMERR_ENOTDIR;
+ rc = fsmOpenat(fdp, dirfd, dn, O_RDONLY|O_NOFOLLOW, 1);
}
if (!rc) {
@@ -378,47 +385,44 @@ static int ensureDir(rpmPlugins plugins, const char *p, int owned, int create,
char *sp = NULL, *bn;
char *apath = NULL;
int oflags = O_RDONLY;
- int rc = 0;
if (*dirfdp >= 0)
- return rc;
+ return 0;
- int dirfd = fsmOpenat(-1, "/", oflags, 1);
+ int dirfd = -1;
+ int rc = fsmOpenat(&dirfd, -1, "/", oflags, 1);
int fd = dirfd; /* special case of "/" */
char *path = xstrdup(p);
char *dp = path;
while ((bn = strtok_r(dp, "/", &sp)) != NULL) {
- fd = fsmOpenat(dirfd, bn, oflags, 1);
+ rc = fsmOpenat(&fd, dirfd, bn, oflags, 1);
/* assemble absolute path for plugins benefit, sigh */
apath = rstrscat(&apath, "/", bn, NULL);
- if (fd < 0 && errno == ENOENT && create) {
+ if (rc && errno == ENOENT && create) {
mode_t mode = S_IFDIR | (_dirPerms & 07777);
rc = fsmDoMkDir(plugins, dirfd, bn, apath, owned, mode, &fd);
}
fsmClose(&dirfd);
- if (fd >= 0) {
- dirfd = fd;
- } else {
- if (!quiet) {
- rpmlog(RPMLOG_ERR, _("failed to open dir %s of %s: %s\n"),
- bn, p, strerror(errno));
- }
- rc = RPMERR_OPEN_FAILED;
+ if (rc)
break;
- }
+ dirfd = fd;
dp = NULL;
}
if (rc) {
+ if (!quiet) {
+ char *msg = rpmfileStrerror(rc);
+ rpmlog(RPMLOG_ERR, _("failed to open dir %s of %s: %s\n"),
+ bn, p, msg);
+ free(msg);
+ }
fsmClose(&fd);
fsmClose(&dirfd);
- } else {
- rc = 0;
}
*dirfdp = dirfd;
@@ -1025,10 +1029,8 @@ setmeta:
/* Only follow safe symlinks, and never on temporary files */
if (fp->suffix)
flags |= AT_SYMLINK_NOFOLLOW;
- fd = fsmOpenat(di.dirfd, fp->fpath, flags,
+ rc = fsmOpenat(&fd, di.dirfd, fp->fpath, flags,
S_ISDIR(fp->sb.st_mode));
- if (fd < 0)
- rc = RPMERR_OPEN_FAILED;
}
if (!rc && fp->setmeta) {
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index 0aacd9f85..821bae875 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -2432,6 +2432,7 @@ char * rpmfileStrerror(int rc)
case RPMERR_DIGEST_MISMATCH: s = _("Digest mismatch"); break;
case RPMERR_INTERNAL: s = _("Internal error"); break;
case RPMERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
+ case RPMERR_INVALID_SYMLINK: s = _("Unsafe symlink"); break;
case RPMERR_ENOENT: s = strerror(ENOENT); break;
case RPMERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break;
case RPMERR_EXIST_AS_DIR:
--
2.47.0

@ -0,0 +1,41 @@
From 98470eccf09b80ed11528ac893852d649c50be72 Mon Sep 17 00:00:00 2001
Message-Id: <98470eccf09b80ed11528ac893852d649c50be72.1571920849.git.pmatilai@redhat.com>
In-Reply-To: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
References: <6b6c4d881dc6fc99f949dac4aaf9a513542f9956.1571920849.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 5 Oct 2018 14:05:27 +0300
Subject: [PATCH 5/5] Drop an unnecessary Python 2 vs 3 incompatibility from
the test
Python 2 speaks about 'type' whereas 3 speaks about 'class', which from
our perspective is just unnecessary pain with no gain.
(cherry picked from commit ff3d8ac2e5cb4456ad1355f227f3ccef08e01972)
---
tests/rpmpython.at | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tests/rpmpython.at b/tests/rpmpython.at
index ae020ae95..bc42e49e4 100644
--- a/tests/rpmpython.at
+++ b/tests/rpmpython.at
@@ -92,7 +92,7 @@ h['arch'] = 'noarch'
myprint(h['nevra'])
del h['epoch']
myprint(h['nevra'])
-for a in ['name', 'bugurl', '__class__', '__foo__', ]:
+for a in ['name', 'bugurl', '__foo__', ]:
try:
x = getattr(h, a)
myprint(x)
@@ -103,7 +103,6 @@ for a in ['name', 'bugurl', '__class__', '__foo__', ]:
testpkg-1.0-1.noarch
testpkg
None
-<type 'rpm.hdr'>
'rpm.hdr' object has no attribute '__foo__']
)
--
2.21.0

@ -0,0 +1,46 @@
From 79b3aa74dda434dadb3a4477f0be6981fbe5ad74 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 18 Oct 2024 14:50:35 +0300
Subject: [PATCH 5/5] Fix FA_TOUCH'ed files getting removed on failed update
On install/update, most files are laid down with a temporary suffix
and if the update fails, removing those at the end of the loop is
the right thing to do. However FA_TOUCH'ed files were already there,
we only update their metadata, and we better not remove them!
AFAICS this all versions since rpm >= 4.14 in one way or the other.
If %_minimize_writes is enabled then it affects way more than just
unmodified config files.
The test is a simplified version of pam update failing in the original
report. Technically, --nomtime should not be needed for the test
verification but we don't even try to restore the metadata on failure,
and fixing that is way out of scope here.
Backported from commits:
027ef640b33b38ca257bb301bb302e9c71d43c27
Tests are excluded from this backport since they would need significant
rework, the use case will be covered by Beaker.
Fixes: RHEL-63069
---
lib/fsm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/fsm.c b/lib/fsm.c
index 720d4a2ec..91155c13c 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -1093,7 +1093,7 @@ setmeta:
if (ensureDir(NULL, rpmfiDN(fi), 0, 0, 1, &di.dirfd))
continue;
- if (fp->stage > FILE_NONE && !fp->skip) {
+ if (fp->stage > FILE_NONE && !fp->skip && fp->action != FA_TOUCH) {
(void) fsmRemove(di.dirfd, fp->fpath, fp->sb.st_mode);
}
}
--
2.47.0

@ -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

@ -0,0 +1,46 @@
From acbf558c486ee3518aca74045504f05872da4a58 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Tue, 26 Sep 2023 13:14:44 +0200
Subject: [PATCH] brp-python-bytecompile compatibility with newer pythons
---
scripts/brp-python-bytecompile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/brp-python-bytecompile b/scripts/brp-python-bytecompile
index 4a9b49e..472bf10 100644
--- a/scripts/brp-python-bytecompile
+++ b/scripts/brp-python-bytecompile
@@ -58,7 +58,7 @@ EOF
# and below /usr/lib/python3.1/, we're targeting /usr/bin/python3.1
shopt -s nullglob
-for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]$"`;
+for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]+$"`;
do
python_binary=/usr/bin/$(basename $python_libdir)
if [ "$python_binary" = "/usr/bin/python3.6" ]; then
@@ -97,17 +97,17 @@ fi
# Figure out if there are files to be bytecompiled with the default_python at all
# this prevents unnecessary default_python invocation
-find "$RPM_BUILD_ROOT" -type f -name "*.py" | grep -Ev "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" || exit 0
+find "$RPM_BUILD_ROOT" -type f -name "*.py" | grep -Ev "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]+|/usr/share/doc" || exit 0
# Generate normal (.pyc) byte-compiled files.
-python_bytecompile "" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/"
+python_bytecompile "" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]+|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/"
if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then
# One or more of the files had a syntax error
exit 1
fi
# Generate optimized (.pyo) byte-compiled files.
-python_bytecompile "-O" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/"
+python_bytecompile "-O" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]+|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/"
if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then
# One or more of the files had a syntax error
exit 1
--
2.41.0

@ -0,0 +1,26 @@
From 682397a8e2758058f780cccd51b570d39415b9b2 Mon Sep 17 00:00:00 2001
From: Tomas Orsava <torsava@redhat.com>
Date: Tue, 3 Jul 2018 14:58:32 +0200
Subject: [PATCH] Compile with Platform-Python binary where relevant
---
scripts/brp-python-bytecompile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/scripts/brp-python-bytecompile b/scripts/brp-python-bytecompile
index 7ed1d7f..9d0a421 100644
--- a/scripts/brp-python-bytecompile
+++ b/scripts/brp-python-bytecompile
@@ -60,6 +60,9 @@ shopt -s nullglob
for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]$"`;
do
python_binary=/usr/bin/$(basename $python_libdir)
+ if [ "$python_binary" = "/usr/bin/python3.6" ]; then
+ python_binary=/usr/libexec/platform-python
+ fi
real_libdir=${python_libdir/$RPM_BUILD_ROOT/}
echo "Bytecompiling .py files below $python_libdir using $python_binary"
--
2.14.4

@ -0,0 +1,11 @@
--- a/platform.in 2018-07-19 17:24:58.737922904 +0200
+++ b/platform.in 2018-07-19 17:25:25.480028741 +0200
@@ -65,7 +65,7 @@
%__arch_install_post @ARCH_INSTALL_POST@
%_python_bytecompile_errors_terminate_build 0
-%_python_bytecompile_extra 1
+%_python_bytecompile_extra 0
# Standard brp-macro naming:
# convert all '-' in basename to '_', add two leading underscores.

@ -0,0 +1,11 @@
--- rpm-4.14.3/plugins/selinux.c.orig 2020-05-11 16:07:22.873791795 +0200
+++ rpm-4.14.3/plugins/selinux.c 2020-05-11 16:10:11.701771157 +0200
@@ -47,7 +47,7 @@
sehandle = selabel_open(SELABEL_CTX_FILE, opts, 1);
- rpmlog(RPMLOG_DEBUG, "selabel_open: (%s) %s\n",
+ rpmlog((sehandle == NULL) ? RPMLOG_ERR : RPMLOG_DEBUG, "selabel_open: (%s) %s\n",
path, (sehandle == NULL ? strerror(errno) : ""));
return (sehandle != NULL) ? RPMRC_OK : RPMRC_FAIL;

@ -8,5 +8,5 @@ diff -up rpm-4.11.1-rc1/macros.in.siteconfig rpm-4.11.1-rc1/macros.in
+ CONFIG_SITE=${CONFIG_SITE:-NONE}\
+ export CONFIG_SITE\
\
%{verbose:set -x}\
%{verbose:set -x}%{!verbose:exec > /dev/null}\
umask 022\

@ -0,0 +1,95 @@
diff --git a/lib/tagexts.c b/lib/tagexts.c
index f72ff60..2c0b179 100644
--- a/lib/tagexts.c
+++ b/lib/tagexts.c
@@ -535,15 +535,6 @@ static int filerequireTag(Header h, rpmtd td, headerGetFlags hgflags)
return filedepTag(h, RPMTAG_REQUIRENAME, td, hgflags);
}
-/* I18N look aside diversions */
-
-#if defined(ENABLE_NLS)
-extern int _nl_msg_cat_cntr; /* XXX GNU gettext voodoo */
-#endif
-static const char * const language = "LANGUAGE";
-
-static const char * const _macro_i18ndomains = "%{?_i18ndomains}";
-
/**
* Retrieve i18n text.
* @param h header
@@ -554,59 +545,30 @@ static const char * const _macro_i18ndomains = "%{?_i18ndomains}";
*/
static int i18nTag(Header h, rpmTag tag, rpmtd td, headerGetFlags hgflags)
{
- int rc;
+ int rc = headerGet(h, tag, td, HEADERGET_ALLOC);
#if defined(ENABLE_NLS)
- char * dstring = rpmExpand(_macro_i18ndomains, NULL);
-
- td->type = RPM_STRING_TYPE;
- td->data = NULL;
- td->count = 0;
-
- if (dstring && *dstring) {
- char *domain, *de;
- const char * langval;
- char * msgkey;
- const char * msgid;
+ if (rc) {
+ static const char * const _macro_i18ndomains = "%{?_i18ndomains}";
+ char *de, *dstring = rpmExpand(_macro_i18ndomains, NULL);
+ const char *domain;
- rasprintf(&msgkey, "%s(%s)", headerGetString(h, RPMTAG_NAME),
- rpmTagGetName(tag));
-
- /* change to en_US for msgkey -> msgid resolution */
- langval = getenv(language);
- (void) setenv(language, "en_US", 1);
- ++_nl_msg_cat_cntr;
-
- msgid = NULL;
for (domain = dstring; domain != NULL; domain = de) {
+ const char *msgid = td->data;
+ const char *msg = NULL;
+
de = strchr(domain, ':');
if (de) *de++ = '\0';
- msgid = dgettext(domain, msgkey);
- if (msgid != msgkey) break;
- }
-
- /* restore previous environment for msgid -> msgstr resolution */
- if (langval)
- (void) setenv(language, langval, 1);
- else
- unsetenv(language);
- ++_nl_msg_cat_cntr;
-
- if (domain && msgid) {
- td->data = dgettext(domain, msgid);
- td->data = xstrdup(td->data); /* XXX xstrdup has side effects. */
- td->count = 1;
- td->flags = RPMTD_ALLOCED;
+ msg = dgettext(domain, td->data);
+ if (msg != msgid) {
+ free(td->data);
+ td->data = xstrdup(msg);
+ break;
+ }
}
- dstring = _free(dstring);
- free(msgkey);
- if (td->data)
- return 1;
+ free(dstring);
}
-
- free(dstring);
#endif
- rc = headerGet(h, tag, td, HEADERGET_ALLOC);
return rc;
}

@ -1,15 +1,16 @@
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)\
@@ -674,10 +674,11 @@ print (t)\
RPM_SOURCE_DIR=\"%{u2p:%{_sourcedir}}\"\
RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\
RPM_OPT_FLAGS=\"%{optflags}\"\
+ RPM_LD_FLAGS=\"%{?build_ldflags}\"\
+ RPM_LD_FLAGS=\"%{?__global_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\
+ export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_LD_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS\
RPM_DOC_DIR=\"%{_docdir}\"\
export RPM_DOC_DIR\
RPM_PACKAGE_NAME=\"%{NAME}\"\

@ -0,0 +1,28 @@
From bf636421120aa2c97f9e0fdcee3c211b4241bd86 Mon Sep 17 00:00:00 2001
From: Tomas Orsava <torsava@redhat.com>
Date: Mon, 29 Jan 2018 16:13:18 +0100
Subject: [PATCH] Add envvar that will be present during RPM build
Part of a Fedora Change for F28:
"Avoid /usr/bin/python in RPM build"
https://fedoraproject.org/wiki/Changes/Avoid_usr_bin_python_in_RPM_Build
---
macros.in | 2 ++
1 file changed, 2 insertions(+)
diff --git a/macros.in b/macros.in
index dd6ef67..68449e3 100644
--- a/macros.in
+++ b/macros.in
@@ -804,6 +804,8 @@ package or when debugging this package.\
export PKG_CONFIG_PATH\
CONFIG_SITE=${CONFIG_SITE:-NONE}\
export CONFIG_SITE\
+ PYTHON_DISALLOW_AMBIGUOUS_VERSION=warn\
+ export PYTHON_DISALLOW_AMBIGUOUS_VERSION\
\
%{verbose:set -x}%{!verbose:exec > /dev/null}\
umask 022\
--
2.13.6

@ -0,0 +1,107 @@
From 8390fa8515f499994646cf3bd113423744dc7bd9 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Fri, 30 Nov 2018 11:02:52 +0100
Subject: [PATCH] Add RPMTAG_MODULARITYLABEL to distinguish packages build for
modularity
Tag can be set with a ModularityLabel: statement in the spec file preamble or
via the modularitylabel macro
---
build/parsePreamble.c | 4 ++++
build/parseSpec.c | 1 +
lib/rpmtag.h | 1 +
macros.in | 5 +++++
tests/rpmgeneral.at | 1 +
5 files changed, 12 insertions(+)
diff --git a/build/parsePreamble.c b/build/parsePreamble.c
index f5e06bac8..e340e5c7a 100644
--- a/build/parsePreamble.c
+++ b/build/parsePreamble.c
@@ -43,6 +43,7 @@ static const rpmTagVal copyTagsDuringParse[] = {
RPMTAG_DISTTAG,
RPMTAG_BUGURL,
RPMTAG_GROUP,
+ RPMTAG_MODULARITYLABEL,
0
};
@@ -526,6 +527,7 @@ static struct optionalTag {
{ RPMTAG_DISTURL, "%{disturl}" },
{ RPMTAG_DISTTAG, "%{disttag}" },
{ RPMTAG_BUGURL, "%{bugurl}" },
+ { RPMTAG_MODULARITYLABEL, "%{modularitylabel}"},
{ -1, NULL }
};
@@ -779,6 +781,7 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
case RPMTAG_URL:
case RPMTAG_DISTTAG:
case RPMTAG_BUGURL:
+ case RPMTAG_MODULARITYLABEL:
/* XXX TODO: validate format somehow */
case RPMTAG_VCS:
SINGLE_TOKEN_ONLY;
@@ -1018,6 +1021,7 @@ static struct PreambleRec_s const preambleList[] = {
{RPMTAG_BUGURL, 0, 0, LEN_AND_STR("bugurl")},
{RPMTAG_ORDERNAME, 2, 0, LEN_AND_STR("orderwithrequires")},
{RPMTAG_REMOVEPATHPOSTFIXES,0, 0, LEN_AND_STR("removepathpostfixes")},
+ {RPMTAG_MODULARITYLABEL, 0, 0, LEN_AND_STR("modularitylabel")},
{0, 0, 0, 0}
};
diff --git a/build/parseSpec.c b/build/parseSpec.c
index bf4789942..c80802baf 100644
--- a/build/parseSpec.c
+++ b/build/parseSpec.c
@@ -517,6 +517,7 @@ static const rpmTagVal sourceTags[] = {
RPMTAG_BUGURL,
RPMTAG_HEADERI18NTABLE,
RPMTAG_VCS,
+ RPMTAG_MODULARITYLABEL,
0
};
diff --git a/lib/rpmtag.h b/lib/rpmtag.h
index 973a6b69d..b9623ef24 100644
--- a/lib/rpmtag.h
+++ b/lib/rpmtag.h
@@ -368,6 +368,7 @@
RPMTAG_FILESIGNATURELENGTH = 5091, /* i */
RPMTAG_PAYLOADDIGEST = 5092, /* s[] */
RPMTAG_PAYLOADDIGESTALGO = 5093, /* i */
+ RPMTAG_MODULARITYLABEL = 5096, /* s */
RPMTAG_FIRSTFREE_TAG /*!< internal */
} rpmTag;
diff --git a/macros.in b/macros.in
index e0a1aea4e..cb4929c10 100644
--- a/macros.in
+++ b/macros.in
@@ -357,6 +357,11 @@ package or when debugging this package.\
%_javadir %{_datadir}/java
%_javadocdir %{_datadir}/javadoc
+
+# Set ModularityLabel: for packages being build
+#
+#%modularitylabel
+
# A colon separated list of paths where files should *not* be installed.
# Usually, these are network file system mount points.
#
diff --git a/tests/rpmgeneral.at b/tests/rpmgeneral.at
index 509277f2c..45d38698b 100644
--- a/tests/rpmgeneral.at
+++ b/tests/rpmgeneral.at
@@ -150,6 +150,7 @@ LONGARCHIVESIZE
LONGFILESIZES
LONGSIGSIZE
LONGSIZE
+MODULARITYLABEL
N
NAME
NEVR
--
2.17.2

@ -0,0 +1,275 @@
From 820dcc1db9f2130a21fdaf721217034376eb8e38 Mon Sep 17 00:00:00 2001
Message-Id: <820dcc1db9f2130a21fdaf721217034376eb8e38.1544785848.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 30 Nov 2018 13:10:44 +0200
Subject: [PATCH] Add support for logging audit events for package installs as
per OSPP v4.2
If enabled at build-time, log audit events for package install, update
and remove. The log includes the operation, package nevra, signature
check result, whether signatures are being enforced enforced and overall
success result. Package install/update/remove are logged as such,
obsoletion is logged as install + remove (whereas the erasure element
on updates is silent)
Loosely based on initial RHEL 7-8 implementations by Pavlina Moravcova
Varekova and Florian Festi (RhBug:1555326, RhBug:1607612)
(cherry picked from commit cfc9dde70fe65e91c83e03e9a9441e627b741489)
---
configure.ac | 21 +++++++++
lib/Makefile.am | 1 +
lib/rpmte.c | 11 +++++
lib/rpmte_internal.h | 6 +++
lib/transaction.c | 104 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 143 insertions(+)
diff --git a/configure.ac b/configure.ac
index 34ea85f9f..ab8a368d3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -312,6 +312,27 @@ fi
AC_SUBST(WITH_BEECRYPT_LIB)
AC_SUBST(WITH_BEECRYPT_INCLUDE)
+
+#=================
+# Check for audit library.
+AC_ARG_WITH(audit,
+AS_HELP_STRING([--with-audit],[log results using Linux Audit]),
+with_audit=$withval,
+with_audit=auto)
+
+WITH_AUDIT_LIB=
+AS_IF([test "x$with_audit" != xno],[
+ AC_SEARCH_LIBS([audit_open],[audit],[
+ WITH_AUDIT_LIB="$ac_res"
+ AC_DEFINE(WITH_AUDIT, 1, [libaudit support])
+ ],
+ [if test "x$with_audit" != xauto; then
+ AC_MSG_ERROR([missing audit library])
+ fi
+ ])
+])
+AC_SUBST(WITH_AUDIT_LIB)
+
#=================
# Check for OpenSSL library.
# We need evp.h from OpenSSL.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index baf3238ee..c055962a3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -51,6 +51,7 @@ librpm_la_LIBADD = \
@WITH_POPT_LIB@ \
@WITH_CAP_LIB@ \
@WITH_ACL_LIB@ \
+ @WITH_AUDIT_LIB@ \
@LIBINTL@
if WITH_LUA
diff --git a/lib/rpmte.c b/lib/rpmte.c
index d980a37a4..bd5d53edc 100644
--- a/lib/rpmte.c
+++ b/lib/rpmte.c
@@ -69,6 +69,7 @@ struct rpmte_s {
int nrelocs; /*!< (TR_ADDED) No. of relocations. */
uint8_t *badrelocs; /*!< (TR_ADDED) Bad relocations (or NULL) */
FD_t fd; /*!< (TR_ADDED) Payload file descriptor. */
+ int verified; /*!< (TR_ADDED) Verification status */
#define RPMTE_HAVE_PRETRANS (1 << 0)
#define RPMTE_HAVE_POSTTRANS (1 << 1)
@@ -753,6 +754,16 @@ rpmfs rpmteGetFileStates(rpmte te)
return te->fs;
}
+void rpmteSetVerified(rpmte te, int verified)
+{
+ te->verified = verified;
+}
+
+int rpmteGetVerified(rpmte te)
+{
+ return te->verified;
+}
+
int rpmteProcess(rpmte te, pkgGoal goal, int num)
{
/* Only install/erase resets pkg file info */
diff --git a/lib/rpmte_internal.h b/lib/rpmte_internal.h
index a5a991ec5..2895925ce 100644
--- a/lib/rpmte_internal.h
+++ b/lib/rpmte_internal.h
@@ -86,6 +86,12 @@ int rpmteHaveTransScript(rpmte te, rpmTagVal tag);
/* XXX should be internal too but build code needs for now... */
rpmfs rpmteGetFileStates(rpmte te);
+RPM_GNUC_INTERNAL
+void rpmteSetVerified(rpmte te, int verified);
+
+RPM_GNUC_INTERNAL
+int rpmteGetVerified(rpmte te);
+
/** \ingroup rpmte
* Retrieve size in bytes of package header.
* @param te transaction element
diff --git a/lib/transaction.c b/lib/transaction.c
index 67b9db579..866e87fc2 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -7,6 +7,10 @@
#include <inttypes.h>
#include <libgen.h>
+#if WITH_AUDIT
+#include <libaudit.h>
+#endif
+
#include <rpm/rpmlib.h> /* rpmMachineScore, rpmReadPackageFile */
#include <rpm/rpmmacro.h> /* XXX for rpmExpand */
#include <rpm/rpmlog.h>
@@ -1195,12 +1199,17 @@ static rpm_loff_t countPkgs(rpmts ts, rpmElementTypes types)
struct vfydata_s {
char *msg;
+ int signature;
int vfylevel;
};
static int vfyCb(struct rpmsinfo_s *sinfo, void *cbdata)
{
struct vfydata_s *vd = cbdata;
+
+ if (sinfo->type == RPMSIG_SIGNATURE_TYPE && sinfo->rc == RPMRC_OK)
+ vd->signature = RPMRC_OK;
+
switch (sinfo->rc) {
case RPMRC_OK:
break;
@@ -1241,6 +1250,7 @@ static int verifyPackageFiles(rpmts ts, rpm_loff_t total)
struct rpmvs_s *vs = rpmvsCreate(vfylevel, vsflags, keyring);
struct vfydata_s vd = {
.msg = NULL,
+ .signature = RPMRC_NOTFOUND,
.vfylevel = vfylevel,
};
rpmRC prc = RPMRC_FAIL;
@@ -1255,6 +1265,9 @@ static int verifyPackageFiles(rpmts ts, rpm_loff_t total)
if (prc == RPMRC_OK)
prc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd);
+ /* Record verify result, signatures only for now */
+ rpmteSetVerified(p, vd.signature == RPMRC_OK);
+
if (prc)
rpmteAddProblem(p, RPMPROB_VERIFY, NULL, vd.msg, 0);
@@ -1619,6 +1632,95 @@ rpmRC runScript(rpmts ts, rpmte te, Header h, ARGV_const_t prefixes,
return rc;
}
+#if WITH_AUDIT
+struct teop {
+ rpmte te;
+ const char *op;
+};
+
+/*
+ * Figure out the actual operations:
+ * Install and remove are straightforward. Updates need to discovered
+ * via their erasure element: locate the updating element, adjust it's
+ * op to update and silence the erasure part. Obsoletion is handled as
+ * as install + remove, which it technically is.
+ */
+static void getAuditOps(rpmts ts, struct teop *ops, int nelem)
+{
+ rpmtsi pi = rpmtsiInit(ts);
+ rpmte p;
+ int i = 0;
+ while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ const char *op = NULL;
+ if (rpmteType(p) == TR_ADDED) {
+ op = "install";
+ } else {
+ op = "remove";
+ rpmte d = rpmteDependsOn(p);
+ /* Fixup op on updating elements, silence the cleanup stage */
+ if (d != NULL && rstreq(rpmteN(d), rpmteN(p))) {
+ /* Linear lookup, but we're only dealing with a few thousand */
+ for (int x = 0; x < i; x++) {
+ if (ops[x].te == d) {
+ ops[x].op = "update";
+ op = NULL;
+ break;
+ }
+ }
+ }
+ }
+ ops[i].te = p;
+ ops[i].op = op;
+ i++;
+ }
+ rpmtsiFree(pi);
+}
+
+/*
+ * If enabled, log audit events for the operations in this transaction.
+ * In the event values, 1 means true/success and 0 false/failure. Shockingly.
+ */
+static void rpmtsAudit(rpmts ts)
+{
+ int auditFd = audit_open();
+ if (auditFd < 0)
+ return;
+
+ int nelem = rpmtsNElements(ts);
+ struct teop *ops = xcalloc(nelem, sizeof(*ops));
+ char *dir = audit_encode_nv_string("root_dir", rpmtsRootDir(ts), 0);
+ int enforce = (rpmtsVfyLevel(ts) & RPMSIG_SIGNATURE_TYPE) != 0;
+
+ getAuditOps(ts, ops, nelem);
+
+ for (int i = 0; i < nelem; i++) {
+ const char *op = ops[i].op;
+ if (op) {
+ rpmte p = ops[i].te;
+ char *nevra = audit_encode_nv_string("sw", rpmteNEVRA(p), 0);
+ char eventTxt[256];
+ int verified = rpmteGetVerified(p);
+ int result = (rpmteFailed(p) == 0);
+
+ snprintf(eventTxt, sizeof(eventTxt),
+ "op=%s %s sw_type=rpm key_enforce=%u gpg_res=%u %s",
+ op, nevra, enforce, verified, dir);
+ audit_log_user_comm_message(auditFd, AUDIT_SOFTWARE_UPDATE,
+ eventTxt, NULL, NULL, NULL, NULL, result);
+ free(nevra);
+ }
+ }
+
+ free(dir);
+ free(ops);
+ audit_close(auditFd);
+}
+#else
+static void rpmtsAudit(rpmts ts)
+{
+}
+#endif
+
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
{
int rc = -1; /* assume failure */
@@ -1732,6 +1834,8 @@ exit:
rpmpluginsCallTsmPost(rpmtsPlugins(ts), ts, rc);
/* Finish up... */
+ if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS)))
+ rpmtsAudit(ts);
(void) umask(oldmask);
(void) rpmtsFinish(ts);
rpmpsFree(tsprobs);
--
2.19.2

@ -0,0 +1,12 @@
diff -up rpm-4.14.2/macros.in.pyerror rpm-4.14.2/macros.in
--- rpm-4.14.2/macros.in.pyerror 2019-06-04 13:33:48.450727270 +0300
+++ rpm-4.14.2/macros.in 2019-06-04 13:34:09.717695822 +0300
@@ -50,7 +50,7 @@
%__mv @__MV@
%__patch @__PATCH@
%__perl @__PERL@
-%__python @__PYTHON@
+%__python %{error:attempt to use unversioned python, define %%__python to %{_bindir}/python2 or %{_bindir}/python3 explicitly}
%__restorecon @__RESTORECON@
%__rm @__RM@
%__rsh @__RSH@

@ -0,0 +1,14 @@
diff -up rpm-4.14.3/scripts/brp-strip.orig rpm-4.14.3/scripts/brp-strip
--- rpm-4.14.3/scripts/brp-strip.orig 2021-02-09 14:43:35.393940550 +0100
+++ rpm-4.14.3/scripts/brp-strip 2021-02-09 14:43:49.459222054 +0100
@@ -12,9 +12,8 @@ Darwin*) exit 0 ;;
esac
# Strip ELF binaries
-for f in `find "$RPM_BUILD_ROOT" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \) -exec file {} \; | \
+for f in `find "$RPM_BUILD_ROOT" -type f -exec file {} \; | \
grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug" | \
- grep -v ' shared object,' | \
sed -n -e 's/^\(.*\):[ ]*ELF.*, not stripped.*/\1/p'`; do
$STRIP -g "$f" || :
done

@ -0,0 +1,186 @@
diff -up rpm-4.14.3/sign/rpmgensig.c.orig rpm-4.14.3/sign/rpmgensig.c
--- rpm-4.14.3/sign/rpmgensig.c.orig 2020-06-26 15:57:43.781333983 +0200
+++ rpm-4.14.3/sign/rpmgensig.c 2020-06-26 15:58:29.819229616 +0200
@@ -8,7 +8,6 @@
#include <errno.h>
#include <sys/wait.h>
#include <popt.h>
-#include <libgen.h>
#include <rpm/rpmlib.h> /* RPMSIGTAG & related */
#include <rpm/rpmmacro.h>
@@ -33,68 +32,6 @@ typedef struct sigTarget_s {
rpm_loff_t size;
} *sigTarget;
-/*
- * There is no function for creating unique temporary fifos so create
- * unique temporary directory and then create fifo in it.
- */
-static char *mkTempFifo(void)
-{
- char *tmppath = NULL, *tmpdir = NULL, *fifofn = NULL;
- mode_t mode;
-
- tmppath = rpmExpand("%{_tmppath}", NULL);
- if (rpmioMkpath(tmppath, 0755, (uid_t) -1, (gid_t) -1))
- goto exit;
-
-
- tmpdir = rpmGetPath(tmppath, "/rpm-tmp.XXXXXX", NULL);
- mode = umask(0077);
- tmpdir = mkdtemp(tmpdir);
- umask(mode);
- if (tmpdir == NULL) {
- rpmlog(RPMLOG_ERR, _("error creating temp directory %s: %m\n"),
- tmpdir);
- tmpdir = _free(tmpdir);
- goto exit;
- }
-
- fifofn = rpmGetPath(tmpdir, "/fifo", NULL);
- if (mkfifo(fifofn, 0600) == -1) {
- rpmlog(RPMLOG_ERR, _("error creating fifo %s: %m\n"), fifofn);
- fifofn = _free(fifofn);
- }
-
-exit:
- if (fifofn == NULL && tmpdir != NULL)
- unlink(tmpdir);
-
- free(tmppath);
- free(tmpdir);
-
- return fifofn;
-}
-
-/* Delete fifo and then temporary directory in which it was located */
-static int rpmRmTempFifo(const char *fn)
-{
- int rc = 0;
- char *dfn = NULL, *dir = NULL;
-
- if ((rc = unlink(fn)) != 0) {
- rpmlog(RPMLOG_ERR, _("error delete fifo %s: %m\n"), fn);
- return rc;
- }
-
- dfn = xstrdup(fn);
- dir = dirname(dfn);
-
- if ((rc = rmdir(dir)) != 0)
- rpmlog(RPMLOG_ERR, _("error delete directory %s: %m\n"), dir);
- free(dfn);
-
- return rc;
-}
-
static int closeFile(FD_t *fdp)
{
if (fdp == NULL || *fdp == NULL)
@@ -241,27 +178,38 @@ exit:
static int runGPG(sigTarget sigt, const char *sigfile)
{
int pid = 0, status;
- FD_t fnamedPipe = NULL;
- char *namedPipeName = NULL;
+ int pipefd[2];
+ FILE *fpipe = NULL;
unsigned char buf[BUFSIZ];
ssize_t count;
ssize_t wantCount;
rpm_loff_t size;
int rc = 1; /* assume failure */
- namedPipeName = mkTempFifo();
+ if (pipe(pipefd) < 0) {
+ rpmlog(RPMLOG_ERR, _("Could not create pipe for signing: %m\n"));
+ goto exit;
+ }
- rpmPushMacro(NULL, "__plaintext_filename", NULL, namedPipeName, -1);
+ rpmPushMacro(NULL, "__plaintext_filename", NULL, "-", -1);
rpmPushMacro(NULL, "__signature_filename", NULL, sigfile, -1);
if (!(pid = fork())) {
char *const *av;
char *cmd = NULL;
- const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
+ const char *tty = ttyname(STDIN_FILENO);
+ const char *gpg_path = NULL;
+
+ if (!getenv("GPG_TTY") && (!tty || setenv("GPG_TTY", tty, 0)))
+ rpmlog(RPMLOG_WARNING, _("Could not set GPG_TTY to stdin: %m\n"));
+ gpg_path = rpmExpand("%{?_gpg_path}", NULL);
if (gpg_path && *gpg_path != '\0')
(void) setenv("GNUPGHOME", gpg_path, 1);
+ dup2(pipefd[0], STDIN_FILENO);
+ close(pipefd[1]);
+
unsetenv("MALLOC_CHECK_");
cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
@@ -276,9 +224,10 @@ static int runGPG(sigTarget sigt, const
rpmPopMacro(NULL, "__plaintext_filename");
rpmPopMacro(NULL, "__signature_filename");
- fnamedPipe = Fopen(namedPipeName, "w");
- if (!fnamedPipe) {
- rpmlog(RPMLOG_ERR, _("Fopen failed\n"));
+ close(pipefd[0]);
+ fpipe = fdopen(pipefd[1], "w");
+ if (!fpipe) {
+ rpmlog(RPMLOG_ERR, _("Could not open pipe for writing: %m\n"));
goto exit;
}
@@ -291,8 +240,8 @@ static int runGPG(sigTarget sigt, const
size = sigt->size;
wantCount = size < sizeof(buf) ? size : sizeof(buf);
while ((count = Fread(buf, sizeof(buf[0]), wantCount, sigt->fd)) > 0) {
- Fwrite(buf, sizeof(buf[0]), count, fnamedPipe);
- if (Ferror(fnamedPipe)) {
+ fwrite(buf, sizeof(buf[0]), count, fpipe);
+ if (ferror(fpipe)) {
rpmlog(RPMLOG_ERR, _("Could not write to pipe\n"));
goto exit;
}
@@ -304,8 +253,13 @@ static int runGPG(sigTarget sigt, const
sigt->fileName, Fstrerror(sigt->fd));
goto exit;
}
- Fclose(fnamedPipe);
- fnamedPipe = NULL;
+
+exit:
+
+ if (fpipe)
+ fclose(fpipe);
+ if (pipefd[1])
+ close(pipefd[1]);
(void) waitpid(pid, &status, 0);
pid = 0;
@@ -314,20 +268,6 @@ static int runGPG(sigTarget sigt, const
} else {
rc = 0;
}
-
-exit:
-
- if (fnamedPipe)
- Fclose(fnamedPipe);
-
- if (pid)
- waitpid(pid, &status, 0);
-
- if (namedPipeName) {
- rpmRmTempFifo(namedPipeName);
- free(namedPipeName);
- }
-
return rc;
}

@ -1,46 +1,71 @@
commit 39595ccee321497dc3b08c7cab8a10304345429c
Author: Radovan Sroka <rsroka@redhat.com>
Date: Tue Oct 27 16:18:04 2020 +0100
From c33faabc2d09b9ad8c80b941b6114c1e4c2be80f Mon Sep 17 00:00:00 2001
Message-Id: <c33faabc2d09b9ad8c80b941b6114c1e4c2be80f.1612252390.git.pmatilai@redhat.com>
From: Radovan Sroka <rsroka@redhat.com>
Date: Tue, 27 Oct 2020 16:18:04 +0100
Subject: [PATCH] Added fapolicyd rpm plugin
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>
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]
Backported into 4.16.1.3, together with commit
6d61b7118adcc14631b7ee5163a481472af940b8 (covscan fix)
The fapolicyd rpm plugin can be enabled with "--with-fapolicyd"
configure option.
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])
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>
(cherry picked from commit 39595ccee321497dc3b08c7cab8a10304345429c)
Backported from commit 39595ccee321497dc3b08c7cab8a10304345429c
---
Makefile.am | 1 +
configure.ac | 8 ++
doc/Makefile.am | 2 +-
doc/rpm-plugin-fapolicyd.8 | 21 +++++
macros.in | 1 +
plugins/Makefile.am | 6 ++
plugins/fapolicyd.c | 189 +++++++++++++++++++++++++++++++++++++
7 files changed, 227 insertions(+), 1 deletion(-)
create mode 100644 doc/rpm-plugin-fapolicyd.8
create mode 100644 plugins/fapolicyd.c
diff --git a/Makefile.am b/Makefile.am
index 1f20f05b7..8e92f0cde 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,6 +16,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
--with-selinux \
--with-imaevm \
--with-crypto=openssl \
+ --with-fapolicyd \
--disable-dependency-tracking
include $(top_srcdir)/rpm.am
diff --git a/configure.ac b/configure.ac
index 3fcb3ff20..3d0e9ef91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -983,6 +983,14 @@ AS_IF([test "$enable_inhibit_plugin" = yes],[
])
AM_CONDITIONAL(ENABLE_INHIBIT_PLUGIN,[test "$enable_inhibit_plugin" = yes])
#=================
+#=================
+# Check for fapolicyd support
+AC_ARG_WITH(fapolicyd,
+AS_HELP_STRING([--with-fapolicyd],[build with File Access Policy Daemon support]),
@ -48,35 +73,27 @@ diff -up rpm-4.16.1.3/configure.ac.orig rpm-4.16.1.3/configure.ac
+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
+
with_dbus=no
AS_IF([test "$enable_plugins" != no],[
AS_IF([test "$enable_inhibit_plugin" != no],[
diff --git a/doc/Makefile.am b/doc/Makefile.am
index d2f520d64..535ad3ec3 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -9,7 +9,7 @@ EXTRA_DIST += $(man_man1_DATA)
man_man8dir = $(mandir)/man8
man_man8_DATA = rpm.8 rpm-misc.8 rpmbuild.8 rpmdeps.8 rpmgraph.8 rpm2cpio.8
man_man8_DATA += rpmdb.8 rpmkeys.8 rpmsign.8 rpmspec.8
-man_man8_DATA += rpm-plugin-systemd-inhibit.8
+man_man8_DATA += rpm-plugin-systemd-inhibit.8 rpm-plugin-fapolicyd.8
EXTRA_DIST += $(man_man8_DATA)
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
diff --git a/doc/rpm-plugin-fapolicyd.8 b/doc/rpm-plugin-fapolicyd.8
new file mode 100644
index 000000000..fe7a8c78e
--- /dev/null
+++ b/doc/rpm-plugin-fapolicyd.8
@@ -0,0 +1,21 @@
+'\" t
+.TH "RPM-FAPOLICYD" "8" "28 Jan 2021" "Red Hat, Inc."
@ -99,32 +116,38 @@ diff -up rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig rpm-4.16.1.3/doc/rpm-plugi
+.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.\
diff --git a/macros.in b/macros.in
index a6069ee4d..2fbda64cc 100644
--- a/macros.in
+++ b/macros.in
@@ -1173,6 +1173,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 @@
#------------------------------------------------------------------------------
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index ab4eee34f..cbfb81e19 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -42,3 +42,9 @@ ima_la_sources = ima.c
ima_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
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
diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
new file mode 100644
index 000000000..50f50155c
--- /dev/null
+++ b/plugins/fapolicyd.c
@@ -0,0 +1,189 @@
+#include "system.h"
+
+#include <rpm/rpmts.h>
@ -185,7 +208,7 @@ diff -up rpm-4.16.1.3/plugins/fapolicyd.c.orig rpm-4.16.1.3/plugins/fapolicyd.c
+ return RPMRC_OK;
+
+ bad:
+ if (fd >= 0)
+ if (fd > 0)
+ close(fd);
+ return RPMRC_FAIL;
+}
@ -303,8 +326,6 @@ diff -up rpm-4.16.1.3/plugins/fapolicyd.c.orig rpm-4.16.1.3/plugins/fapolicyd.c
+ snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
+ (void) write_fifo(&fapolicyd_state, buffer);
+
+ free(sha);
+
+ end:
+ return RPMRC_OK;
+}
@ -316,19 +337,42 @@ diff -up rpm-4.16.1.3/plugins/fapolicyd.c.orig rpm-4.16.1.3/plugins/fapolicyd.c
+ .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
--
2.29.2
commit c66cee32e74ce1e507c031605e3d7b2c1391a52c
Author: Radovan Sroka <rsroka@redhat.com>
Date: Wed Feb 10 17:04:55 2021 +0100
Fixed issues find by coverity
- enhance the check for the file descriptor fd because 0 is also a valid
descriptor
- added free() for sha so it doesn't leak memory for every file that is
processed
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
index 50f50155c..48f65ae11 100644
--- a/plugins/fapolicyd.c
+++ b/plugins/fapolicyd.c
@@ -58,7 +58,7 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
return RPMRC_OK;
+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
bad:
- if (fd > 0)
+ if (fd >= 0)
close(fd);
return RPMRC_FAIL;
}
@@ -176,6 +176,8 @@ static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
(void) write_fifo(&fapolicyd_state, buffer);
+ free(sha);
+
if AUDIT
audit_la_sources = audit.c
audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@
end:
return RPMRC_OK;
}

@ -1,4 +1,4 @@
From ba659220886c1a315f50fb91b9af4615b1a8757e Mon Sep 17 00:00:00 2001
From 013cd4ba63c35fa75feeccde0022d56e68bc5845 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
@ -18,7 +18,7 @@ Combined with:
d1aebda01033bc8ba0d748b49f6fad9a5c0caa3f
f62b6d27cd741406a52a7e9c5b1d6f581dbd3af8
Backported for 4.16.1.3.
Backported for 4.14.3.
---
doc/rpm.8 | 9 ++++++--
lib/poptQV.c | 6 +++++-
@ -28,7 +28,7 @@ Backported for 4.16.1.3.
5 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/doc/rpm.8 b/doc/rpm.8
index 80055b675..ab7364cf6 100644
index 15a3db25f..74604c8ec 100644
--- a/doc/rpm.8
+++ b/doc/rpm.8
@@ -57,7 +57,7 @@ rpm \- RPM Package Manager
@ -37,10 +37,10 @@ index 80055b675..ab7364cf6 100644
[\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-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".
@@ -555,7 +555,7 @@ starts with "b".
List duplicated packages.
.TP
\fB-f, --file \fIFILE\fB\fR
@ -49,7 +49,7 @@ index 80055b675..ab7364cf6 100644
.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
@@ -598,6 +598,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
@ -62,7 +62,7 @@ index 80055b675..ab7364cf6 100644
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
index 9021d7b3c..f752d8b82 100644
--- a/lib/poptQV.c
+++ b/lib/poptQV.c
@@ -27,6 +27,7 @@ struct rpmQVKArguments_s rpmQVKArgs;
@ -93,10 +93,10 @@ index d9d1fad75..9b6101009 100644
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
index 26cdecf10..e6ea1fa2d 100644
--- a/lib/query.c
+++ b/lib/query.c
@@ -445,6 +445,7 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
@@ -440,6 +440,7 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
}
/* fallthrough on absolute and relative paths */
case RPMQV_PATH:
@ -104,7 +104,7 @@ index fdabe6e52..9a71f0dc5 100644
{ char * fn;
for (s = arg; *s != '\0'; s++)
@@ -463,8 +464,10 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
@@ -458,8 +459,10 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
fn = xstrdup(arg);
(void) rpmCleanPath(fn);
@ -118,10 +118,10 @@ index fdabe6e52..9a71f0dc5 100644
mi = rpmtsInitIterator(ts, RPMDBI_PROVIDENAME, fn, 0);
diff --git a/lib/rpmcli.h b/lib/rpmcli.h
index 4886c2453..3961418e7 100644
index 99af2585a..c0d07d137 100644
--- a/lib/rpmcli.h
+++ b/lib/rpmcli.h
@@ -101,6 +101,7 @@ enum rpmQVSources_e {
@@ -102,6 +102,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. */
@ -130,10 +130,10 @@ index 4886c2453..3961418e7 100644
typedef rpmFlags rpmQVSources;
diff --git a/tests/rpmquery.at b/tests/rpmquery.at
index 9a4f1cb76..335d5ee0d 100644
index 36c62339a..ad580f664 100644
--- a/tests/rpmquery.at
+++ b/tests/rpmquery.at
@@ -201,6 +201,58 @@ runroot rpm \
@@ -194,6 +194,58 @@ runroot rpm \
AT_CLEANUP

@ -0,0 +1,798 @@
From 34790c335fe6e5e1099c9320d7b3134398104120 Mon Sep 17 00:00:00 2001
Message-Id: <34790c335fe6e5e1099c9320d7b3134398104120.1624429665.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 23 Jun 2021 08:24:44 +0300
Subject: [PATCH] Add read-only support for sqlite
Based on latest upstream sqlite backend version, chainsaw write support
out and adjust for the infra differences (which there are more than a
few) and add an error message instead.
---
configure.ac | 23 ++
lib/Makefile.am | 6 +
lib/backend/dbi.c | 14 +
lib/backend/dbi.h | 5 +
lib/backend/sqlite.c | 659 +++++++++++++++++++++++++++++++++++++++++++
macros.in | 1 +
6 files changed, 708 insertions(+)
create mode 100644 lib/backend/sqlite.c
diff --git a/configure.ac b/configure.ac
index 3fcb3ff20..e04aced68 100644
--- a/configure.ac
+++ b/configure.ac
@@ -589,6 +589,29 @@ AS_IF([test "$enable_ndb" = yes],[
])
AM_CONDITIONAL([NDB], [test "$enable_ndb" = yes])
+# Check for SQLITE support
+AC_ARG_ENABLE([sqlite],
+ [AS_HELP_STRING([--enable-sqlite=@<:@yes/no/auto@:>@)],
+ [build with sqlite rpm database format support (default=yes)])],
+ [enable_sqlite="$enableval"],
+ [enable_sqlite=yes])
+
+AS_IF([test "x$enable_sqlite" != "xno"], [
+ PKG_CHECK_MODULES([SQLITE], [sqlite3 >= 3.22.0], [have_sqlite=yes], [have_sqlite=no])
+ AS_IF([test "$enable_sqlite" = "yes"], [
+ if test "$have_sqlite" = "no"; then
+ AC_MSG_ERROR([--enable-sqlite specified, but not available])
+ fi
+ ])
+])
+
+if test "x$have_sqlite" = "xyes"; then
+ AC_DEFINE([WITH_SQLITE], [1], [Define if SQLITE is available])
+ SQLITE_REQUIRES=sqlite
+ AC_SUBST(SQLITE_REQUIRES)
+fi
+AM_CONDITIONAL([SQLITE], [test "x$have_sqlite" = "xyes"])
+
#=================
# Check for LMDB support
AC_ARG_ENABLE([lmdb],
diff --git a/lib/Makefile.am b/lib/Makefile.am
index baf3238ee..8a9fe77bd 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -76,6 +76,12 @@ librpm_la_SOURCES += \
backend/ndb/rpmxdb.h
endif
+if SQLITE
+AM_CPPFLAGS += $(SQLITE_CFLAGS)
+librpm_la_LIBADD += $(SQLITE_LIBS)
+librpm_la_SOURCES += backend/sqlite.c
+endif
+
if LMDB
AM_CPPFLAGS += $(LMDB_CFLAGS)
librpm_la_LIBADD += $(LMDB_LIBS)
diff --git a/lib/backend/dbi.c b/lib/backend/dbi.c
index e99a5f2b2..dc3587f58 100644
--- a/lib/backend/dbi.c
+++ b/lib/backend/dbi.c
@@ -48,6 +48,11 @@ dbDetectBackend(rpmdb rdb)
if (!strcmp(db_backend, "ndb")) {
rdb->db_ops = &ndb_dbops;
} else
+#endif
+#ifdef WITH_SQLITE
+ if (!strcmp(db_backend, "sqlite")) {
+ rdb->db_ops = &sqlite_dbops;
+ } else
#endif
{
rdb->db_ops = &db3_dbops;
@@ -75,6 +80,15 @@ dbDetectBackend(rpmdb rdb)
free(path);
#endif
+#ifdef WITH_SQLITE
+ path = rstrscat(NULL, dbhome, "/rpmdb.sqlite", NULL);
+ if (access(path, F_OK) == 0 && rdb->db_ops != &sqlite_dbops) {
+ rdb->db_ops = &sqlite_dbops;
+ rpmlog(RPMLOG_WARNING, _("Found SQLITE rpmdb.sqlite database while attempting %s backend: using sqlite backend.\n"), db_backend);
+ }
+ free(path);
+#endif
+
path = rstrscat(NULL, dbhome, "/Packages", NULL);
if (access(path, F_OK) == 0 && rdb->db_ops != &db3_dbops) {
rdb->db_ops = &db3_dbops;
diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h
index 02f49c8fd..ff2b4f974 100644
--- a/lib/backend/dbi.h
+++ b/lib/backend/dbi.h
@@ -275,6 +275,11 @@ RPM_GNUC_INTERNAL
extern struct rpmdbOps_s lmdb_dbops;
#endif
+#if defined(WITH_SQLITE)
+RPM_GNUC_INTERNAL
+extern struct rpmdbOps_s sqlite_dbops;
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c
new file mode 100644
index 000000000..3caeba5f0
--- /dev/null
+++ b/lib/backend/sqlite.c
@@ -0,0 +1,659 @@
+#include "system.h"
+
+#include <sqlite3.h>
+#include <fcntl.h>
+
+#include <rpm/rpmlog.h>
+#include <rpm/rpmfileutil.h>
+#include <rpm/rpmmacro.h>
+#include "lib/rpmdb_internal.h"
+
+#include "debug.h"
+
+static const int sleep_ms = 50;
+
+struct dbiCursor_s {
+ sqlite3 *sdb;
+ sqlite3_stmt *stmt;
+ const char *fmt;
+ int flags;
+ rpmTagVal tag;
+ int ctype;
+ struct dbiCursor_s *subc;
+
+ const void *key;
+ unsigned int keylen;
+};
+
+static int sqlexec(sqlite3 *sdb, const char *fmt, ...);
+
+static void rpm_match3(sqlite3_context *sctx, int argc, sqlite3_value **argv)
+{
+ int match = 0;
+ if (argc == 3) {
+ int b1len = sqlite3_value_bytes(argv[0]);
+ int b2len = sqlite3_value_bytes(argv[1]);
+ int n = sqlite3_value_int(argv[2]);
+ if (b1len >= n && b2len >= n) {
+ const char *b1 = sqlite3_value_blob(argv[0]);
+ const char *b2 = sqlite3_value_blob(argv[1]);
+ match = (memcmp(b1, b2, n) == 0);
+ }
+ }
+ sqlite3_result_int(sctx, match);
+}
+
+static void errCb(void *data, int err, const char *msg)
+{
+ rpmdb rdb = data;
+ rpmlog(RPMLOG_WARNING, "%s: %s: %s\n",
+ rdb->db_descr, sqlite3_errstr(err), msg);
+}
+
+static int dbiCursorReset(dbiCursor dbc)
+{
+ if (dbc->stmt) {
+ sqlite3_reset(dbc->stmt);
+ sqlite3_clear_bindings(dbc->stmt);
+ }
+ return 0;
+}
+
+static int dbiCursorResult(dbiCursor dbc)
+{
+ int rc = sqlite3_errcode(dbc->sdb);
+ int err = (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW);
+ if (err) {
+ rpmlog(RPMLOG_ERR, "%s: %d: %s\n", sqlite3_sql(dbc->stmt),
+ sqlite3_errcode(dbc->sdb), sqlite3_errmsg(dbc->sdb));
+ }
+ return err ? RPMRC_FAIL : RPMRC_OK;
+}
+
+static int dbiCursorPrep(dbiCursor dbc, const char *fmt, ...)
+{
+ if (dbc->stmt == NULL) {
+ char *cmd = NULL;
+ va_list ap;
+
+ va_start(ap, fmt);
+ cmd = sqlite3_vmprintf(fmt, ap);
+ va_end(ap);
+
+ sqlite3_prepare_v2(dbc->sdb, cmd, -1, &dbc->stmt, NULL);
+ sqlite3_free(cmd);
+ } else {
+ dbiCursorReset(dbc);
+ }
+
+ return dbiCursorResult(dbc);
+}
+
+static int dbiCursorBindPkg(dbiCursor dbc, unsigned int hnum,
+ void *blob, unsigned int bloblen)
+{
+ int rc = 0;
+
+ if (hnum)
+ rc = sqlite3_bind_int(dbc->stmt, 1, hnum);
+ else
+ rc = sqlite3_bind_null(dbc->stmt, 1);
+
+ if (blob) {
+ if (!rc)
+ rc = sqlite3_bind_blob(dbc->stmt, 2, blob, bloblen, NULL);
+ }
+ return dbiCursorResult(dbc);
+}
+
+static int dbiCursorBindIdx(dbiCursor dbc, const void *key, int keylen,
+ dbiIndexItem rec)
+{
+ int rc;
+ if (dbc->ctype == SQLITE_TEXT) {
+ rc = sqlite3_bind_text(dbc->stmt, 1, key, keylen, NULL);
+ } else {
+ rc = sqlite3_bind_blob(dbc->stmt, 1, key, keylen, NULL);
+ }
+
+ if (rec) {
+ if (!rc)
+ rc = sqlite3_bind_int(dbc->stmt, 2, rec->hdrNum);
+ if (!rc)
+ rc = sqlite3_bind_int(dbc->stmt, 3, rec->tagNum);
+ }
+
+ return dbiCursorResult(dbc);
+}
+
+static int sqlite_init(rpmdb rdb, const char * dbhome)
+{
+ int rc = 0;
+ char *dbfile = NULL;
+
+ if (rdb->db_dbenv == NULL) {
+ dbfile = rpmGenPath(dbhome, "rpmdb.sqlite", NULL);
+ sqlite3 *sdb = NULL;
+ int xx, flags = 0;
+ int retry_open = 1;
+
+ free(rdb->db_descr);
+ rdb->db_descr = xstrdup("sqlite");
+
+ if ((rdb->db_mode & O_ACCMODE) == O_RDONLY)
+ flags |= SQLITE_OPEN_READONLY;
+ else {
+ rpmlog(RPMLOG_ERR,
+ _("unable to open sqlite database %s for writing, sqlite support is read-only\n"), dbfile);
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+
+ while (retry_open--) {
+ xx = sqlite3_open_v2(dbfile, &sdb, flags, NULL);
+ /* Attempt to create if missing, discarding OPEN_READONLY (!) */
+ if (xx == SQLITE_CANTOPEN && (flags & SQLITE_OPEN_READONLY)) {
+ /* Sqlite allocates resources even on failure to open (!) */
+ sqlite3_close(sdb);
+ flags &= ~SQLITE_OPEN_READONLY;
+ flags |= (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+ retry_open++;
+ }
+ }
+
+ if (xx != SQLITE_OK) {
+ rpmlog(RPMLOG_ERR, _("Unable to open sqlite database %s: %s\n"),
+ dbfile, sqlite3_errstr(xx));
+ rc = 1;
+ goto exit;
+ }
+
+ sqlite3_create_function(sdb, "match", 3,
+ (SQLITE_UTF8|SQLITE_DETERMINISTIC),
+ NULL, rpm_match3, NULL, NULL);
+
+ sqlite3_busy_timeout(sdb, sleep_ms);
+ sqlite3_config(SQLITE_CONFIG_LOG, errCb, rdb);
+
+ sqlexec(sdb, "PRAGMA secure_delete = OFF");
+ sqlexec(sdb, "PRAGMA case_sensitive_like = ON");
+
+ if (sqlite3_db_readonly(sdb, NULL) == 0) {
+ if (sqlexec(sdb, "PRAGMA journal_mode = WAL") == 0) {
+ int one = 1;
+ /* Annoying but necessary to support non-privileged readers */
+ sqlite3_file_control(sdb, NULL, SQLITE_FCNTL_PERSIST_WAL, &one);
+
+ if (!rpmExpandNumeric("%{?_flush_io}"))
+ sqlexec(sdb, "PRAGMA wal_autocheckpoint = 0");
+ }
+ }
+
+ rdb->db_dbenv = sdb;
+ }
+ rdb->db_opens++;
+
+exit:
+ free(dbfile);
+ return rc;
+}
+
+static int sqlite_fini(rpmdb rdb)
+{
+ int rc = 0;
+ if (rdb) {
+ sqlite3 *sdb = rdb->db_dbenv;
+ if (rdb->db_opens > 1) {
+ rdb->db_opens--;
+ } else {
+ if (sqlite3_db_readonly(sdb, NULL) == 0) {
+ sqlexec(sdb, "PRAGMA optimize");
+ sqlexec(sdb, "PRAGMA wal_checkpoint = TRUNCATE");
+ }
+ rdb->db_dbenv = NULL;
+ int xx = sqlite3_close(sdb);
+ rc = (xx != SQLITE_OK);
+ }
+ }
+
+ return rc;
+}
+
+static int sqlexec(sqlite3 *sdb, const char *fmt, ...)
+{
+ int rc = 0;
+ char *cmd = NULL;
+ char *err = NULL;
+ va_list ap;
+
+ va_start(ap, fmt);
+ cmd = sqlite3_vmprintf(fmt, ap);
+ va_end(ap);
+
+ /* sqlite3_exec() doesn't seeem to honor sqlite3_busy_timeout() */
+ while ((rc = sqlite3_exec(sdb, cmd, NULL, NULL, &err)) == SQLITE_BUSY) {
+ usleep(sleep_ms);
+ }
+
+ if (rc)
+ rpmlog(RPMLOG_ERR, "sqlite failure: %s: %s\n", cmd, err);
+ else
+ rpmlog(RPMLOG_DEBUG, "%s: %d\n", cmd, rc);
+
+ sqlite3_free(cmd);
+
+ return rc ? RPMRC_FAIL : RPMRC_OK;
+}
+
+static int dbiExists(dbiIndex dbi)
+{
+ const char *col = (dbi->dbi_type == DBI_PRIMARY) ? "hnum" : "key";
+ const char *tbl = dbi->dbi_file;
+ int rc = sqlite3_table_column_metadata(dbi->dbi_db, NULL, tbl, col,
+ NULL, NULL, NULL, NULL, NULL);
+ return (rc == 0);
+}
+
+static int init_table(dbiIndex dbi, rpmTagVal tag)
+{
+ int rc = 0;
+
+ if (dbiExists(dbi))
+ return 0;
+
+ if (dbi->dbi_type == DBI_PRIMARY) {
+ rc = sqlexec(dbi->dbi_db,
+ "CREATE TABLE IF NOT EXISTS '%q' ("
+ "hnum INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "blob BLOB NOT NULL"
+ ")",
+ dbi->dbi_file);
+ } else {
+ const char *keytype = (rpmTagGetClass(tag) == RPM_STRING_CLASS) ?
+ "TEXT" : "BLOB";
+ rc = sqlexec(dbi->dbi_db,
+ "CREATE TABLE IF NOT EXISTS '%q' ("
+ "key '%q' NOT NULL, "
+ "hnum INTEGER NOT NULL, "
+ "idx INTEGER NOT NULL, "
+ "FOREIGN KEY (hnum) REFERENCES 'Packages'(hnum)"
+ ")",
+ dbi->dbi_file, keytype);
+ }
+ if (!rc)
+ dbi->dbi_flags |= DBI_CREATED;
+
+ return rc;
+}
+
+static int create_index(sqlite3 *sdb, const char *table, const char *col)
+{
+ return sqlexec(sdb,
+ "CREATE INDEX IF NOT EXISTS '%s_%s_idx' ON '%q'(%s ASC)",
+ table, col, table, col);
+}
+
+static int init_index(dbiIndex dbi, rpmTagVal tag)
+{
+ int rc = 0;
+
+ /* Can't create on readonly database, but things will still work */
+ if (sqlite3_db_readonly(dbi->dbi_db, NULL) == 1)
+ return 0;
+
+ if (dbi->dbi_type == DBI_SECONDARY) {
+ int string = (rpmTagGetClass(tag) == RPM_STRING_CLASS);
+ int array = (rpmTagGetReturnType(tag) == RPM_ARRAY_RETURN_TYPE);
+ if (!rc && string)
+ rc = create_index(dbi->dbi_db, dbi->dbi_file, "key");
+ if (!rc && array)
+ rc = create_index(dbi->dbi_db, dbi->dbi_file, "hnum");
+ }
+ return rc;
+}
+
+static int sqlite_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
+{
+ int rc = sqlite_init(rdb, rpmdbHome(rdb));
+
+ if (!rc) {
+ dbiIndex dbi = dbiNew(rdb, rpmtag);
+ dbi->dbi_db = rdb->db_dbenv;
+
+ rc = init_table(dbi, rpmtag);
+
+ if (!rc && !(rdb->db_flags & RPMDB_FLAG_REBUILD))
+ rc = init_index(dbi, rpmtag);
+
+ if (!rc && dbip)
+ *dbip = dbi;
+ else
+ dbiFree(dbi);
+ }
+
+ return rc;
+}
+
+static int sqlite_Close(dbiIndex dbi, unsigned int flags)
+{
+ rpmdb rdb = dbi->dbi_rpmdb;
+ int rc = 0;
+ if (rdb->db_flags & RPMDB_FLAG_REBUILD)
+ rc = init_index(dbi, rpmTagGetValue(dbi->dbi_file));
+ sqlite_fini(dbi->dbi_rpmdb);
+ dbiFree(dbi);
+ return rc;
+}
+
+static int sqlite_Verify(dbiIndex dbi, unsigned int flags)
+{
+ int errors = -1;
+ int key_errors = -1;
+ sqlite3_stmt *s = NULL;
+ const char *cmd = "PRAGMA integrity_check";
+
+ if (dbi->dbi_type == DBI_SECONDARY)
+ return RPMRC_OK;
+
+ if (sqlite3_prepare_v2(dbi->dbi_db, cmd, -1, &s, NULL) == SQLITE_OK) {
+ errors = 0;
+ while (sqlite3_step(s) == SQLITE_ROW) {
+ const char *txt = (const char *)sqlite3_column_text(s, 0);
+ if (!rstreq(txt, "ok")) {
+ errors++;
+ rpmlog(RPMLOG_ERR, "verify: %s\n", txt);
+ }
+ }
+ sqlite3_finalize(s);
+ } else {
+ rpmlog(RPMLOG_ERR, "%s: %s\n", cmd, sqlite3_errmsg(dbi->dbi_db));
+ }
+
+ /* No point checking higher-level errors if low-level errors exist */
+ if (errors)
+ goto exit;
+
+ cmd = "PRAGMA foreign_key_check";
+ if (sqlite3_prepare_v2(dbi->dbi_db, cmd, -1, &s, NULL) == SQLITE_OK) {
+ key_errors = 0;
+ while (sqlite3_step(s) == SQLITE_ROW) {
+ key_errors++;
+ rpmlog(RPMLOG_ERR, "verify key: %s[%lld]\n",
+ sqlite3_column_text(s, 0),
+ sqlite3_column_int64(s, 1));
+ }
+ sqlite3_finalize(s);
+ } else {
+ rpmlog(RPMLOG_ERR, "%s: %s\n", cmd, sqlite3_errmsg(dbi->dbi_db));
+ }
+
+exit:
+
+ return (errors == 0 && key_errors == 0) ? RPMRC_OK : RPMRC_FAIL;
+}
+
+static void sqlite_SetFSync(rpmdb rdb, int enable)
+{
+ if (rdb->db_dbenv) {
+ sqlexec(rdb->db_dbenv,
+ "PRAGMA synchronous = %s", enable ? "FULL" : "OFF");
+ }
+}
+
+static int sqlite_Ctrl(rpmdb rdb, dbCtrlOp ctrl)
+{
+ int rc = 0;
+
+ switch (ctrl) {
+ case DB_CTRL_LOCK_RW:
+ rc = sqlexec(rdb->db_dbenv, "SAVEPOINT 'rwlock'");
+ break;
+ case DB_CTRL_UNLOCK_RW:
+ rc = sqlexec(rdb->db_dbenv, "RELEASE 'rwlock'");
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+static dbiCursor sqlite_CursorInit(dbiIndex dbi, unsigned int flags)
+{
+ dbiCursor dbc = xcalloc(1, sizeof(*dbc));
+ dbc->sdb = dbi->dbi_db;
+ dbc->flags = flags;
+ dbc->tag = rpmTagGetValue(dbi->dbi_file);
+ if (rpmTagGetClass(dbc->tag) == RPM_STRING_CLASS) {
+ dbc->ctype = SQLITE_TEXT;
+ } else {
+ dbc->ctype = SQLITE_BLOB;
+ }
+ if (dbc->flags & DBC_WRITE)
+ sqlexec(dbc->sdb, "SAVEPOINT '%s'", dbi->dbi_file);
+ return dbc;
+}
+
+static dbiCursor sqlite_CursorFree(dbiIndex dbi, dbiCursor dbc)
+{
+ if (dbc) {
+ sqlite3_finalize(dbc->stmt);
+ if (dbc->subc)
+ dbiCursorFree(dbi, dbc->subc);
+ if (dbc->flags & DBC_WRITE)
+ sqlexec(dbc->sdb, "RELEASE '%s'", dbi->dbi_file);
+ free(dbc);
+ }
+ return NULL;
+}
+
+static rpmRC sqlite_pkgdbNew(dbiIndex dbi, dbiCursor dbc, unsigned int *hdrNum)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_pkgdbPut(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char *hdrBlob, unsigned int hdrLen)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_pkgdbDel(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_stepPkg(dbiCursor dbc, unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc = sqlite3_step(dbc->stmt);
+
+ if (rc == SQLITE_ROW) {
+ if (hdrLen)
+ *hdrLen = sqlite3_column_bytes(dbc->stmt, 1);
+ if (hdrBlob)
+ *hdrBlob = (void *) sqlite3_column_blob(dbc->stmt, 1);
+ }
+ return rc;
+}
+
+static rpmRC sqlite_pkgdbByKey(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc = dbiCursorPrep(dbc, "SELECT hnum, blob FROM '%q' WHERE hnum=?",
+ dbi->dbi_file);
+
+ if (!rc)
+ rc = dbiCursorBindPkg(dbc, hdrNum, NULL, 0);
+
+ if (!rc)
+ rc = sqlite_stepPkg(dbc, hdrBlob, hdrLen);
+
+ return dbiCursorResult(dbc);
+}
+
+static rpmRC sqlite_pkgdbIter(dbiIndex dbi, dbiCursor dbc,
+ unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc = RPMRC_OK;
+ if (dbc->stmt == NULL) {
+ rc = dbiCursorPrep(dbc, "SELECT hnum, blob FROM '%q'", dbi->dbi_file);
+ }
+
+ if (!rc)
+ rc = sqlite_stepPkg(dbc, hdrBlob, hdrLen);
+
+ if (rc == SQLITE_DONE) {
+ rc = RPMRC_NOTFOUND;
+ } else {
+ rc = dbiCursorResult(dbc);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_pkgdbGet(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc;
+
+ if (hdrNum) {
+ rc = sqlite_pkgdbByKey(dbi, dbc, hdrNum, hdrBlob, hdrLen);
+ } else {
+ rc = sqlite_pkgdbIter(dbi, dbc, hdrBlob, hdrLen);
+ }
+
+ return rc;
+}
+
+static unsigned int sqlite_pkgdbKey(dbiIndex dbi, dbiCursor dbc)
+{
+ return sqlite3_column_int(dbc->stmt, 0);
+}
+
+static rpmRC sqlite_idxdbByKey(dbiIndex dbi, dbiCursor dbc,
+ const char *keyp, size_t keylen, int searchType,
+ dbiIndexSet *set)
+{
+ int rc = RPMRC_NOTFOUND;
+
+ if (searchType == DBC_PREFIX_SEARCH) {
+ rc = dbiCursorPrep(dbc, "SELECT hnum, idx FROM '%q' "
+ "WHERE MATCH(key,'%q',%d) "
+ "ORDER BY key",
+ dbi->dbi_file, keyp, keylen);
+ } else {
+ rc = dbiCursorPrep(dbc, "SELECT hnum, idx FROM '%q' WHERE key=?",
+ dbi->dbi_file);
+ if (!rc)
+ rc = dbiCursorBindIdx(dbc, keyp, keylen, NULL);
+ }
+
+
+ if (!rc) {
+ while ((rc = sqlite3_step(dbc->stmt)) == SQLITE_ROW) {
+ unsigned int hnum = sqlite3_column_int(dbc->stmt, 0);
+ unsigned int tnum = sqlite3_column_int(dbc->stmt, 1);
+
+ if (*set == NULL)
+ *set = dbiIndexSetNew(5);
+ dbiIndexSetAppendOne(*set, hnum, tnum, 0);
+ }
+ }
+
+ if (rc == SQLITE_DONE) {
+ rc = (*set) ? RPMRC_OK : RPMRC_NOTFOUND;
+ } else {
+ rc = dbiCursorResult(dbc);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_idxdbIter(dbiIndex dbi, dbiCursor dbc, dbiIndexSet *set)
+{
+ int rc = RPMRC_OK;
+
+ if (dbc->stmt == NULL) {
+ rc = dbiCursorPrep(dbc, "SELECT DISTINCT key FROM '%q' ORDER BY key",
+ dbi->dbi_file);
+ if (set)
+ dbc->subc = dbiCursorInit(dbi, 0);
+ }
+
+ if (!rc)
+ rc = sqlite3_step(dbc->stmt);
+
+ if (rc == SQLITE_ROW) {
+ if (dbc->ctype == SQLITE_TEXT) {
+ dbc->key = sqlite3_column_text(dbc->stmt, 0);
+ } else {
+ dbc->key = sqlite3_column_blob(dbc->stmt, 0);
+ }
+ dbc->keylen = sqlite3_column_bytes(dbc->stmt, 0);
+ if (dbc->subc) {
+ rc = sqlite_idxdbByKey(dbi, dbc->subc, dbc->key, dbc->keylen,
+ DBC_NORMAL_SEARCH, set);
+ } else {
+ rc = RPMRC_OK;
+ }
+ } else if (rc == SQLITE_DONE) {
+ rc = RPMRC_NOTFOUND;
+ } else {
+ rc = dbiCursorResult(dbc);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexSet *set, int searchType)
+{
+ int rc;
+ if (keyp) {
+ rc = sqlite_idxdbByKey(dbi, dbc, keyp, keylen, searchType, set);
+ } else {
+ rc = sqlite_idxdbIter(dbi, dbc, set);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_idxdbPut(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexItem rec)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_idxdbDel(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexItem rec)
+{
+ return RPMRC_FAIL;
+}
+
+static const void * sqlite_idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen)
+{
+ const void *key = NULL;
+ if (dbc) {
+ key = dbc->key;
+ if (key && keylen)
+ *keylen = dbc->keylen;
+ }
+ return key;
+}
+
+struct rpmdbOps_s sqlite_dbops = {
+ .open = sqlite_Open,
+ .close = sqlite_Close,
+ .verify = sqlite_Verify,
+ .setFSync = sqlite_SetFSync,
+ .ctrl = sqlite_Ctrl,
+
+ .cursorInit = sqlite_CursorInit,
+ .cursorFree = sqlite_CursorFree,
+
+ .pkgdbPut = sqlite_pkgdbPut,
+ .pkgdbDel = sqlite_pkgdbDel,
+ .pkgdbGet = sqlite_pkgdbGet,
+ .pkgdbKey = sqlite_pkgdbKey,
+ .pkgdbNew = sqlite_pkgdbNew,
+
+ .idxdbGet = sqlite_idxdbGet,
+ .idxdbPut = sqlite_idxdbPut,
+ .idxdbDel = sqlite_idxdbDel,
+ .idxdbKey = sqlite_idxdbKey
+};
+
diff --git a/macros.in b/macros.in
index a6069ee4d..9ad3d60ef 100644
--- a/macros.in
+++ b/macros.in
@@ -620,6 +620,7 @@ package or when debugging this package.\
# bdb Berkeley DB
# lmdb Lightning Memory-mapped Database
# ndb new data base format
+# sqlite Sqlite database (read-only in this version!)
#
%_db_backend bdb
--
2.31.1

@ -0,0 +1,12 @@
diff -up rpm-4.14.3/lib/header.c.orig rpm-4.14.3/lib/header.c
--- rpm-4.14.3/lib/header.c.orig 2020-04-28 14:50:11.816399041 +0200
+++ rpm-4.14.3/lib/header.c 2021-02-03 16:47:23.567245743 +0100
@@ -1910,7 +1910,7 @@ rpmRC hdrblobRead(FD_t fd, int magic, in
if (regionTag == RPMTAG_HEADERSIGNATURES) {
il_max = 32;
- dl_max = 8192;
+ dl_max = 64 * 1024 * 1024;
}
memset(block, 0, sizeof(block));

@ -0,0 +1,101 @@
diff -up rpm-4.14.3/lib/rpmscript.c.orig rpm-4.14.3/lib/rpmscript.c
--- rpm-4.14.3/lib/rpmscript.c.orig 2021-02-08 14:07:44.527197946 +0100
+++ rpm-4.14.3/lib/rpmscript.c 2021-02-08 14:09:05.732749080 +0100
@@ -46,27 +46,27 @@ struct scriptInfo_s {
};
static const struct scriptInfo_s scriptInfo[] = {
- { RPMSCRIPT_PREIN, "%prein", 0,
+ { RPMSCRIPT_PREIN, "prein", 0,
RPMTAG_PREIN, RPMTAG_PREINPROG, RPMTAG_PREINFLAGS },
- { RPMSCRIPT_PREUN, "%preun", 0,
+ { RPMSCRIPT_PREUN, "preun", 0,
RPMTAG_PREUN, RPMTAG_PREUNPROG, RPMTAG_PREUNFLAGS },
- { RPMSCRIPT_POSTIN, "%post", 0,
+ { RPMSCRIPT_POSTIN, "post", 0,
RPMTAG_POSTIN, RPMTAG_POSTINPROG, RPMTAG_POSTINFLAGS },
- { RPMSCRIPT_POSTUN, "%postun", 0,
+ { RPMSCRIPT_POSTUN, "postun", 0,
RPMTAG_POSTUN, RPMTAG_POSTUNPROG, RPMTAG_POSTUNFLAGS },
- { RPMSCRIPT_PRETRANS, "%pretrans", 0,
+ { RPMSCRIPT_PRETRANS, "pretrans", 0,
RPMTAG_PRETRANS, RPMTAG_PRETRANSPROG, RPMTAG_PRETRANSFLAGS },
- { RPMSCRIPT_POSTTRANS, "%posttrans", 0,
+ { RPMSCRIPT_POSTTRANS, "posttrans", 0,
RPMTAG_POSTTRANS, RPMTAG_POSTTRANSPROG, RPMTAG_POSTTRANSFLAGS },
- { RPMSCRIPT_TRIGGERPREIN, "%triggerprein", RPMSENSE_TRIGGERPREIN,
+ { RPMSCRIPT_TRIGGERPREIN, "triggerprein", RPMSENSE_TRIGGERPREIN,
RPMTAG_TRIGGERPREIN, 0, 0 },
- { RPMSCRIPT_TRIGGERUN, "%triggerun", RPMSENSE_TRIGGERUN,
+ { RPMSCRIPT_TRIGGERUN, "triggerun", RPMSENSE_TRIGGERUN,
RPMTAG_TRIGGERUN, 0, 0 },
- { RPMSCRIPT_TRIGGERIN, "%triggerin", RPMSENSE_TRIGGERIN,
+ { RPMSCRIPT_TRIGGERIN, "triggerin", RPMSENSE_TRIGGERIN,
RPMTAG_TRIGGERIN, 0, 0 },
- { RPMSCRIPT_TRIGGERPOSTUN, "%triggerpostun", RPMSENSE_TRIGGERPOSTUN,
+ { RPMSCRIPT_TRIGGERPOSTUN, "triggerpostun", RPMSENSE_TRIGGERPOSTUN,
RPMTAG_TRIGGERPOSTUN, 0, 0 },
- { RPMSCRIPT_VERIFY, "%verify", 0,
+ { RPMSCRIPT_VERIFY, "verify", 0,
RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, RPMTAG_VERIFYSCRIPTFLAGS},
{ 0, "unknown", 0,
RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND }
@@ -457,7 +457,7 @@ static const char * tag2sln(rpmTagVal ta
}
static rpmScript rpmScriptNew(Header h, rpmTagVal tag, const char *body,
- rpmscriptFlags flags)
+ rpmscriptFlags flags, const char *prefix)
{
char *nevra = headerGetAsString(h, RPMTAG_NEVRA);
rpmScript script = xcalloc(1, sizeof(*script));
@@ -465,7 +465,7 @@ static rpmScript rpmScriptNew(Header h,
script->type = getScriptType(tag);
script->flags = flags;
script->body = (body != NULL) ? xstrdup(body) : NULL;
- rasprintf(&script->descr, "%s(%s)", tag2sln(tag), nevra);
+ rasprintf(&script->descr, "%%%s%s(%s)", prefix, tag2sln(tag), nevra);
/* macros need to be expanded before possible queryformat */
if (script->body && (script->flags & RPMSCRIPT_FLAG_EXPAND)) {
@@ -556,6 +556,7 @@ rpmScript rpmScriptFromTriggerTag(Header
rpmScript script = NULL;
struct rpmtd_s tscripts, tprogs, tflags;
headerGetFlags hgflags = HEADERGET_MINMEM;
+ const char *prefix = "";
switch (tm) {
case RPMSCRIPT_NORMALTRIGGER:
@@ -567,11 +568,13 @@ rpmScript rpmScriptFromTriggerTag(Header
headerGet(h, RPMTAG_FILETRIGGERSCRIPTS, &tscripts, hgflags);
headerGet(h, RPMTAG_FILETRIGGERSCRIPTPROG, &tprogs, hgflags);
headerGet(h, RPMTAG_FILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
+ prefix = "file";
break;
case RPMSCRIPT_TRANSFILETRIGGER:
headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTS, &tscripts, hgflags);
headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTPROG, &tprogs, hgflags);
headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
+ prefix = "transfile";
break;
}
@@ -582,7 +585,8 @@ rpmScript rpmScriptFromTriggerTag(Header
if (rpmtdSetIndex(&tflags, ix) >= 0)
sflags = rpmtdGetNumber(&tflags);
- script = rpmScriptNew(h, triggerTag, rpmtdGetString(&tscripts), sflags);
+ script = rpmScriptNew(h, triggerTag,
+ rpmtdGetString(&tscripts), sflags, prefix);
/* hack up a hge-style NULL-terminated array */
script->args = xmalloc(2 * sizeof(*script->args) + strlen(prog) + 1);
@@ -608,7 +612,7 @@ rpmScript rpmScriptFromTag(Header h, rpm
script = rpmScriptNew(h, scriptTag,
headerGetString(h, scriptTag),
- headerGetNumber(h, getFlagTag(scriptTag)));
+ headerGetNumber(h, getFlagTag(scriptTag)), "");
if (headerGet(h, progTag, &prog, (HEADERGET_ALLOC|HEADERGET_ARGV))) {
script->args = prog.data;

@ -1,7 +1,7 @@
From 8c37dff4ce9c887eda5ad61f78001e87473002ed Mon Sep 17 00:00:00 2001
From f17aa638649fb8de730fecdbc906dc869b626ba5 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
Subject: [PATCH 1/2] Fix spurious %transfiletriggerpostun execution
(RhBug:2023311)
If a package has multiple %transfiletriggerpostun triggers, any one
@ -15,30 +15,26 @@ 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(-)
lib/rpmtriggers.c | 64 +++++++++++++++++++++++------------------------
1 file changed, 31 insertions(+), 33 deletions(-)
diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c
index fc809a65e..8d8f57450 100644
index 0827af0c2..dc457f7cc 100644
--- a/lib/rpmtriggers.c
+++ b/lib/rpmtriggers.c
@@ -97,19 +97,39 @@ static void rpmtriggersSortAndUniq(rpmtriggers trigs)
@@ -97,19 +97,37 @@ static void rpmtriggersSortAndUniq(rpmtriggers trigs)
}
}
+static void addTriggers(rpmts ts, Header trigH, rpmsenseFlags filter,
+ const char *prefix)
+static void addTriggers(rpmts ts, Header trigH, rpmsenseFlags filter)
+{
+ 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) {
+ if ((rpmdsNext(ds) >= 0) && (rpmdsFlags(ds) & filter)) {
+ struct rpmtd_s priorities;
+
+ if (headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES,
@ -70,22 +66,22 @@ index fc809a65e..8d8f57450 100644
files = rpmteFiles(te);
/* Iterate over file triggers in rpmdb */
@@ -121,39 +141,20 @@ void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
@@ -121,39 +139,19 @@ 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));
- break;
+ unsigned int npkg = rpmdbIndexIteratorNumPkgs(ii);
+ const unsigned int *offs = rpmdbIndexIteratorPkgOffsets(ii);
+ /* Save any postun triggers matching this prefix */
+ /* Save any matching postun triggers */
+ for (int i = 0; i < npkg; i++) {
+ Header h = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offs[i]);
+ addTriggers(ts, h, RPMSENSE_TRIGGERPOSTUN, pfx);
+ addTriggers(ts, h, RPMSENSE_TRIGGERPOSTUN);
+ headerFree(h);
+ }
break;
}
}
rpmfiFree(fi);
@ -121,3 +117,68 @@ index fc809a65e..8d8f57450 100644
--
2.35.1
From e617e7c550d3523998707c55f96b37ede2c48c78 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 2 Feb 2022 13:46:23 +0200
Subject: [PATCH 2/2] Really fix spurious %transfiletriggerpostun execution
(RhBug:2023311)
Commit b3d672a5523dfec033160e5cc866432a0e808649 got the base reasoning
in the ballpark but the code all wrong, introducing a severe performance
regression without actually fixing what it claimed to.
The missing incredient is actually comparing the current prefix with the
triggers in matched package (trying to describe this makes my head
spin): a package may have multiple triggers on multiple prefixes and
we need to make sure we only execute triggers of this type, from this
prefix.
This stuff really needs more and better testcases.
Fixes: b3d672a5523dfec033160e5cc866432a0e808649
---
lib/rpmtriggers.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c
index dc457f7cc..c652981be 100644
--- a/lib/rpmtriggers.c
+++ b/lib/rpmtriggers.c
@@ -97,14 +97,16 @@ static void rpmtriggersSortAndUniq(rpmtriggers trigs)
}
}
-static void addTriggers(rpmts ts, Header trigH, rpmsenseFlags filter)
+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)) {
+ if ((rpmdsNext(ds) >= 0) && (rpmdsFlags(ds) & filter) &&
+ strcmp(prefix, rpmdsN(ds)) == 0) {
struct rpmtd_s priorities;
if (headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES,
@@ -141,12 +143,13 @@ void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) {
unsigned int npkg = rpmdbIndexIteratorNumPkgs(ii);
const unsigned int *offs = rpmdbIndexIteratorPkgOffsets(ii);
- /* Save any matching postun triggers */
+ /* 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);
+ addTriggers(ts, h, RPMSENSE_TRIGGERPOSTUN, pfx);
headerFree(h);
}
+ break;
}
}
rpmfiFree(fi);
--
2.35.1

@ -0,0 +1,100 @@
commit 8f4b3c3cab8922a2022b9e47c71f1ecf906077ef
Author: Demi Marie Obenour <athena@invisiblethingslab.com>
Date: Mon Feb 8 16:05:01 2021 -0500
hdrblobInit() needs bounds checks too
Users can pass untrusted data to hdrblobInit() and it must be robust
against this.
diff --git a/lib/header.c b/lib/header.c
index ea39e679f..ebba9c2b0 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -11,6 +11,7 @@
#include "system.h"
#include <netdb.h>
#include <errno.h>
+#include <inttypes.h>
#include <rpm/rpmtypes.h>
#include <rpm/rpmstring.h>
#include "lib/header_internal.h"
@@ -1912,6 +1913,25 @@ hdrblob hdrblobFree(hdrblob blob)
return NULL;
}
+static rpmRC hdrblobVerifyLengths(rpmTagVal regionTag, uint32_t il, uint32_t dl,
+ char **emsg) {
+ uint32_t il_max = HEADER_TAGS_MAX;
+ uint32_t dl_max = HEADER_DATA_MAX;
+ if (regionTag == RPMTAG_HEADERSIGNATURES) {
+ il_max = 32;
+ dl_max = 64 * 1024 * 1024;
+ }
+ if (hdrchkRange(il_max, il)) {
+ rasprintf(emsg, _("hdr tags: BAD, no. of tags(%" PRIu32 ") out of range"), il);
+ return RPMRC_FAIL;
+ }
+ if (hdrchkRange(dl_max, dl)) {
+ rasprintf(emsg, _("hdr data: BAD, no. of bytes(%" PRIu32 ") out of range"), dl);
+ return RPMRC_FAIL;
+ }
+ return RPMRC_OK;
+}
+
rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrblob blob, char **emsg)
{
int32_t block[4];
@@ -1924,13 +1944,6 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
size_t nb;
rpmRC rc = RPMRC_FAIL; /* assume failure */
int xx;
- int32_t il_max = HEADER_TAGS_MAX;
- int32_t dl_max = HEADER_DATA_MAX;
-
- if (regionTag == RPMTAG_HEADERSIGNATURES) {
- il_max = 32;
- dl_max = 64 * 1024 * 1024;
- }
memset(block, 0, sizeof(block));
if ((xx = Freadall(fd, bs, blen)) != blen) {
@@ -1943,15 +1956,9 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
goto exit;
}
il = ntohl(block[2]);
- if (hdrchkRange(il_max, il)) {
- rasprintf(emsg, _("hdr tags: BAD, no. of tags(%d) out of range"), il);
- goto exit;
- }
dl = ntohl(block[3]);
- if (hdrchkRange(dl_max, dl)) {
- rasprintf(emsg, _("hdr data: BAD, no. of bytes(%d) out of range"), dl);
+ if (hdrblobVerifyLengths(regionTag, il, dl, emsg))
goto exit;
- }
nb = (il * sizeof(struct entryInfo_s)) + dl;
uc = sizeof(il) + sizeof(dl) + nb;
@@ -1995,11 +2002,18 @@ rpmRC hdrblobInit(const void *uh, size_t uc,
struct hdrblob_s *blob, char **emsg)
{
rpmRC rc = RPMRC_FAIL;
-
memset(blob, 0, sizeof(*blob));
+ if (uc && uc < 8) {
+ rasprintf(emsg, _("hdr length: BAD"));
+ goto exit;
+ }
+
blob->ei = (int32_t *) uh; /* discards const */
- blob->il = ntohl(blob->ei[0]);
- blob->dl = ntohl(blob->ei[1]);
+ blob->il = ntohl((uint32_t)(blob->ei[0]));
+ blob->dl = ntohl((uint32_t)(blob->ei[1]));
+ if (hdrblobVerifyLengths(regionTag, blob->il, blob->dl, emsg) != RPMRC_OK)
+ goto exit;
+
blob->pe = (entryInfo) &(blob->ei[2]);
blob->pvlen = sizeof(blob->il) + sizeof(blob->dl) +
(blob->il * sizeof(*blob->pe)) + blob->dl;

@ -12,8 +12,6 @@ Date: Mon Jun 21 10:05:10 2021 +0200
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
@ -284,3 +282,46 @@ index 09c5a6454..0f29b6371 100644
--
2.31.1
commit 9747a6af016a3458d54fe060777c95e3900b5fa4
Author: Demi Marie Obenour <athena@invisiblethingslab.com>
Date: Tue Mar 2 12:47:29 2021 -0500
Fix a tiny memory leak
Found by fuzzing rpmReadPackageFile() with libfuzzer under ASAN.
diff --git a/lib/headerutil.c b/lib/headerutil.c
index 22e36c74d..fab210ff2 100644
--- a/lib/headerutil.c
+++ b/lib/headerutil.c
@@ -333,8 +333,10 @@ static void providePackageNVR(Header h)
rpmds hds, nvrds;
/* Generate provides for this package name-version-release. */
- if (!(name && pEVR))
+ if (!(name && pEVR)) {
+ free(pEVR);
return;
+ }
/*
* Rpm prior to 3.0.3 does not have versioned provides.
commit cb2ae4bdf2f60876fdc68e3f84938e9c37182fab
Author: Igor Gnatenko <i.gnatenko.brain@gmail.com>
Date: Tue Feb 6 14:50:27 2018 +0100
lua: fix memory leak in Pexec()
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
diff --git a/luaext/lposix.c b/luaext/lposix.c
index 5d7ad3c87..2730bcff7 100644
--- a/luaext/lposix.c
+++ b/luaext/lposix.c
@@ -348,6 +348,7 @@ static int Pexec(lua_State *L) /** exec(path,[args]) */
for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
argv[i] = NULL;
execvp(path,argv);
+ free(argv);
return pusherror(L, path);
}

@ -0,0 +1,38 @@
From 77007d68782b66f2d00d7b200516731246876dca 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.
Backported for 4.14.3.
---
macros.in | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/macros.in b/macros.in
index a6069ee4d..be28a3b28 100644
--- a/macros.in
+++ b/macros.in
@@ -82,6 +82,8 @@
%__remsh %{__rsh}
%__strip @__STRIP@
+%__find_debuginfo %{_rpmconfigdir}/find-debuginfo.sh
+
# XXX avoid failures if tools are not installed when rpm is built.
%__libtoolize libtoolize
%__aclocal aclocal
@@ -177,7 +179,7 @@
# the script. See the script for details.
#
%__debug_install_post \
- %{_rpmconfigdir}/find-debuginfo.sh \\\
+ %{__find_debuginfo} \\\
%{?_smp_mflags} \\\
%{?_missing_build_ids_terminate_build:--strict-build-id} \\\
%{?_no_recompute_build_ids:-n} \\\
--
2.33.1

@ -0,0 +1,162 @@
commit d6a86b5e69e46cc283b1e06c92343319beb42e21
Author: Panu Matilainen <pmatilai@redhat.com>
Date: Thu Mar 4 13:21:19 2021 +0200
Be much more careful about copying data from the signature header
Only look for known tags, and ensure correct type and size where known
before copying over. Bump the old arbitrary 16k count limit to 16M limit
though, it's not inconceivable that a package could have that many files.
While at it, ensure none of these tags exist in the main header,
which would confuse us greatly.
This is optimized for backporting ease, upstream can remove redundancies
and further improve checking later.
Reported and initial patches by Demi Marie Obenour.
Fixes: RhBug:1935049, RhBug:1933867, RhBug:1935035, RhBug:1934125, ...
Fixes: CVE-2021-3421, CVE-2021-20271
Combined with e2f1f1931c5ccf3ecbe4e1e12cacb1e17a277776 and backported into
4.14.3
diff -up rpm-4.14.3/lib/package.c.orig rpm-4.14.3/lib/package.c
--- rpm-4.14.3/lib/package.c.orig 2021-05-31 12:32:49.970393976 +0200
+++ rpm-4.14.3/lib/package.c 2021-05-31 13:53:58.250673275 +0200
@@ -31,76 +31,72 @@ struct pkgdata_s {
rpmRC rc;
};
+struct taglate_s {
+ rpmTagVal stag;
+ rpmTagVal xtag;
+ rpm_count_t count;
+ int quirk;
+} const xlateTags[] = {
+ { 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_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 }
+};
+
/** \ingroup header
* Translate and merge legacy signature tags into header.
* @param h header (dest)
* @param sigh signature header (src)
+ * @return failing tag number, 0 on success
*/
static
-void headerMergeLegacySigs(Header h, Header sigh)
+rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg)
{
- HeaderIterator hi;
+ const struct taglate_s *xl;
struct rpmtd_s td;
- hi = headerInitIterator(sigh);
- for (; headerNext(hi, &td); rpmtdFreeData(&td))
- {
- switch (td.tag) {
- /* XXX Translate legacy signature tag values. */
- case RPMSIGTAG_SIZE:
- td.tag = RPMTAG_SIGSIZE;
- break;
- case RPMSIGTAG_PGP:
- td.tag = RPMTAG_SIGPGP;
- break;
- case RPMSIGTAG_MD5:
- td.tag = RPMTAG_SIGMD5;
- break;
- case RPMSIGTAG_GPG:
- td.tag = RPMTAG_SIGGPG;
- break;
- case RPMSIGTAG_PGP5:
- td.tag = RPMTAG_SIGPGP5;
- break;
- case RPMSIGTAG_PAYLOADSIZE:
- td.tag = RPMTAG_ARCHIVESIZE;
- break;
- case RPMSIGTAG_SHA1:
- case RPMSIGTAG_SHA256:
- case RPMSIGTAG_DSA:
- case RPMSIGTAG_RSA:
- default:
- if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
+ rpmtdReset(&td);
+ for (xl = xlateTags; xl->stag; xl++) {
+ /* There mustn't be one in the main header */
+ if (headerIsEntry(h, xl->xtag)) {
+ /* Some tags may exist in either header, but never both */
+ if (xl->quirk && !headerIsEntry(sigh, xl->stag))
continue;
break;
}
- if (!headerIsEntry(h, td.tag)) {
- switch (td.type) {
- case RPM_NULL_TYPE:
- continue;
+ if (headerGet(sigh, xl->stag, &td, HEADERGET_RAW|HEADERGET_MINMEM)) {
+ /* Translate legacy tags */
+ if (xl->stag != xl->xtag)
+ td.tag = xl->xtag;
+ /* Ensure type and tag size match expectations */
+ if (td.type != rpmTagGetTagType(td.tag))
break;
- case RPM_CHAR_TYPE:
- case RPM_INT8_TYPE:
- case RPM_INT16_TYPE:
- case RPM_INT32_TYPE:
- case RPM_INT64_TYPE:
- if (td.count != 1)
- continue;
+ if (td.count < 1 || td.count > 16*1024*1024)
break;
- case RPM_STRING_TYPE:
- case RPM_BIN_TYPE:
- if (td.count >= 16*1024)
- continue;
+ if (xl->count && td.count != xl->count)
break;
- case RPM_STRING_ARRAY_TYPE:
- case RPM_I18NSTRING_TYPE:
- continue;
+ if (!headerPut(h, &td, HEADERPUT_DEFAULT))
break;
- }
- (void) headerPut(h, &td, HEADERPUT_DEFAULT);
+ rpmtdFreeData(&td);
}
}
- headerFreeIterator(hi);
+ rpmtdFreeData(&td);
+
+ if (xl->stag) {
+ rasprintf(msg, "invalid signature tag %s (%d)",
+ rpmTagGetName(xl->xtag), xl->xtag);
+ }
+
+ return xl->stag;
}
/**
@@ -363,7 +359,8 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t
goto exit;
/* Append (and remap) signature tags to the metadata. */
- headerMergeLegacySigs(h, sigh);
+ if (headerMergeLegacySigs(h, sigh, &msg))
+ goto exit;
applyRetrofits(h);
/* Bump reference count for return. */

@ -0,0 +1,13 @@
--- rpm-4.14.3/configure.ac.orig 2020-05-04 21:08:41.481365399 +0200
+++ rpm-4.14.3/configure.ac 2020-05-04 21:09:03.550604043 +0200
@@ -129,8 +129,8 @@
AC_PATH_PROG(__PERL, perl, /usr/bin/perl, $MYPATH)
AC_PATH_PROG(__PGP, pgp, /usr/bin/pgp, $MYPATH)
-AC_PATH_PROG(__PYTHON, python2, /usr/bin/python2, $MYPATH)
-AC_PATH_PROG(PYTHON, python2, /usr/bin/python2, $MYPATH)
+AC_PATH_PROG(__PYTHON, python3, /usr/bin/python3, $MYPATH)
+AC_PATH_PROG(PYTHON, python3, /usr/bin/python3, $MYPATH)
AC_PATH_PROG(__RM, rm, /bin/rm, $MYPATH)
AC_PATH_PROG(__RSH, rsh, /usr/bin/rsh, $MYPATH)
AC_PATH_PROG(__SED, sed, /bin/sed, $MYPATH)

@ -13,41 +13,6 @@ Resolves: #1530
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

@ -1,4 +1,4 @@
From 6cdcdd8770d1f0b9ba706dcc1e6392a59dbe3fe5 Mon Sep 17 00:00:00 2001
From 2e61e5846f8301f85da9d30281538ea736d96fd0 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)
@ -24,7 +24,7 @@ eventual C implementation.
1 file changed, 1 insertion(+)
diff --git a/rpmpopt.in b/rpmpopt.in
index 27d298651..d5a6b140b 100644
index 67fcabfb1..e130a5d05 100644
--- a/rpmpopt.in
+++ b/rpmpopt.in
@@ -44,6 +44,7 @@ rpm alias --scripts --qf '\
@ -36,5 +36,5 @@ index 27d298651..d5a6b140b 100644
chmod %7{FILEMODES:octal} %{FILENAMES:shescape}\n]' \
--pipe "grep -v \(none\) | grep '^. -L ' | sed 's/chmod .../chmod /' | sh" \
--
2.34.1
2.35.1

@ -1,4 +1,4 @@
From 32b21da4bae5b8fbe0f42c31b723c4963b4b2512 Mon Sep 17 00:00:00 2001
From 82c53e4b7f720012a391d8f6e5da9ee3c4f22bed 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
@ -36,10 +36,10 @@ Fixes CVE-2021-3521.
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
index 46cd0f31a..bd4992ec7 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -515,7 +515,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
@@ -511,7 +511,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
return NULL;
}
@ -48,7 +48,7 @@ index d0688ebe9..3372d577d 100644
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,
@@ -524,10 +524,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
int mpil = pgpMpiLen(p);
if (p + mpil > pend)
break;
@ -61,7 +61,7 @@ index d0688ebe9..3372d577d 100644
p += mpil;
}
@@ -604,7 +602,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
@@ -600,7 +598,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
}
p = ((uint8_t *)v) + sizeof(*v);
@ -70,7 +70,7 @@ index d0688ebe9..3372d577d 100644
} break;
case 4:
{ pgpPktSigV4 v = (pgpPktSigV4)h;
@@ -662,7 +660,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
@@ -658,7 +656,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
if (p > (h + hlen))
return 1;
@ -79,7 +79,7 @@ index d0688ebe9..3372d577d 100644
} 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)
@@ -999,36 +997,127 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype)
return algo;
}
@ -215,7 +215,7 @@ index d0688ebe9..3372d577d 100644
if (ret && rc == 0) {
*ret = digp;
} else {
@@ -1105,8 +1194,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
@@ -1063,8 +1152,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
digps = xrealloc(digps, alloced * sizeof(*digps));
}
@ -226,10 +226,10 @@ index d0688ebe9..3372d577d 100644
digps[count]->userid = xstrdup(mainkey->userid);
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index e5d191cc0..988a0f611 100644
index 771d01098..b33fe996c 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -351,7 +351,7 @@ static int haveSignature(rpmtd sigtd, Header h)
@@ -409,7 +409,7 @@ static int haveSignature(rpmtd sigtd, Header h)
pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2);
if (pgpDigParamsCmp(sig1, sig2) == 0)
rc = 1;
@ -239,10 +239,10 @@ index e5d191cc0..988a0f611 100644
pgpDigParamsFree(sig1);
rpmtdFreeData(&oldtd);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f742a9e1d..328234278 100644
index 5f5207e56..309347262 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -107,6 +107,9 @@ EXTRA_DIST += data/SPECS/hello-config-buildid.spec
@@ -87,6 +87,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
@ -250,8 +250,8 @@ index f742a9e1d..328234278 100644
+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
# testsuite voodoo
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
@ -358,10 +358,10 @@ index 000000000..3a2e7417f
+-----END PGP PUBLIC KEY BLOCK-----
+
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
index e1a3ab062..705fc5870 100644
index 09fcdd525..a74f400ae 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -240,6 +240,34 @@ gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918
@@ -212,6 +212,34 @@ UNW2iqnN3BA7guhOv6OMiROF1+I7Q5nWT63mQC7IgQ==
[])
AT_CLEANUP

@ -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,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,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,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,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,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,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,12 @@
diff -up rpm-4.8.1/macros.in.gpg2 rpm-4.8.1/macros.in
--- rpm-4.8.0/macros.in.gpg2 2011-01-17 12:17:38.000000000 +0200
+++ rpm-4.8.0/macros.in 2011-01-17 12:17:59.000000000 +0200
@@ -40,7 +40,7 @@
%__cp @__CP@
%__cpio @__CPIO@
%__file @__FILE@
-%__gpg @__GPG@
+%__gpg /usr/bin/gpg2
%__grep @__GREP@
%__gzip @__GZIP@
%__id @__ID@

@ -1,19 +0,0 @@
[Unit]
Description=RPM database rebuild
ConditionPathExists=/var/lib/rpm/.rebuilddb
# 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/bin/rpmdb --rebuilddb
ExecStartPost=rm -f /var/lib/rpm/.rebuilddb
[Install]
WantedBy=basic.target

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