Backport file handling code from rpm-4.19
Fixes CVE-2021-35937, CVE-2021-35938 and CVE-2021-35939 Patches include small changes found in other patches. See RHEL-8.10 patch set for intermediate steps. Resolves: RHEL-14598 RHEL-14599 RHEL-14600
This commit is contained in:
parent
f3da53eb6d
commit
94360abd84
107
0001-Add-optional-callback-on-directory-changes-during-rp.patch
Normal file
107
0001-Add-optional-callback-on-directory-changes-during-rp.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 186e0ab025b9ad92d900697f611633a6f6162f3b Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Wed, 9 Feb 2022 14:47:14 +0200
|
||||
Subject: [PATCH] Add optional callback on directory changes during rpmfi
|
||||
iteration
|
||||
|
||||
Internal only for now in case we need to fiddle with the API some more,
|
||||
but no reason this couldn't be made public later.
|
||||
---
|
||||
lib/rpmfi.c | 24 ++++++++++++++++++++----
|
||||
lib/rpmfi_internal.h | 17 +++++++++++++++++
|
||||
2 files changed, 37 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
|
||||
index aec8220a3..6c631fdb5 100644
|
||||
--- a/lib/rpmfi.c
|
||||
+++ b/lib/rpmfi.c
|
||||
@@ -53,6 +53,9 @@ struct rpmfi_s {
|
||||
int intervalStart; /*!< Start of iterating interval. */
|
||||
int intervalEnd; /*!< End of iterating interval. */
|
||||
|
||||
+ rpmfiChdirCb onChdir; /*!< Callback for directory changes */
|
||||
+ void *onChdirData; /*!< Caller private callback data */
|
||||
+
|
||||
rpmfiles files; /*!< File info set */
|
||||
rpmcpio_t archive; /*!< Archive with payload */
|
||||
unsigned char * found; /*!< Bit field of files found in the archive */
|
||||
@@ -298,11 +301,16 @@ rpm_count_t rpmfiDC(rpmfi fi)
|
||||
return (fi != NULL ? rpmfilesDC(fi->files) : 0);
|
||||
}
|
||||
|
||||
-#ifdef NOTYET
|
||||
-int rpmfiDI(rpmfi fi)
|
||||
+int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data)
|
||||
{
|
||||
+ int rc = -1;
|
||||
+ if (fi != NULL) {
|
||||
+ fi->onChdir = cb;
|
||||
+ fi->onChdirData = data;
|
||||
+ rc = 0;
|
||||
+ }
|
||||
+ return rc;
|
||||
}
|
||||
-#endif
|
||||
|
||||
int rpmfiFX(rpmfi fi)
|
||||
{
|
||||
@@ -314,9 +322,17 @@ int rpmfiSetFX(rpmfi fi, int fx)
|
||||
int i = -1;
|
||||
|
||||
if (fi != NULL && fx >= 0 && fx < rpmfilesFC(fi->files)) {
|
||||
+ int dx = fi->j;
|
||||
i = fi->i;
|
||||
fi->i = fx;
|
||||
fi->j = rpmfilesDI(fi->files, fi->i);
|
||||
+ i = fi->i;
|
||||
+
|
||||
+ if (fi->j != dx && fi->onChdir) {
|
||||
+ int chrc = fi->onChdir(fi, fi->onChdirData);
|
||||
+ if (chrc < 0)
|
||||
+ i = chrc;
|
||||
+ }
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -1682,9 +1698,9 @@ static rpmfi initIter(rpmfiles files, int itype, int link)
|
||||
if (files && itype>=0 && itype<=RPMFILEITERMAX) {
|
||||
fi = xcalloc(1, sizeof(*fi));
|
||||
fi->i = -1;
|
||||
+ fi->j = -1;
|
||||
fi->files = link ? rpmfilesLink(files) : files;
|
||||
fi->next = nextfuncs[itype];
|
||||
- fi->i = -1;
|
||||
if (itype == RPMFI_ITER_BACK) {
|
||||
fi->i = rpmfilesFC(fi->files);
|
||||
} else if (itype >=RPMFI_ITER_READ_ARCHIVE
|
||||
diff --git a/lib/rpmfi_internal.h b/lib/rpmfi_internal.h
|
||||
index dccc6ccbe..37f1d45f5 100644
|
||||
--- a/lib/rpmfi_internal.h
|
||||
+++ b/lib/rpmfi_internal.h
|
||||
@@ -13,6 +13,23 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
+/** \ingroup rpmfi
|
||||
+ * Callback on file iterator directory changes
|
||||
+ * @param fi file info
|
||||
+ * @param data caller private callback data
|
||||
+ * @return 0 on success, < 0 on error (to stop iteration)
|
||||
+ */
|
||||
+typedef int (*rpmfiChdirCb)(rpmfi fi, void *data);
|
||||
+
|
||||
+/** \ingroup rpmfi
|
||||
+ * Set a callback for directory changes during iteration.
|
||||
+ * @param fi file info
|
||||
+ * @param cb callback function
|
||||
+ * @param data caller private callback data
|
||||
+ * @return string pool handle (weak reference)
|
||||
+ */
|
||||
+int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data);
|
||||
+
|
||||
/** \ingroup rpmfi
|
||||
* Return file info set string pool handle
|
||||
* @param fi file info
|
||||
--
|
||||
2.41.0
|
||||
|
35
0001-Eliminate-code-duplication-from-rpmfiNext.patch
Normal file
35
0001-Eliminate-code-duplication-from-rpmfiNext.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 0bc13d75b5883ccf4d6579f7a60fb1badd104649 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Thu, 10 Feb 2022 10:23:22 +0200
|
||||
Subject: [PATCH] Eliminate code duplication from rpmfiNext()
|
||||
|
||||
Now that we can, let rpmfiSetFX() take care of the details.
|
||||
---
|
||||
lib/rpmfi.c | 11 ++---------
|
||||
1 file changed, 2 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
|
||||
index 689ead2c5..aec8220a3 100644
|
||||
--- a/lib/rpmfi.c
|
||||
+++ b/lib/rpmfi.c
|
||||
@@ -856,15 +856,8 @@ int rpmfiNext(rpmfi fi)
|
||||
next = fi->next(fi);
|
||||
} while (next == RPMERR_ITER_SKIP);
|
||||
|
||||
- if (next >= 0 && next < rpmfilesFC(fi->files)) {
|
||||
- fi->i = next;
|
||||
- fi->j = rpmfilesDI(fi->files, fi->i);
|
||||
- } else {
|
||||
- fi->i = -1;
|
||||
- if (next >= 0) {
|
||||
- next = -1;
|
||||
- }
|
||||
- }
|
||||
+ if (next >= 0)
|
||||
+ next = rpmfiSetFX(fi, next);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
--
|
||||
2.41.0
|
||||
|
158
0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch
Normal file
158
0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch
Normal file
@ -0,0 +1,158 @@
|
||||
From ac7b0dbd5a18d2c57a942ca14ac856b8047425ff Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Tue, 15 Feb 2022 10:43:13 +0200
|
||||
Subject: [PATCH] Pass file descriptor to file prepare plugin hook, use when
|
||||
possible
|
||||
|
||||
Sadly the thing that allegedly makes things better mostly just makes
|
||||
things more complicated as symlinks can't be opened, so we'll now have
|
||||
to deal with both cases in plugins too. To make matters worse, most
|
||||
APIs out there support either an fd or a path, but very few support
|
||||
the *at() style dirfd + basename approach so plugins are stuck with
|
||||
absolute paths for now.
|
||||
|
||||
This is of course a plugin API/ABI change too.
|
||||
---
|
||||
lib/rpmplugin.h | 2 +-
|
||||
lib/rpmplugins.c | 4 ++--
|
||||
lib/rpmplugins.h | 3 ++-
|
||||
plugins/ima.c | 9 +++++++--
|
||||
plugins/selinux.c | 13 ++++++++-----
|
||||
5 files changed, 20 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/lib/rpmplugin.h b/lib/rpmplugin.h
|
||||
index fd81aec8d..fab4b3e83 100644
|
||||
--- a/lib/rpmplugin.h
|
||||
+++ b/lib/rpmplugin.h
|
||||
@@ -57,7 +57,7 @@ typedef rpmRC (*plugin_fsm_file_post_func)(rpmPlugin plugin, rpmfi fi,
|
||||
const char* path, mode_t file_mode,
|
||||
rpmFsmOp op, int res);
|
||||
typedef rpmRC (*plugin_fsm_file_prepare_func)(rpmPlugin plugin, rpmfi fi,
|
||||
- const char* path,
|
||||
+ int fd, const char* path,
|
||||
const char *dest,
|
||||
mode_t file_mode, rpmFsmOp op);
|
||||
|
||||
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
|
||||
index 65e684e84..923084b78 100644
|
||||
--- a/lib/rpmplugins.c
|
||||
+++ b/lib/rpmplugins.c
|
||||
@@ -384,7 +384,7 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char *path,
|
||||
}
|
||||
|
||||
rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
|
||||
- const char *path, const char *dest,
|
||||
+ int fd, const char *path, const char *dest,
|
||||
mode_t file_mode, rpmFsmOp op)
|
||||
{
|
||||
plugin_fsm_file_prepare_func hookFunc;
|
||||
@@ -394,7 +394,7 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
|
||||
for (i = 0; i < plugins->count; i++) {
|
||||
rpmPlugin plugin = plugins->plugins[i];
|
||||
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_prepare);
|
||||
- if (hookFunc && hookFunc(plugin, fi, path, dest, file_mode, op) == RPMRC_FAIL) {
|
||||
+ if (hookFunc && hookFunc(plugin, fi, fd, path, dest, file_mode, op) == RPMRC_FAIL) {
|
||||
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_prepare failed\n", plugin->name);
|
||||
rc = RPMRC_FAIL;
|
||||
}
|
||||
diff --git a/lib/rpmplugins.h b/lib/rpmplugins.h
|
||||
index 39762c376..ddf5d7048 100644
|
||||
--- a/lib/rpmplugins.h
|
||||
+++ b/lib/rpmplugins.h
|
||||
@@ -156,6 +156,7 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char* path,
|
||||
* permissions etc, but before committing file to destination path.
|
||||
* @param plugins plugins structure
|
||||
* @param fi file info iterator (or NULL)
|
||||
+ * @param fd file descriptor (or -1 if not available)
|
||||
* @param path file object current path
|
||||
* @param dest file object destination path
|
||||
* @param mode file object mode
|
||||
@@ -164,7 +165,7 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char* path,
|
||||
*/
|
||||
RPM_GNUC_INTERNAL
|
||||
rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
|
||||
- const char *path, const char *dest,
|
||||
+ int fd, const char *path, const char *dest,
|
||||
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)
|
||||
return (memcmp(fsig, &zero_hdr, sizeof(zero_hdr)) == 0);
|
||||
}
|
||||
|
||||
-static rpmRC ima_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
|
||||
+static rpmRC ima_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, int fd,
|
||||
const char *path,
|
||||
const char *dest,
|
||||
mode_t file_mode, rpmFsmOp op)
|
||||
@@ -68,8 +68,13 @@
|
||||
|
||||
fsig = rpmfiFSignature(fi, &len);
|
||||
if (fsig && (check_zero_hdr(fsig, len) == 0)) {
|
||||
- if (lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0) < 0) {
|
||||
- int is_err = errno != EOPNOTSUPP;
|
||||
+ 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) {
|
||||
+ int is_err = xx != 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,
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
|
||||
+static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, int fd,
|
||||
const char *path, const char *dest,
|
||||
mode_t file_mode, rpmFsmOp op)
|
||||
{
|
||||
@@ -194,13 +194,17 @@
|
||||
if (sehandle && !XFA_SKIPPING(action)) {
|
||||
char *scon = NULL;
|
||||
if (selabel_lookup_raw(sehandle, &scon, dest, file_mode) == 0) {
|
||||
- int conrc = lsetfilecon(path, scon);
|
||||
+ int conrc;
|
||||
+ if (fd >= 0)
|
||||
+ conrc = fsetfilecon(fd, scon);
|
||||
+ else
|
||||
+ conrc = lsetfilecon(path, scon);
|
||||
|
||||
if (conrc == 0 || (conrc < 0 && errno == EOPNOTSUPP))
|
||||
rc = RPMRC_OK;
|
||||
|
||||
- rpmlog(loglvl(rc != RPMRC_OK), "lsetfilecon: (%s, %s) %s\n",
|
||||
- path, scon, (conrc < 0 ? strerror(errno) : ""));
|
||||
+ rpmlog(loglvl(rc != RPMRC_OK), "lsetfilecon: (%d %s, %s) %s\n",
|
||||
+ fd, path, scon, (conrc < 0 ? strerror(errno) : ""));
|
||||
|
||||
freecon(scon);
|
||||
} else {
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,90 @@
|
||||
From 6dd62720fe84f7e2ad902c915b952fc0b29e3dcd Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Tue, 15 Feb 2022 11:34:37 +0200
|
||||
Subject: [PATCH] Swap over to dirfd+basename based operation within the fsm
|
||||
|
||||
Within fsm this is just a matter of adjusting error messages to include
|
||||
the directory... if it only wasn't for the plugins requiring absolute
|
||||
paths for outside users. For the plugins, we need to assemble absolute
|
||||
paths as needed, both in ensureDir() and plugin file slots.
|
||||
---
|
||||
lib/rpmplugins.c | 20 +++++++++++++++++---
|
||||
2 files changed, 36 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
|
||||
index 703368c0d..f06fd7895 100644
|
||||
--- a/lib/rpmplugins.c
|
||||
+++ b/lib/rpmplugins.c
|
||||
@@ -350,21 +350,31 @@ rpmRC rpmpluginsCallScriptletPost(rpmPlugins plugins, const char *s_name, int ty
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static char *abspath(rpmfi fi, const char *path)
|
||||
+{
|
||||
+ if (*path == '/')
|
||||
+ return xstrdup(path);
|
||||
+ else
|
||||
+ return rstrscat(NULL, rpmfiDN(fi), path, NULL);
|
||||
+}
|
||||
+
|
||||
rpmRC rpmpluginsCallFsmFilePre(rpmPlugins plugins, rpmfi fi, const char *path,
|
||||
mode_t file_mode, rpmFsmOp op)
|
||||
{
|
||||
plugin_fsm_file_pre_func hookFunc;
|
||||
int i;
|
||||
rpmRC rc = RPMRC_OK;
|
||||
+ char *apath = abspath(fi, path);
|
||||
|
||||
for (i = 0; i < plugins->count; i++) {
|
||||
rpmPlugin plugin = plugins->plugins[i];
|
||||
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_pre);
|
||||
- if (hookFunc && hookFunc(plugin, fi, path, file_mode, op) == RPMRC_FAIL) {
|
||||
+ if (hookFunc && hookFunc(plugin, fi, apath, file_mode, op) == RPMRC_FAIL) {
|
||||
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_pre failed\n", plugin->name);
|
||||
rc = RPMRC_FAIL;
|
||||
}
|
||||
}
|
||||
+ free(apath);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -375,14 +385,16 @@ rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char *path,
|
||||
plugin_fsm_file_post_func hookFunc;
|
||||
int i;
|
||||
rpmRC rc = RPMRC_OK;
|
||||
+ char *apath = abspath(fi, path);
|
||||
|
||||
for (i = 0; i < plugins->count; i++) {
|
||||
rpmPlugin plugin = plugins->plugins[i];
|
||||
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_post);
|
||||
- if (hookFunc && hookFunc(plugin, fi, path, file_mode, op, res) == RPMRC_FAIL) {
|
||||
+ if (hookFunc && hookFunc(plugin, fi, apath, file_mode, op, res) == RPMRC_FAIL) {
|
||||
rpmlog(RPMLOG_WARNING, "Plugin %s: hook fsm_file_post failed\n", plugin->name);
|
||||
}
|
||||
}
|
||||
+ free(apath);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -394,15 +406,17 @@ rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
|
||||
plugin_fsm_file_prepare_func hookFunc;
|
||||
int i;
|
||||
rpmRC rc = RPMRC_OK;
|
||||
+ char *apath = abspath(fi, path);
|
||||
|
||||
for (i = 0; i < plugins->count; i++) {
|
||||
rpmPlugin plugin = plugins->plugins[i];
|
||||
RPMPLUGINS_SET_HOOK_FUNC(fsm_file_prepare);
|
||||
- if (hookFunc && hookFunc(plugin, fi, fd, path, dest, file_mode, op) == RPMRC_FAIL) {
|
||||
+ if (hookFunc && hookFunc(plugin, fi, fd, apath, dest, file_mode, op) == RPMRC_FAIL) {
|
||||
rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_prepare failed\n", plugin->name);
|
||||
rc = RPMRC_FAIL;
|
||||
}
|
||||
}
|
||||
+ free(apath);
|
||||
|
||||
return rc;
|
||||
}
|
||||
--
|
||||
2.41.0
|
||||
|
1631
0001-Use-file-state-machine-from-rpm-4.19.patch
Normal file
1631
0001-Use-file-state-machine-from-rpm-4.19.patch
Normal file
File diff suppressed because it is too large
Load Diff
11
rpm.spec
11
rpm.spec
@ -32,7 +32,7 @@
|
||||
|
||||
%global rpmver 4.16.1.3
|
||||
#global snapver rc1
|
||||
%global rel 25
|
||||
%global rel 26
|
||||
%global sover 9
|
||||
|
||||
%global srcver %{rpmver}%{?snapver:-%{snapver}}
|
||||
@ -94,6 +94,12 @@ Patch122: rpm-4.16.1.3-Support-long-languages-names-for-QT.patch
|
||||
Patch123: rpm-4.14.3-rpm2archive-parse-popt-options.patch
|
||||
Patch124: rpm-4.14.3-rpm2archive-Don-t-print-usage.patch
|
||||
Patch125: rpm-4.16.1.3-IMA-without-xattr.patch
|
||||
# Backport fsm to fix CVEs
|
||||
Patch126: 0001-Eliminate-code-duplication-from-rpmfiNext.patch
|
||||
Patch127: 0001-Add-optional-callback-on-directory-changes-during-rp.patch
|
||||
Patch128: 0001-Pass-file-descriptor-to-file-prepare-plugin-hook-use.patch
|
||||
Patch129: 0001-Swap-over-to-dirfd-basename-based-operation-within-t.patch
|
||||
Patch130: 0001-Use-file-state-machine-from-rpm-4.19.patch
|
||||
|
||||
# These are not yet upstream
|
||||
Patch906: rpm-4.7.1-geode-i686.patch
|
||||
@ -643,6 +649,9 @@ fi
|
||||
%doc doc/librpm/html/*
|
||||
|
||||
%changelog
|
||||
* Fri Nov 10 2023 Florian Festi <ffesti@redhat.com> - 4.16.1.3-26
|
||||
- Backport file handling code from rpm-4.19 to fix CVE-2021-35937,
|
||||
CVE-2021-35938 and CVE-2021-35939
|
||||
|
||||
* Fri Jun 30 2023 Florian Festi <ffesti@redhat.com> - 4.16.1.3-25
|
||||
- Followup on #2166383
|
||||
|
Loading…
Reference in New Issue
Block a user