From b86572b8d2e2f78f7e6bb4c05914fd747ae0fbb4 Mon Sep 17 00:00:00 2001 From: Florian Festi Date: Dec 13 2023 13:31:16 +0000 Subject: Fix issues with backported file handling Resolves: RHEL-9561 RHEL-9563 RHEL-9565 --- diff --git a/0001-Don-t-warn-about-missing-user-group-on-skipped-files.patch b/0001-Don-t-warn-about-missing-user-group-on-skipped-files.patch new file mode 100644 index 0000000..f910f38 --- /dev/null +++ b/0001-Don-t-warn-about-missing-user-group-on-skipped-files.patch @@ -0,0 +1,30 @@ +From 6c66abd34cccbb5b3c063f8f613e0c2faffc415f Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Wed, 13 Dec 2023 11:57:50 +0200 +Subject: [PATCH] Don't warn about missing user/group on skipped files + +There's no reason to complain about missing user/group for entities +we don't create at all. It's cosmetical only, but "regressed" in the +4.17 fsm robustness rewrite. + +Reported in https://issues.redhat.com/browse/RHEL-18037 +--- + lib/fsm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/fsm.c b/lib/fsm.c +index 2189bd84c..a54e43bae 100644 +--- a/lib/fsm.c ++++ b/lib/fsm.c +@@ -903,7 +903,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + fp->fpath = fsmFsPath(fi, fp->suffix); + + /* Remap file perms, owner, and group. */ +- rc = rpmfiStat(fi, 1, &fp->sb); ++ rc = rpmfiStat(fi, (fp->skip == 0), &fp->sb); + + /* Hardlinks are tricky and handled elsewhere for install */ + fp->setmeta = (fp->skip == 0) && +-- +2.43.0 + diff --git a/0001-Emit-full-paths-for-file-disposition-diagnostics-on-.patch b/0001-Emit-full-paths-for-file-disposition-diagnostics-on-.patch new file mode 100644 index 0000000..29fb473 --- /dev/null +++ b/0001-Emit-full-paths-for-file-disposition-diagnostics-on-.patch @@ -0,0 +1,66 @@ +From c140768202e271b60910644c1e4bf848a50218d3 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 27 Nov 2023 11:52:34 +0200 +Subject: [PATCH] Emit full paths for file disposition diagnostics on + --fsmdebug + +The full path is visible in the actual file operations later, but the +pre-flight disposition diagnostics is unreadable without the full path. +This regressed in the switch to relative paths for the *at() API family +for the symlink CVE fixes. +--- + lib/fsm.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/lib/fsm.c b/lib/fsm.c +index 091e90554..fcd764648 100644 +--- a/lib/fsm.c ++++ b/lib/fsm.c +@@ -482,14 +482,14 @@ static void removeSBITS(int dirfd, const char *path) + } + } + +-static void fsmDebug(const char *fpath, rpmFileAction action, ++static void fsmDebug(const char *dn, const char *fpath, rpmFileAction action, + const struct stat *st) + { +- rpmlog(RPMLOG_DEBUG, "%-10s %06o%3d (%4d,%4d)%6d %s\n", ++ rpmlog(RPMLOG_DEBUG, "%-10s %06o%3d (%4d,%4d)%6d %s%s\n", + fileActionString(action), (int)st->st_mode, + (int)st->st_nlink, (int)st->st_uid, + (int)st->st_gid, (int)st->st_size, +- (fpath ? fpath : "")); ++ (dn ? dn : ""), (fpath ? fpath : "")); + } + + static int fsmSymlink(const char *opath, int dirfd, const char *path) +@@ -910,7 +910,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + (fp->sb.st_nlink == 1 || fp->action == FA_TOUCH); + + setFileState(fs, fx); +- fsmDebug(fp->fpath, fp->action, &fp->sb); ++ fsmDebug(rpmfiDN(fi), fp->fpath, fp->action, &fp->sb); + + fp->stage = FILE_PRE; + } +@@ -975,7 +975,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, + rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n", + fp->fpath); + fp->action = FA_CREATE; +- fsmDebug(fp->fpath, fp->action, &fp->sb); ++ fsmDebug(rpmfiDN(fi), fp->fpath, fp->action, &fp->sb); + } + + /* When touching we don't need any of this... */ +@@ -1138,7 +1138,7 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files, + + rc = fsmStat(di.dirfd, fp->fpath, 1, &fp->sb); + +- fsmDebug(fp->fpath, fp->action, &fp->sb); ++ fsmDebug(rpmfiDN(fi), fp->fpath, fp->action, &fp->sb); + + /* Run fsm file pre hook for all plugins */ + rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath, +-- +2.43.0 + diff --git a/0001-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch b/0001-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch new file mode 100644 index 0000000..1d73765 --- /dev/null +++ b/0001-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch @@ -0,0 +1,46 @@ +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 + +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.43.0 + diff --git a/0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch b/0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch index 0cdde83..51ecf97 100644 --- a/0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch +++ b/0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch @@ -76,11 +76,23 @@ index 39762c376..ddf5d7048 100644 mode_t mode, rpmFsmOp op); #ifdef __cplusplus -diff --git a/plugins/ima.c b/plugins/ima.c -index fe6d3ad7f..9c28a41a3 100644 ---- a/plugins/ima.c -+++ b/plugins/ima.c -@@ -39,7 +39,7 @@ static int check_zero_hdr(const unsigned char *fsig, size_t siglen) +diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c +index 7ac44f0d0..1ff50c30f 100644 +--- a/plugins/fapolicyd.c ++++ b/plugins/fapolicyd.c +@@ -145,7 +145,8 @@ static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name, + } + + static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, +- const char *path, const char *dest, ++ int fd, const char *path, ++ const char *dest, + mode_t file_mode, rpmFsmOp op) + { + /* not ready */ +--- a/plugins/ima.c 2020-04-28 14:50:11.835399269 +0200 ++++ b/plugins/ima.c 2023-12-13 11:19:58.835948660 +0100 +@@ -39,7 +39,7 @@ return (memcmp(fsig, &zero_hdr, sizeof(zero_hdr)) == 0); } @@ -89,39 +101,26 @@ index fe6d3ad7f..9c28a41a3 100644 const char *path, const char *dest, mode_t file_mode, rpmFsmOp op) -@@ -63,7 +63,12 @@ static rpmRC ima_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, +@@ -63,8 +63,14 @@ fsig = rpmfiFSignature(fi, &len); if (fsig && (check_zero_hdr(fsig, len) == 0)) { - if (lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0) < 0) { +- rpmlog(RPMLOG_ERR, + int xx; + if (fd >= 0) + xx = fsetxattr(fd, XATTR_NAME_IMA, fsig, len, 0); + else + xx = lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0); + if (xx < 0) { - rpmlog(RPMLOG_ERR, ++ int is_err = errno != EOPNOTSUPP; ++ rpmlog(is_err?RPMLOG_ERR:RPMLOG_DEBUG, "ima: could not apply signature on '%s': %s\n", path, strerror(errno)); -diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c -index 7ac44f0d0..1ff50c30f 100644 ---- a/plugins/fapolicyd.c -+++ b/plugins/fapolicyd.c -@@ -145,7 +145,8 @@ static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name, - } - - static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, -- const char *path, const char *dest, -+ int fd, const char *path, -+ const char *dest, - mode_t file_mode, rpmFsmOp op) - { - /* not ready */ -diff --git a/plugins/selinux.c b/plugins/selinux.c -index 32c3b7529..a7f20aeca 100644 ---- a/plugins/selinux.c -+++ b/plugins/selinux.c -@@ -149,7 +149,7 @@ static rpmRC selinux_scriptlet_fork_post(rpmPlugin plugin, + rc = RPMRC_FAIL; +--- a/plugins/selinux.c 2023-12-13 11:21:54.935009141 +0100 ++++ b/plugins/selinux.c 2023-12-13 11:22:23.172510285 +0100 +@@ -149,7 +149,7 @@ return rc; } @@ -130,7 +129,7 @@ index 32c3b7529..a7f20aeca 100644 const char *path, const char *dest, mode_t file_mode, rpmFsmOp op) { -@@ -159,14 +159,17 @@ static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, +@@ -159,14 +159,17 @@ if (sehandle && !XFA_SKIPPING(action)) { security_context_t scon = NULL; if (selabel_lookup_raw(sehandle, &scon, dest, file_mode) == 0) { @@ -152,6 +151,3 @@ index 32c3b7529..a7f20aeca 100644 freecon(scon); } else { --- -2.41.0 - diff --git a/0001-Print-full-path-if-file-removal-fails.patch b/0001-Print-full-path-if-file-removal-fails.patch new file mode 100644 index 0000000..266bd69 --- /dev/null +++ b/0001-Print-full-path-if-file-removal-fails.patch @@ -0,0 +1,32 @@ +From f1503ab6e898430b80017c0f8347860f3a74d5bb Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Mon, 11 Dec 2023 15:50:15 +0100 +Subject: [PATCH] Print full path if file removal fails + +For normal debug output the basename of the files are sufficient as when +debugging is enabled the directories are also printed. But here the +warning is given without a debug flag so we need the full context right +there. +--- + lib/fsm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/fsm.c b/lib/fsm.c +index fcd764648..2189bd84c 100644 +--- a/lib/fsm.c ++++ b/lib/fsm.c +@@ -1174,9 +1174,9 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files, + + if (rc) { + int lvl = strict_erasures ? RPMLOG_ERR : RPMLOG_WARNING; +- rpmlog(lvl, _("%s %s: remove failed: %s\n"), ++ rpmlog(lvl, _("%s %s%s: remove failed: %s\n"), + S_ISDIR(fp->sb.st_mode) ? _("directory") : _("file"), +- fp->fpath, strerror(errno)); ++ rpmfiDN(fi), fp->fpath, strerror(errno)); + } + } + +-- +2.43.0 + diff --git a/rpm.spec b/rpm.spec index aa07aea..a52c767 100644 --- a/rpm.spec +++ b/rpm.spec @@ -32,7 +32,7 @@ %global rpmver 4.14.3 #global snapver rc2 -%global rel 30 +%global rel 31 %global srcver %{version}%{?snapver:-%{snapver}} %global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x} @@ -125,6 +125,10 @@ Patch170: 0001-Add-optional-callback-on-directory-changes-during-rp.patch Patch171: 0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch Patch172: 0001-Swap-over-to-dirfd-basename-based-operation-within-t.patch Patch173: 0001-Use-file-state-machine-from-rpm-4.19.patch +Patch174: 0001-Emit-full-paths-for-file-disposition-diagnostics-on-.patch +Patch175: 0001-Fix-wrong-return-code-on-O_DIRECTORY-open-of-invalid.patch +Patch176: 0001-Print-full-path-if-file-removal-fails.patch +Patch177: 0001-Don-t-warn-about-missing-user-group-on-skipped-files.patch # Python 3 string API sanity Patch500: 0001-In-Python-3-return-all-our-string-data-as-surrogate-.patch @@ -707,7 +711,7 @@ make check || cat tests/rpmtests.log %doc doc/librpm/html/* %changelog -* Fri Nov 10 2023 Florian Festi - 4.14.3-30 +* Tue Dec 12 2023 Florian Festi - 4.14.3-31 - Backport file handling code from rpm-4.19 to fix CVE-2021-35937, CVE-2021-35938 and CVE-2021-35939