import rpm-4.14.2-26.el8_1

This commit is contained in:
CentOS Sources 2020-04-07 05:15:25 -04:00 committed by Andrew Lukoshko
commit 76fa559b8f
45 changed files with 5008 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/rpm-4.14.2.tar.bz2

1
.rpm.metadata Normal file
View File

@ -0,0 +1 @@
1ca664af796ab8d05ea3fccabe2b2e4767a97c74 SOURCES/rpm-4.14.2.tar.bz2

View File

@ -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
}
@@ -409,8 +426,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 ;;
esac
$skip_mini || add_minidebug "${debugfn}" "$f"

View File

@ -0,0 +1,38 @@
From ce11f04ed529cd84de8981b82c1185c0a30dfdcf Mon Sep 17 00:00:00 2001
From: Pavlina Moravcova Varekova <pmoravco@redhat.com>
Date: Thu, 14 Mar 2019 13:23:13 +0100
Subject: [PATCH] Correct rpm -ql exit value when optional -p is omitted
(RhBug:1680610)
---
lib/query.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/query.c b/lib/query.c
index e47189ed0..e5408e211 100644
--- a/lib/query.c
+++ b/lib/query.c
@@ -568,16 +568,18 @@ int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_const_t argv)
break;
default:
for (ARGV_const_t arg = argv; arg && *arg; arg++) {
+ int ecLocal;
rpmdbMatchIterator mi = initQueryIterator(qva, ts, *arg);
- ec += rpmcliShowMatches(qva, ts, mi);
+ ecLocal = rpmcliShowMatches(qva, ts, mi);
if (mi == NULL && qva->qva_source == RPMQV_PACKAGE) {
size_t l = strlen(*arg);
if (l > 4 && !strcmp(*arg + l - 4, ".rpm")) {
rpmgi gi = rpmgiNew(ts, giFlags, argv);
- ec += rpmgiShowMatches(qva, ts, gi);
+ ecLocal = rpmgiShowMatches(qva, ts, gi);
rpmgiFree(gi);
}
}
+ ec += ecLocal;
rpmdbFreeIterator(mi);
}
break;
--
2.17.2

View File

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

View File

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

View File

@ -0,0 +1,26 @@
From 788935c9ea9d2f469f24be10a9fa998594046731 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 7 Sep 2018 11:52:33 +0300
Subject: [PATCH] Fix a blindingly obvious memleak in package verify step
Erm. Introduced in commit 765e2c72ae8be369ada41d4747b8999519a0e327,
but how on earth did this go unnoticed... *blush*
---
lib/transaction.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/transaction.c b/lib/transaction.c
index 205c3f388..3969ad3fc 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -1261,6 +1261,7 @@ static int verifyPackageFiles(rpmts ts, rpm_loff_t total)
rpmteAddProblem(p, RPMPROB_VERIFY, NULL, vd.msg, 0);
vd.msg = _free(vd.msg);
+ rpmvsFree(vs);
}
rpmtsNotify(ts, NULL, RPMCALLBACK_VERIFY_STOP, total, total);
--
2.21.0

View File

@ -0,0 +1,46 @@
From 531dc8495cd3aabd3f659ecab604106fdbacbe98 Mon Sep 17 00:00:00 2001
Message-Id: <531dc8495cd3aabd3f659ecab604106fdbacbe98.1554974459.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 3 Oct 2018 11:51:38 +0300
Subject: [PATCH] Fix ancient python GIL locking bug on callback
(RhBug:1632488)
Introduced in commit c7881d801745b4c156a8aa2afc17b95f97481e34 back in 2002,
synthesizing a python object for the callback occurs before retaking
the GIL lock, which is not allowed. Somehow this has managed to stay
latent all these years, and even now requires fairly specific conditions:
when the callback gets called without an associated key, such as erasures
or file trigger script start/stop events (in the case of RhBug:1632488),
when Python 3 is running in PYTHONMALLOC=debug mode,
it crashes with "Python memory allocator called without holding the GIL".
Simply retake the lock before any Python operations take place to fix.
---
python/rpmts-py.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/rpmts-py.c b/python/rpmts-py.c
index e4c5e1250..1ddfc9a1e 100644
--- a/python/rpmts-py.c
+++ b/python/rpmts-py.c
@@ -495,6 +495,8 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
if (cbInfo->cb == Py_None) return NULL;
+ PyEval_RestoreThread(cbInfo->_save);
+
/* Synthesize a python object for callback (if necessary). */
if (pkgObj == NULL) {
if (h) {
@@ -506,8 +508,6 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
} else
Py_INCREF(pkgObj);
- PyEval_RestoreThread(cbInfo->_save);
-
args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
result = PyEval_CallObject(cbInfo->cb, args);
Py_DECREF(args);
--
2.20.1

View File

@ -0,0 +1,30 @@
From 5188a7b35eb3672c9b15e96433e033ee36f8e6a8 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 6 Aug 2019 13:06:16 +0300
Subject: [PATCH] Fix memleak during transaction verify step in the NOKEY case.
Found during RhBug:1714657 QA testing.
In addition, add a comment to clarify the fallthrough as intentional.
---
lib/transaction.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/transaction.c b/lib/transaction.c
index 6e4d4be65..e51cff25a 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -1226,8 +1226,10 @@ static int vfyCb(struct rpmsinfo_s *sinfo, void *cbdata)
*/
if (!(vd->vfylevel & RPMSIG_SIGNATURE_TYPE))
sinfo->rc = RPMRC_OK;
+ /* fallthrough */
default:
- vd->msg = rpmsinfoMsg(sinfo);
+ if (sinfo->rc)
+ vd->msg = rpmsinfoMsg(sinfo);
break;
}
return (sinfo->rc == 0);
--
2.21.0

View File

@ -0,0 +1,52 @@
From 0d83637769b8a122b1e80f2e960ea1bbae8b4f10 Mon Sep 17 00:00:00 2001
Message-Id: <0d83637769b8a122b1e80f2e960ea1bbae8b4f10.1540199566.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 22 Oct 2018 10:52:39 +0300
Subject: [PATCH] Fix nasty --setperms/--setugids regression in 4.14.2 (RhBug:
1640470)
Commit 38c2f6e160d5ed3e9c3a266139c7eb2632724c15 causes --setperms and
--setugids follow symlinks instead of skipping them.
In case of --setperms, all encountered symlinks will have their
target file/directory permissions set to the 0777 of the link itself
(so world writable etc but suid/sgid stripped), temporarily or permanently,
depending on whether the symlink occurs before or after it's target in the
package file list. When the link occurs before its target, there's a short
window where the target is world writable before having it's permissions
reset to original, making it particularly bad for suid/sgid binaries.
--setugids is similarly affected with link targets owner/group changing
to that of the symlink.
Add missing parentheses to the conditions introduced in commit
38c2f6e160d5ed3e9c3a266139c7eb2632724c15 to fix.
Reported by Karel Srot, patch by Pavlina Moravcova Varekova.
---
rpmpopt.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rpmpopt.in b/rpmpopt.in
index 8aaa91f11..42d3416a3 100644
--- a/rpmpopt.in
+++ b/rpmpopt.in
@@ -44,14 +44,14 @@ rpm alias --scripts --qf '\
--POPTdesc=$"list install/erase scriptlets from package(s)"
rpm alias --setperms -q --qf '[\[ -L %{FILENAMES:shescape} \] || \
- \[ $((%{FILEFLAGS} & 2#1001000)) != 0 \] && \[ ! -e %{FILENAMES:shescape} \] || \
+ ( \[ $((%{FILEFLAGS} & 2#1001000)) != 0 \] && \[ ! -e %{FILENAMES:shescape} \] ) || \
chmod %7{FILEMODES:octal} %{FILENAMES:shescape}\n]' \
--pipe "grep -v \(none\) | grep '^. -L ' | sed 's/chmod .../chmod /' | sh" \
--POPTdesc=$"set permissions of files in a package"
rpm alias --setugids -q --qf \
'[ch %{FILEUSERNAME:shescape} %{FILEGROUPNAME:shescape} %{FILENAMES:shescape} %{FILEFLAGS}\n]' \
- --pipe "(echo 'ch() { \[ $(($4 & 2#1001000)) != 0 \] && \[ ! -e \"$3\" \] || \
+ --pipe "(echo 'ch() { ( \[ $(($4 & 2#1001000)) != 0 \] && \[ ! -e \"$3\" \] ) || \
(chown -h -- \"$1\" \"$3\";chgrp -h -- \"$2\" \"$3\";) }'; \
grep '^ch '|grep -v \(none\))|sh" \
--POPTdesc=$"set user/group ownership of files in a package"
--
2.17.2

View File

@ -0,0 +1,37 @@
From e219c9548d16a3c18dd261f7043bb8d221b87c77 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 31 Jul 2019 11:56:26 +0300
Subject: [PATCH] Fix off-by-one in hdrblobGet() making last entry unreachable
(RhBug:1722921)
hdrblobGet() introduced in commits acfde0d0e812e9f8e153ab6be8c9f2682bdd4763
and 9821de18811db97238c34a564221e315f5f35b44 has an off-by-one thinko
(perhaps the idea was to skip the first, region tag) which causes
the last entry to be unreachable. In typical packages, that is
RPMSIG_PAYLOADSIZE which is not used at all in this context so it doesn't
matter, but in large packages use RPMSIG_LONGARCHIVESIZE which has a lower
tag number and leaves either RPMSIGTAG_MD5 or RPMSIGTAG_GPG last,
unreachable and thus unverifiable. Oops.
This fixes the regression introduced in rpm 4.14, affecting verification
of large packages (ie having RPMSIG_LONGARCHIVESIZE)
---
lib/header.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/header.c b/lib/header.c
index 33623884a..9ec7ed0e4 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -2015,7 +2015,7 @@ rpmRC hdrblobGet(hdrblob blob, uint32_t tag, rpmtd td)
memset(&einfo, 0, sizeof(einfo));
rpmtdReset(td);
- for (int i = 1; i < blob->il; i++, pe++) {
+ for (int i = 0; i < blob->il; i++, pe++) {
if (pe->tag != ntag)
continue;
ei2h(pe, &einfo);
--
2.21.0

View File

@ -0,0 +1,39 @@
From a144c29831a39ed303d6ea8d2ae91e1c36d64c84 Mon Sep 17 00:00:00 2001
Message-Id: <a144c29831a39ed303d6ea8d2ae91e1c36d64c84.1559799452.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 15 May 2019 13:51:19 +0300
Subject: [PATCH] Fix packages getting erased on failed update with dnf
(RhBug:1620275)
When adding update elements, we set the erase element to depend on the
install element, but if an API user adds the same erasure manually
after adding the update, we know its a duplicate erasure and filter
it out, BUT we zero out the dependent element in the process. And
if installing the update now fails, we end up removing the whole package
due to that missing dependent element.
This never happens with rpm itself so we can't easily test it, but is
100% reproducable with dnf (at least dnf 3-4). Apparently it adds all
erasures by itself (which is kind of understandable I guess, perhaps
we should better allow this in the API)
---
lib/depends.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/depends.c b/lib/depends.c
index 6e9866eae..f8a6084ab 100644
--- a/lib/depends.c
+++ b/lib/depends.c
@@ -121,7 +121,8 @@ static int removePackage(rpmts ts, Header h, rpmte depends)
/* Filter out duplicate erasures. */
if (packageHashGetEntry(tsmem->removedPackages, dboffset, &pp, NULL, NULL)) {
- rpmteSetDependsOn(pp[0], depends);
+ if (depends)
+ rpmteSetDependsOn(pp[0], depends);
return 0;
}
--
2.21.0

View File

@ -0,0 +1,25 @@
From 475af64f64cbc210c87588d425fa9a14cd9760b6 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 29 May 2019 11:38:53 +0300
Subject: [PATCH] Fix rpmfiles memory leak on %postuntrans file trigger
preparation
---
lib/rpmtriggers.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c
index cb2441c5a..b7c76e7fc 100644
--- a/lib/rpmtriggers.c
+++ b/lib/rpmtriggers.c
@@ -154,6 +154,7 @@ void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
}
}
rpmdbFreeIterator(mi);
+ rpmfilesFree(files);
}
int runPostUnTransFileTrigs(rpmts ts)
--
2.21.0

View File

@ -0,0 +1,60 @@
From 050b392f8c11d111379e0d2bac52762beb97b3ae Mon Sep 17 00:00:00 2001
Message-Id: <050b392f8c11d111379e0d2bac52762beb97b3ae.1559645935.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 2 Apr 2019 12:57:11 +0300
Subject: [PATCH] Fix segfault on fingerprinting symlink round (RhBug:1660232)
Both yum and dnf perform a test-transaction before the real thing,
and both neglet to check for an error code from the test-transaction
when there are no problem objects to return. Which can happen in
some special cases, such a using different vsflags between initial
package read and transaction (which is what both yum and dnf do),
which can cause the in-transaction package open fail on corrupt packages.
And when this failed transaction is fed back to rpmtsRun(), it
segfaults in fingerprinting as the second loop of symlink checking
doesn't check for NULL's element files like the first loop does.
Add the missing NULL check and remove bogus "can't happen" comment to fix.
FWIW, the scenario with different vsflags and corrupted packages doesn't
happen by default in rpm >= 4.14.2, the corrupt package gets caught
in the verify stage which does create problem objects and thus both
yum and dnf abort as they should.
---
lib/fprint.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/fprint.c b/lib/fprint.c
index b810e4d2b..ab1891961 100644
--- a/lib/fprint.c
+++ b/lib/fprint.c
@@ -488,7 +488,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
(void) rpmsqPoll();
if ((fi = rpmteFiles(p)) == NULL)
- continue; /* XXX can't happen */
+ continue;
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
rpmfilesFpLookup(fi, fpc);
@@ -522,6 +522,9 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
while ((p = rpmtsiNext(pi, 0)) != NULL) {
(void) rpmsqPoll();
+ if ((fi = rpmteFiles(p)) == NULL)
+ continue;
+
fs = rpmteGetFileStates(p);
fc = rpmfsFC(fs);
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
@@ -531,6 +534,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
fpLookupSubdir(symlinks, fpc, p, i);
}
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
+ rpmfilesFree(fi);
}
rpmtsiFree(pi);
--
2.21.0

View File

@ -0,0 +1,28 @@
From 66e0c929b203d684a4f58135f42435fcc29cdd51 Mon Sep 17 00:00:00 2001
Message-Id: <66e0c929b203d684a4f58135f42435fcc29cdd51.1554982695.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 10 Oct 2018 12:00:19 +0300
Subject: [PATCH] Fix testing for wrong variable in selinux plugin debug log
The strerror() case couldn't be reached as we were testing for the
wrong rc, spotted by covscan.
---
plugins/selinux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/selinux.c b/plugins/selinux.c
index 3c9d9e4ab..accd47416 100644
--- a/plugins/selinux.c
+++ b/plugins/selinux.c
@@ -169,7 +169,7 @@ static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
if (rpmIsDebug()) {
rpmlog(RPMLOG_DEBUG, "lsetfilecon: (%s, %s) %s\n",
- path, scon, (rc < 0 ? strerror(errno) : ""));
+ path, scon, (conrc < 0 ? strerror(errno) : ""));
}
if (conrc == 0 || (conrc < 0 && errno == EOPNOTSUPP))
--
2.20.1

View File

@ -0,0 +1,47 @@
From 74766d30b95f1575df8a42d185f2643caa235a8b Mon Sep 17 00:00:00 2001
Message-Id: <74766d30b95f1575df8a42d185f2643caa235a8b.1543835412.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 23 Nov 2018 12:47:27 +0200
Subject: [PATCH] Handle unsupported digests the same as disabled ones
(RhBug:1652529)
A digest type unsupported by the underlying crypto library (whether
technically or by configuration) does not mean the digest is invalid,
it just cannot be used. Which for the purposes of verification is the
same as if that digest didn't exist at all, and that's exactly how we
handle digests and signatures disabled by configuration.
One particular case is FIPS mode which globally disables the use of MD5,
which we mishandled prior to this by showing it as OK in verification
despite actually not verifying it at all.
The exact place for handling this case is a bit subtle: the "obvious"
place for checking for supported type is in rpmvsInitRange() but this
doesn't work because of rpmDigestBundleAddID() return code semantics.
The other "obvious" place would be rpmvsVerify(), but by that point
we have even more funny cases to consider. So for now, it's actually
easiest to check for this in rpmvsFiniRange() even if it's not the
most obvious place for doing so. Might want to change the
rpmDigestBundleAddID() semantics later, but this makes for a nicer
backport (we'll need this in 4.14.x too).
---
lib/rpmvs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/rpmvs.c b/lib/rpmvs.c
index 7b5b86f8e..622e48011 100644
--- a/lib/rpmvs.c
+++ b/lib/rpmvs.c
@@ -388,6 +388,9 @@ void rpmvsFiniRange(struct rpmvs_s *sis, int range)
if (sinfo->range == range && sinfo->rc == RPMRC_OK) {
sinfo->ctx = rpmDigestBundleDupCtx(sis->bundle, sinfo->id);
+ /* Handle unsupported digests the same as disabled ones */
+ if (sinfo->ctx == NULL)
+ sinfo->rc = RPMRC_NOTFOUND;
rpmDigestBundleFinal(sis->bundle, sinfo->id, NULL, NULL, 0);
}
}
--
2.19.2

View File

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

View File

@ -0,0 +1,86 @@
From 8cbe8baf9c3ff4754369bcd29441df14ecc6889d Mon Sep 17 00:00:00 2001
Message-Id: <8cbe8baf9c3ff4754369bcd29441df14ecc6889d.1554982512.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 14 Feb 2019 13:12:49 +0200
Subject: [PATCH] Log RPMLOG_ERR level messages on actual errors in selinux
plugin, doh.
When there's an actual error, people will want to know without having
to rerun in verbose mode. Such as in RhBug:1641631 where configured
selinux policy differs from what is installed - the former message
error: Plugin selinux: hook tsm_pre failed
...is not particularly helpful to anybody, whereas this actually provides
some clues now:
error: selabel_open: (/etc/selinux/ponies/contexts/files/file_contexts) No such file or directory
error: Plugin selinux: hook tsm_pre failed
---
plugins/selinux.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/plugins/selinux.c b/plugins/selinux.c
index accd47416..f1caf257c 100644
--- a/plugins/selinux.c
+++ b/plugins/selinux.c
@@ -12,6 +12,11 @@
static struct selabel_handle * sehandle = NULL;
+static inline rpmlogLvl loglvl(int iserror)
+{
+ return iserror ? RPMLOG_ERR : RPMLOG_DEBUG;
+}
+
static void sehandle_fini(int close_status)
{
if (sehandle) {
@@ -47,7 +52,7 @@ static rpmRC sehandle_init(int open_status)
sehandle = selabel_open(SELABEL_CTX_FILE, opts, 1);
- rpmlog(RPMLOG_DEBUG, "selabel_open: (%s) %s\n",
+ rpmlog(loglvl(sehandle == NULL), "selabel_open: (%s) %s\n",
path, (sehandle == NULL ? strerror(errno) : ""));
return (sehandle != NULL) ? RPMRC_OK : RPMRC_FAIL;
@@ -125,10 +130,8 @@ static rpmRC selinux_scriptlet_fork_post(rpmPlugin plugin,
if ((xx = setexeccon(newcon)) == 0)
rc = RPMRC_OK;
- if (rpmIsDebug()) {
- rpmlog(RPMLOG_DEBUG, "setexeccon: (%s, %s) %s\n",
+ rpmlog(loglvl(xx < 0), "setexeccon: (%s, %s) %s\n",
path, newcon, (xx < 0 ? strerror(errno) : ""));
- }
exit:
context_free(con);
@@ -143,10 +146,8 @@ exit:
if ((xx = setexecfilecon(path, "rpm_script_t") == 0))
rc = RPMRC_OK;
- if (rpmIsDebug()) {
- rpmlog(RPMLOG_DEBUG, "setexecfilecon: (%s) %s\n",
+ rpmlog(loglvl(xx < 0), "setexecfilecon: (%s) %s\n",
path, (xx < 0 ? strerror(errno) : ""));
- }
#endif
/* If selinux is not enforcing, we don't care either */
if (rc && security_getenforce() < 1)
@@ -167,10 +168,8 @@ static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
if (selabel_lookup_raw(sehandle, &scon, dest, file_mode) == 0) {
int conrc = lsetfilecon(path, scon);
- if (rpmIsDebug()) {
- rpmlog(RPMLOG_DEBUG, "lsetfilecon: (%s, %s) %s\n",
+ rpmlog(loglvl(conrc < 0), "lsetfilecon: (%s, %s) %s\n",
path, scon, (conrc < 0 ? strerror(errno) : ""));
- }
if (conrc == 0 || (conrc < 0 && errno == EOPNOTSUPP))
rc = RPMRC_OK;
--
2.20.1

View File

@ -0,0 +1,49 @@
From 2ec0832287bd1443ebf336f8a98293f30bfa2036 Mon Sep 17 00:00:00 2001
Message-Id: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 18 Mar 2019 15:24:54 +0200
Subject: [PATCH 1/3] Make rpmsign exit values more consistent with our other
tools
rpmPkgSign*() return -1 for failure, which is not that helpful when
returned to shell and the way it was counted could easily wrap around
when signing multiple packages. Return number of failures similarly to
how rpm -q and frieds does, avoid overflows and xargs special value 255.
---
rpmsign.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/rpmsign.c b/rpmsign.c
index ae86f666d..1a5cd59c2 100644
--- a/rpmsign.c
+++ b/rpmsign.c
@@ -134,7 +134,8 @@ static int doSign(poptContext optCon, struct rpmSignArgs *sargs)
const char *arg;
rc = 0;
while ((arg = poptGetArg(optCon)) != NULL) {
- rc += rpmPkgSign(arg, sargs);
+ if (rpmPkgSign(arg, sargs) < 0)
+ rc++;
}
exit:
@@ -175,7 +176,8 @@ int main(int argc, char *argv[])
case MODE_DELSIGN:
ec = 0;
while ((arg = poptGetArg(optCon)) != NULL) {
- ec += rpmPkgDelSign(arg, &sargs);
+ if (rpmPkgDelSign(arg, &sargs) < 0)
+ ec++;
}
break;
case MODE_NONE:
@@ -188,5 +190,5 @@ int main(int argc, char *argv[])
exit:
rpmcliFini(optCon);
- return ec;
+ return RETVAL(ec);
}
--
2.20.1

View File

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

View File

@ -0,0 +1,89 @@
From 13b0ebee7cdb1e4d200b3c40d0ec9440f198a1d4 Mon Sep 17 00:00:00 2001
Message-Id: <13b0ebee7cdb1e4d200b3c40d0ec9440f198a1d4.1554886141.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 10 Apr 2019 11:24:44 +0300
Subject: [PATCH] Monkey-patch .decode() method to our strings as a temporary
compat crutch
As a temporary crutch to support faster deployment of the sane
string behavior on python3, monkey-patch a decode method into all
strings we return. This seems to be enough to fix practically all
API users who have already adapted to the long-standing broken API
on Python 3. API users compatible with both Python 2 and 3 never needed
this anyway. Issue a warning with pointer to the relevant bug when the
fake decode() method is used to alert users to the issue.
This is certainly an evil thing to do and will be removed as soon as
the critical users have been fixed to work with the new, corrected
behavior.
---
python/rpm/__init__.py | 3 +++
python/rpmmodule.c | 1 +
python/rpmsystem-py.h | 22 ++++++++++++++++++++--
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/python/rpm/__init__.py b/python/rpm/__init__.py
index 54728bbd4..6d69eda7b 100644
--- a/python/rpm/__init__.py
+++ b/python/rpm/__init__.py
@@ -61,6 +61,9 @@ except ImportError:
# backwards compatibility + give the same class both ways
ts = TransactionSet
+def _fakedecode(self, encoding='utf-8', errors='strict'):
+ warnings.warn("decode() called on unicode string, see https://bugzilla.redhat.com/show_bug.cgi?id=1693751", UnicodeWarning, stacklevel=2)
+ return self
def headerLoad(*args, **kwds):
"""DEPRECATED! Use rpm.hdr() instead."""
diff --git a/python/rpmmodule.c b/python/rpmmodule.c
index 05032edc7..2a76cfbd0 100644
--- a/python/rpmmodule.c
+++ b/python/rpmmodule.c
@@ -28,6 +28,7 @@
*/
PyObject * pyrpmError;
+PyObject * fakedecode = NULL;
static PyObject * archScore(PyObject * self, PyObject * arg)
{
diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
index 25938464a..803da0fc1 100644
--- a/python/rpmsystem-py.h
+++ b/python/rpmsystem-py.h
@@ -19,12 +19,29 @@
#define PyInt_AsSsize_t PyLong_AsSsize_t
#endif
+PyObject * fakedecode;
+
static inline PyObject * utf8FromString(const char *s)
{
/* In Python 3, we return all strings as surrogate-escaped utf-8 */
#if PY_MAJOR_VERSION >= 3
- if (s != NULL)
- return PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
+ if (s != NULL) {
+ PyObject *o = PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
+ /* fish the fake decode function from python side if not done yet */
+ if (fakedecode == NULL) {
+ PyObject *n = PyUnicode_FromString("rpm");
+ PyObject *m = PyImport_Import(n);
+ PyObject *md = PyModule_GetDict(m);
+ fakedecode = PyDict_GetItemString(md, "_fakedecode");
+ Py_DECREF(m);
+ Py_DECREF(n);
+ }
+ if (fakedecode && o) {
+ /* monkey-patch it into the string object as "decode" */
+ PyDict_SetItemString(Py_TYPE(o)->tp_dict, "decode", fakedecode);
+ }
+ return o;
+ }
#else
if (s != NULL)
return PyBytes_FromString(s);
--
2.20.1

View File

@ -0,0 +1,80 @@
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;
diff --git a/lib/rpmvs.h b/lib/rpmvs.h
index b27d9a612..a836d5c94 100644
--- a/lib/rpmvs.h
+++ b/lib/rpmvs.h
@@ -75,6 +75,9 @@ void rpmvsInitRange(struct rpmvs_s *sis, int range);
RPM_GNUC_INTERNAL
void rpmvsFiniRange(struct rpmvs_s *sis, int range);
+RPM_GNUC_INTERNAL
+int rpmvsRange(struct rpmvs_s *vs);
+
RPM_GNUC_INTERNAL
int rpmvsVerify(struct rpmvs_s *sis, int type,
rpmsinfoCb cb, void *cbdata);
--
2.20.1