Add patches for next release
Resolves: RHEL-73186 RHEL-54386 RHEL-65378
This commit is contained in:
parent
4783f4455f
commit
a7bd5f6cf7
229
0001-Report-unsafe-symlinks-during-installation-as-a-spec.patch
Normal file
229
0001-Report-unsafe-symlinks-during-installation-as-a-spec.patch
Normal file
@ -0,0 +1,229 @@
|
||||
From 6d8f3cbe56839c7417fe17714b92034eea044895 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Mon, 19 Aug 2024 11:03:10 +0300
|
||||
Subject: [PATCH 1/2] 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
|
||||
|
||||
Fixes: RHEL-73186
|
||||
---
|
||||
lib/fsm.c | 70 ++++++++++++++++++++++++++-------------------------
|
||||
lib/rpmfi.c | 2 +-
|
||||
tests/rpmi.at | 4 +--
|
||||
3 files changed, 39 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 36708acc3..5e073ce22 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;
|
||||
|
||||
@@ -1026,10 +1030,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 011d6787e..b35195e76 100644
|
||||
--- a/lib/rpmfi.c
|
||||
+++ b/lib/rpmfi.c
|
||||
@@ -2487,7 +2487,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 = _("Invalid symlink"); break;
|
||||
+ case RPMERR_INVALID_SYMLINK: s = _("Unsafe symlink"); break;
|
||||
case RPMERR_ENOTDIR: s = strerror(ENOTDIR); break;
|
||||
case RPMERR_ENOENT: s = strerror(ENOENT); break;
|
||||
case RPMERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break;
|
||||
diff --git a/tests/rpmi.at b/tests/rpmi.at
|
||||
index 95b4497be..ae8b24437 100644
|
||||
--- a/tests/rpmi.at
|
||||
+++ b/tests/rpmi.at
|
||||
@@ -1555,8 +1555,8 @@ runroot --setenv SOURCE_DATE_EPOCH 1699955855 rpm -U /build/RPMS/noarch/replacet
|
||||
],
|
||||
[1],
|
||||
[],
|
||||
-[error: failed to open dir opt of /opt/: Not a directory
|
||||
-error: unpacking of archive failed on file /opt/foo;6553448f: cpio: open failed - Not a directory
|
||||
+[error: failed to open dir opt of /opt/: cpio: Unsafe symlink
|
||||
+error: unpacking of archive failed on file /opt/foo;6553448f: cpio: Unsafe symlink
|
||||
error: replacetest-1.0-1.noarch: install failed
|
||||
])
|
||||
RPMTEST_CLEANUP
|
||||
--
|
||||
2.47.1
|
||||
|
121
0002-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch
Normal file
121
0002-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From 5ae6dd32ea4b755a354facb54d5cecbdcf3df25a Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Fri, 18 Oct 2024 14:50:35 +0300
|
||||
Subject: [PATCH 2/2] 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
|
||||
|
||||
Fixes: RHEL-54386
|
||||
---
|
||||
lib/fsm.c | 2 +-
|
||||
tests/data/SPECS/pamupdate.spec | 21 +++++++++++++++++
|
||||
tests/rpmi.at | 40 +++++++++++++++++++++++++++++++++
|
||||
3 files changed, 62 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/data/SPECS/pamupdate.spec
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 5e073ce22..19f28cade 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -1094,7 +1094,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);
|
||||
}
|
||||
}
|
||||
diff --git a/tests/data/SPECS/pamupdate.spec b/tests/data/SPECS/pamupdate.spec
|
||||
new file mode 100644
|
||||
index 000000000..a458b9b73
|
||||
--- /dev/null
|
||||
+++ b/tests/data/SPECS/pamupdate.spec
|
||||
@@ -0,0 +1,21 @@
|
||||
+Name: pamupdate
|
||||
+Version: 1.0
|
||||
+Release: %{rel}
|
||||
+Group: Testing
|
||||
+License: Public domain
|
||||
+Summary: Test config behavior on update failure
|
||||
+BuildArch: noarch
|
||||
+
|
||||
+%description
|
||||
+%{summary}
|
||||
+
|
||||
+%install
|
||||
+mkdir -p ${RPM_BUILD_ROOT}/etc
|
||||
+echo AAAA > ${RPM_BUILD_ROOT}/etc/my.conf
|
||||
+echo BBBB > ${RPM_BUILD_ROOT}/etc/your.conf
|
||||
+mkdir -p ${RPM_BUILD_ROOT}/var/run/faillock
|
||||
+
|
||||
+%files
|
||||
+%config /etc/my.conf
|
||||
+%config /etc/your.conf
|
||||
+%dir /var/run/faillock
|
||||
diff --git a/tests/rpmi.at b/tests/rpmi.at
|
||||
index ae8b24437..804123b1a 100644
|
||||
--- a/tests/rpmi.at
|
||||
+++ b/tests/rpmi.at
|
||||
@@ -1560,3 +1560,43 @@ error: unpacking of archive failed on file /opt/foo;6553448f: cpio: Unsafe symli
|
||||
error: replacetest-1.0-1.noarch: install failed
|
||||
])
|
||||
RPMTEST_CLEANUP
|
||||
+
|
||||
+AT_SETUP([update on invalid symlinked directory])
|
||||
+AT_KEYWORDS([install update symlink])
|
||||
+RPMDB_INIT
|
||||
+
|
||||
+RPMTEST_CHECK([
|
||||
+for r in 1 2; do
|
||||
+ runroot rpmbuild --quiet --bb \
|
||||
+ --define "rel ${r}" \
|
||||
+ /data/SPECS/pamupdate.spec
|
||||
+done
|
||||
+],
|
||||
+[0],
|
||||
+[],
|
||||
+[])
|
||||
+
|
||||
+RPMTEST_CHECK([
|
||||
+runroot rpm -U /build/RPMS/noarch/pamupdate-1.0-1.noarch.rpm
|
||||
+runroot rpm -V pamupdate
|
||||
+],
|
||||
+[0],
|
||||
+[],
|
||||
+[])
|
||||
+
|
||||
+RPMTEST_CHECK([
|
||||
+runroot_other chown -h nobody:nobody /var/run
|
||||
+runroot rpm -U /build/RPMS/noarch/pamupdate-1.0-2.noarch.rpm
|
||||
+],
|
||||
+[1],
|
||||
+[],
|
||||
+[ignore])
|
||||
+
|
||||
+RPMTEST_CHECK([
|
||||
+# --nomtime shouldn't be needed but fixing that's another story
|
||||
+runroot rpm -V --nomtime pamupdate
|
||||
+],
|
||||
+[0],
|
||||
+[],
|
||||
+[])
|
||||
+RPMTEST_CLEANUP
|
||||
--
|
||||
2.47.1
|
||||
|
10
rpm.spec
10
rpm.spec
@ -27,7 +27,7 @@
|
||||
|
||||
%global rpmver 4.19.1.1
|
||||
#global snapver rc1
|
||||
%global baserelease 9
|
||||
%global baserelease 10
|
||||
%global sover 10
|
||||
|
||||
%global srcver %{rpmver}%{?snapver:-%{snapver}}
|
||||
@ -146,6 +146,9 @@ rpm-4.18.90-weak-user-group.patch
|
||||
0002-Eliminate-hardcoded-GPG-references-from-user-visible.patch
|
||||
0003-Declare-signCmd-static.patch
|
||||
|
||||
0001-Report-unsafe-symlinks-during-installation-as-a-spec.patch
|
||||
0002-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch
|
||||
|
||||
# These are not yet upstream
|
||||
rpm-4.7.1-geode-i686.patch
|
||||
|
||||
@ -628,6 +631,11 @@ fi
|
||||
%doc %{_defaultdocdir}/rpm/API/
|
||||
|
||||
%changelog
|
||||
* Mon Jan 13 2025 Michal Domonkos <mdomonko@redhat.com> - 4.19.1.1-10
|
||||
- Report unsafe symlinks during installation as a specific case (RHEL-73186)
|
||||
- Fix FA_TOUCH'ed files getting removed on failed update (RHEL-54386)
|
||||
- Rebuild for ima-evm-utils 1.6 soname bump (RHEL-65378)
|
||||
|
||||
* Wed Dec 04 2024 Panu Matilainen <pmatilai@redhat.com> - 4.19.1.1-9
|
||||
- Revert the gnupg/sequoia sub-packages, too much headache
|
||||
- Ship sequoia-signing enablement macros as documentation instead
|
||||
|
Loading…
Reference in New Issue
Block a user