Add patches for next 8.10.z batch
Resolves: RHEL-39894 RHEL-39896 RHEL-49494 RHEL-39897 RHEL-63069
This commit is contained in:
parent
b86572b8d2
commit
b4c5b23742
40
0001-Don-t-segfault-on-missing-priority-tag.patch
Normal file
40
0001-Don-t-segfault-on-missing-priority-tag.patch
Normal file
@ -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
|
||||||
|
|
221
0002-Fix-IMA-signature-fubar-take-III-1833-RhBug-2018937.patch
Normal file
221
0002-Fix-IMA-signature-fubar-take-III-1833-RhBug-2018937.patch
Normal file
@ -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
|
||||||
|
|
94
0003-Fix-root-relocation-regression.patch
Normal file
94
0003-Fix-root-relocation-regression.patch
Normal file
@ -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
|
||||||
|
|
215
0004-Report-unsafe-symlinks-during-installation-as-a-spec.patch
Normal file
215
0004-Report-unsafe-symlinks-during-installation-as-a-spec.patch
Normal file
@ -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,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
|
||||||
|
|
14
rpm.spec
14
rpm.spec
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
%global rpmver 4.14.3
|
%global rpmver 4.14.3
|
||||||
#global snapver rc2
|
#global snapver rc2
|
||||||
%global rel 31
|
%global rel 32
|
||||||
|
|
||||||
%global srcver %{version}%{?snapver:-%{snapver}}
|
%global srcver %{version}%{?snapver:-%{snapver}}
|
||||||
%global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x}
|
%global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x}
|
||||||
@ -141,6 +141,11 @@ Patch506: 0004-Bump-the-minimum-Python-version-requirement-to-2.7.patch
|
|||||||
Patch507: 0005-Drop-an-unnecessary-Python-2-vs-3-incompatibility-fr.patch
|
Patch507: 0005-Drop-an-unnecessary-Python-2-vs-3-incompatibility-fr.patch
|
||||||
Patch508: rpm-4.14.3-python3.diff
|
Patch508: rpm-4.14.3-python3.diff
|
||||||
Patch509: rpm-4-14.3-selinux-log-error.patch
|
Patch509: rpm-4-14.3-selinux-log-error.patch
|
||||||
|
Patch510: 0001-Don-t-segfault-on-missing-priority-tag.patch
|
||||||
|
Patch511: 0002-Fix-IMA-signature-fubar-take-III-1833-RhBug-2018937.patch
|
||||||
|
Patch512: 0003-Fix-root-relocation-regression.patch
|
||||||
|
Patch513: 0004-Report-unsafe-symlinks-during-installation-as-a-spec.patch
|
||||||
|
Patch514: 0005-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch
|
||||||
|
|
||||||
# These are not yet upstream
|
# These are not yet upstream
|
||||||
# Audit support
|
# Audit support
|
||||||
@ -711,6 +716,13 @@ make check || cat tests/rpmtests.log
|
|||||||
%doc doc/librpm/html/*
|
%doc doc/librpm/html/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Oct 21 2024 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-32
|
||||||
|
- Fix FA_TOUCH'ed files getting removed on failed update (RHEL-63069)
|
||||||
|
- Fix IMA signature lengths assumed constant (RHEL-39896)
|
||||||
|
- Fix root relocation regression (RHEL-49494)
|
||||||
|
- Report unsafe symlinks during installation as a specific case (RHEL-39897)
|
||||||
|
- Don't segfault on missing priority tag (RHEL-39894)
|
||||||
|
|
||||||
* Tue Dec 12 2023 Florian Festi <ffesti@redhat.com> - 4.14.3-31
|
* Tue Dec 12 2023 Florian Festi <ffesti@redhat.com> - 4.14.3-31
|
||||||
- Backport file handling code from rpm-4.19 to fix CVE-2021-35937,
|
- Backport file handling code from rpm-4.19 to fix CVE-2021-35937,
|
||||||
CVE-2021-35938 and CVE-2021-35939
|
CVE-2021-35938 and CVE-2021-35939
|
||||||
|
Loading…
Reference in New Issue
Block a user