diff --git a/backport-Allow-version-to-be-omitted-in-the-replace-test-spec.patch b/backport-Allow-version-to-be-omitted-in-the-replace-test-spec.patch new file mode 100644 index 0000000..106cb77 --- /dev/null +++ b/backport-Allow-version-to-be-omitted-in-the-replace-test-spec.patch @@ -0,0 +1,27 @@ +From 2c20f9677eff989817148d236543191dec0d8059 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 14 Nov 2023 09:07:28 +0200 +Subject: [PATCH] Allow version to be omitted in the replace test spec + +Conflict:adapt context +Reference:https://github.com/rpm-software-management/rpm/commit/2c20f9677eff989817148d236543191dec0d8059 + +--- + tests/data/SPECS/replacetest.spec | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/data/SPECS/replacetest.spec b/tests/data/SPECS/replacetest.spec +index 0f86ea628..4fb72b408 100644 +--- a/tests/data/SPECS/replacetest.spec ++++ b/tests/data/SPECS/replacetest.spec +@@ -2,6 +2,7 @@ + %{?fixit: %global havepretrans 1} + %{!?user: %global user root} + %{!?grp: %global grp root} ++%{!?ver: %global ver 1.0} + + Name: replacetest%{?sub:-%{sub}} + Version: %{ver} +-- +2.33.0 + diff --git a/backport-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch b/backport-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch new file mode 100644 index 0000000..8695532 --- /dev/null +++ b/backport-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch @@ -0,0 +1,47 @@ +From 027ef640b33b38ca257bb301bb302e9c71d43c27 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Fri, 18 Oct 2024 14:50:35 +0300 +Subject: [PATCH] Fix FA_TOUCH'ed files getting removed on failed update + +Conflict:modify fsm.c instead of fsm.cc; don't modify testcode because +the test code differs greatly, it requires the root permission to run +chown. However, the current test code cannot implement chown. Manual +test cases will be used to guard test cases. +Reference:https://github.com/rpm-software-management/rpm/commit/027ef640b33b38ca257bb301bb302e9c71d43c27 + +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. + +Fixes: RHEL-54386 +Fixes: #3284 +--- + lib/fsm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/fsm.c b/lib/fsm.c +index e3be219c3..ec0303400 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); + } + } +-- +2.33.0 + diff --git a/backport-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch b/backport-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch new file mode 100644 index 0000000..1fc8fd5 --- /dev/null +++ b/backport-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch @@ -0,0 +1,49 @@ +From 89ce4e7ca592f5abafc3f25aeaa07d36a7b43a61 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 14 Nov 2023 11:37:48 +0200 +Subject: [PATCH] Fix wrong return code on O_DIRECTORY open of invalid symlink + +Conflict:NA +Reference:https://github.com/rpm-software-management/rpm/commit/89ce4e7ca592f5abafc3f25aeaa07d36a7b43a61 + +The dir argument to fsmOpenpath() is supposed to be a rough O_DIRECTORY +equivalent, and if the path is actually a misowned symlink it should +return ENOTDIR instead of ELOOP. Makes the resulting error messages +at least a little more comprehensible. +--- + lib/fsm.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/fsm.c b/lib/fsm.c +index 51f439ef3..091e90554 100644 +--- a/lib/fsm.c ++++ b/lib/fsm.c +@@ -304,6 +304,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir) + struct stat lsb, sb; + int sflags = flags | O_NOFOLLOW; + int fd = openat(dirfd, path, sflags); ++ int ffd = fd; + + /* + * Only ever follow symlinks by root or target owner. Since we can't +@@ -312,7 +313,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir) + * it could've only been the link owner or root. + */ + if (fd < 0 && errno == ELOOP && flags != sflags) { +- int ffd = openat(dirfd, path, flags); ++ ffd = openat(dirfd, path, flags); + if (ffd >= 0) { + if (fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) { + if (fstat(ffd, &sb) == 0) { +@@ -327,7 +328,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir) + } + + /* O_DIRECTORY equivalent */ +- if (dir && fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)) { ++ if (dir && ((fd != ffd) || (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)))) { + errno = ENOTDIR; + fsmClose(&fd); + } +-- +2.33.0 + diff --git a/backport-Refactor-fsmOpenat-return-style-for-consistency-with.patch b/backport-Refactor-fsmOpenat-return-style-for-consistency-with.patch new file mode 100644 index 0000000..8cb749f --- /dev/null +++ b/backport-Refactor-fsmOpenat-return-style-for-consistency-with.patch @@ -0,0 +1,175 @@ +From 14516542c113560dc0070df2f9102568a7a71b58 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 19 Aug 2024 11:03:10 +0300 +Subject: [PATCH] Refactor fsmOpenat() return style for consistency within the + fsm + +Conflict:adapt context; don't modify testcode because the test code differs +greatly, 0091214 requires the root permission to run chown. However, the +current test code cannot implement chown. Manual test cases will be used to +guard test cases. +Reference:https://github.com/rpm-software-management/rpm/commit/14516542c113560dc0070df2f9102568a7a71b58 + +Everything inside the fsm is returning a return code as the main +returned data and file descriptors as one of the arguments, except +for fsmOpenat() which I for some reason modeled after openat() instead. +This mismatch makes for some strange code in the callers. + +The only visible change here is supposed to be the error message +changing slightly due to using rpmfileStrerror() instead of strerror(). + +Co-authored-by: Florian Festi +--- + lib/fsm.c | 62 +++++++++++++++++++++++++-------------------------- + 1 file changed, 31 insertions(+), 31 deletions(-) + +diff --git a/lib/fsm.c b/lib/fsm.c +index 20b270cf5..b5f8800a8 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) + #if 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,13 @@ 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 +@@ -328,11 +329,17 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir) + } + + /* O_DIRECTORY equivalent */ +- if (dir && ((fd != ffd) || (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)))) { +- errno = ENOTDIR; ++ if (!rc && dir && ((fd != ffd) || (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 +358,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 +383,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 +1028,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) { +-- +2.33.0 + diff --git a/backport-Report-unsafe-symlinks-during-installation-as-a-spec.patch b/backport-Report-unsafe-symlinks-during-installation-as-a-spec.patch new file mode 100644 index 0000000..bfc8586 --- /dev/null +++ b/backport-Report-unsafe-symlinks-during-installation-as-a-spec.patch @@ -0,0 +1,87 @@ +From 535eacc96ae6fe5289a2917bb0af43e491b0f4f4 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 19 Aug 2024 11:43:33 +0300 +Subject: [PATCH] Report unsafe symlinks during installation as a specific case + +Conflict:don't modify testcode because the test code differs greatly, 0091214 +requires the root permission to run chown. However, the current test code +cannot implement chown. Manual test cases will be used to guard test cases. +Reference:https://github.com/rpm-software-management/rpm/commit/535eacc96ae6fe5289a2917bb0af43e491b0f4f4 + +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 + +Resolves: #3100 +--- + lib/fsm.c | 10 ++++++---- + lib/rpmfi.c | 2 +- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/lib/fsm.c b/lib/fsm.c +index b5f8800a8..4c0968f73 100644 +--- a/lib/fsm.c ++++ b/lib/fsm.c +@@ -304,7 +304,6 @@ 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; + + /* +@@ -314,7 +313,7 @@ static int fsmOpenat(int *wfdp, 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) { +@@ -323,13 +322,16 @@ static int fsmOpenat(int *wfdp, 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 (!rc && dir && ((fd != ffd) || (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)))) ++ if (!rc && dir && fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)) + rc = RPMERR_ENOTDIR; + + if (!rc && fd < 0) +diff --git a/lib/rpmfi.c b/lib/rpmfi.c +index a3d8ad470..d8dbb67c7 100644 +--- a/lib/rpmfi.c ++++ b/lib/rpmfi.c +@@ -2426,7 +2426,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; +-- +2.33.0 + diff --git a/rpm.spec b/rpm.spec index 96cf15a..89d4a7f 100644 --- a/rpm.spec +++ b/rpm.spec @@ -1,6 +1,6 @@ Name: rpm Version: 4.18.2 -Release: 21 +Release: 22 Summary: RPM Package Manager License: GPL-2.0-or-later URL: https://rpm.org/ @@ -52,6 +52,11 @@ Patch6029: backport-Fix-memleak-when-process-policies.patch Patch6030: backport-Enforce-the-same-sanity-checks-on-db-add-and-rebuild.patch Patch6031: backport-Fix-a-memory-leak-on-rpmdb-importdb.patch Patch6032: backport-Require-macro-filenames-to-end-in-alphanum-char.patch +Patch6033: backport-Allow-version-to-be-omitted-in-the-replace-test-spec.patch +Patch6034: backport-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch +Patch6035: backport-Refactor-fsmOpenat-return-style-for-consistency-with.patch +Patch6036: backport-Report-unsafe-symlinks-during-installation-as-a-spec.patch +Patch6037: backport-Fix-FA_TOUCH-ed-files-getting-removed-on-failed-upda.patch Patch9000: Add-digest-list-plugin.patch Patch9001: Add-IMA-digest-list-support.patch @@ -340,6 +345,9 @@ make clean %exclude %{_mandir}/man8/rpmspec.8* %changelog +* Mon Dec 2 2024 hugel - 4.18.2-22 +- sync patches from upstream + * Wed Nov 27 2024 hugel - 4.18.2-21 - Require macro filenames to end in alphanum char