!150 fix CVE-2021-35937 CVE-2021-35938 CVE-2021-35939
From: @renxichen Reviewed-by: @xujing99 Signed-off-by: @xujing99
This commit is contained in:
commit
b4bb964fff
@ -0,0 +1,105 @@
|
|||||||
|
From fb13f7fd9eff012cb7b9dbf94ac5381c69404055 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, 40 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
|
||||||
|
index 4673fbb..e8e7d08 100644
|
||||||
|
--- a/lib/rpmfi.c
|
||||||
|
+++ b/lib/rpmfi.c
|
||||||
|
@@ -55,6 +55,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 */
|
||||||
|
@@ -312,6 +312,17 @@ int rpmfiDI(rpmfi fi)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data)
|
||||||
|
+{
|
||||||
|
+ int rc = -1;
|
||||||
|
+ if (fi != NULL) {
|
||||||
|
+ fi->onChdir = cb;
|
||||||
|
+ fi->onChdirData = data;
|
||||||
|
+ rc = 0;
|
||||||
|
+ }
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int rpmfiFX(rpmfi fi)
|
||||||
|
{
|
||||||
|
return (fi != NULL ? fi->i : -1);
|
||||||
|
@@ -313,9 +327,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;
|
||||||
|
}
|
||||||
|
@@ -1780,9 +1802,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 dccc6ccb..37f1d45 100644
|
||||||
|
--- a/lib/rpmfi_internal.h
|
||||||
|
+++ b/lib/rpmfi_internal.h
|
||||||
|
@@ -14,6 +14,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
|
||||||
|
* @return string pool handle (weak reference)
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
129
backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
Normal file
129
backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
From bbc270d78fb361bd78eac9a9117070caeb537d4a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Panu Matilainen <pmatilai@redhat.com>
|
||||||
|
Date: Mon, 14 Feb 2022 12:35:58 +0200
|
||||||
|
Subject: [PATCH] Bury rpmio FD use to fsmUnpack()
|
||||||
|
|
||||||
|
fsmUnpack() is the only place in FSM that needs to deal with rpmio FD
|
||||||
|
types, everywhere else they are nothing but a hindrance that need to
|
||||||
|
be converted to OS level descriptors for use. Better deal with OS
|
||||||
|
level descriptors to begin with.
|
||||||
|
---
|
||||||
|
lib/fsm.c | 37 ++++++++++++++++---------------------
|
||||||
|
1 file changed, 16 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||||
|
index 13b1142..b019f57 100644
|
||||||
|
--- a/lib/fsm.c
|
||||||
|
+++ b/lib/fsm.c
|
||||||
|
@@ -110,14 +110,14 @@ static int fsmSetFCaps(const char *path, const char *captxt)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmClose(FD_t *wfdp)
|
||||||
|
+static int fsmClose(int *wfdp)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
- if (wfdp && *wfdp) {
|
||||||
|
+ if (wfdp && *wfdp >= 0) {
|
||||||
|
int myerrno = errno;
|
||||||
|
static int oneshot = 0;
|
||||||
|
static int flush_io = 0;
|
||||||
|
- int fdno = Fileno(*wfdp);
|
||||||
|
+ int fdno = *wfdp;
|
||||||
|
|
||||||
|
if (!oneshot) {
|
||||||
|
flush_io = (rpmExpandNumeric("%{?_flush_io}") > 0);
|
||||||
|
@@ -126,61 +126,56 @@ static int fsmClose(FD_t *wfdp)
|
||||||
|
if (flush_io) {
|
||||||
|
fsync(fdno);
|
||||||
|
}
|
||||||
|
- if (Fclose(*wfdp))
|
||||||
|
+ if (close(fdno))
|
||||||
|
rc = RPMERR_CLOSE_FAILED;
|
||||||
|
|
||||||
|
if (_fsm_debug) {
|
||||||
|
rpmlog(RPMLOG_DEBUG, " %8s ([%d]) %s\n", __func__,
|
||||||
|
fdno, (rc < 0 ? strerror(errno) : ""));
|
||||||
|
}
|
||||||
|
- *wfdp = NULL;
|
||||||
|
+ *wfdp = -1;
|
||||||
|
errno = myerrno;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmOpen(FD_t *wfdp, int dirfd, const char *dest)
|
||||||
|
+static int fsmOpen(int *wfdp, int dirfd, const char *dest)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
/* Create the file with 0200 permissions (write by owner). */
|
||||||
|
int fd = openat(dirfd, dest, O_WRONLY|O_EXCL|O_CREAT, 0200);
|
||||||
|
|
||||||
|
- if (fd >= 0) {
|
||||||
|
- *wfdp = fdDup(fd);
|
||||||
|
- close(fd);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (fd < 0 || Ferror(*wfdp))
|
||||||
|
+ if (fd < 0)
|
||||||
|
rc = RPMERR_OPEN_FAILED;
|
||||||
|
|
||||||
|
if (_fsm_debug) {
|
||||||
|
rpmlog(RPMLOG_DEBUG, " %8s (%s [%d]) %s\n", __func__,
|
||||||
|
- dest, Fileno(*wfdp), (rc < 0 ? strerror(errno) : ""));
|
||||||
|
+ dest, fd, (rc < 0 ? strerror(errno) : ""));
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- if (rc)
|
||||||
|
- fsmClose(wfdp);
|
||||||
|
+ *wfdp = fd;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmUnpack(rpmfi fi, FD_t fd, rpmpsm psm, int nodigest)
|
||||||
|
+static int fsmUnpack(rpmfi fi, int fdno, rpmpsm psm, int nodigest)
|
||||||
|
{
|
||||||
|
+ FD_t fd = fdDup(fdno);
|
||||||
|
int rc = rpmfiArchiveReadToFilePsm(fi, fd, nodigest, psm);
|
||||||
|
if (_fsm_debug) {
|
||||||
|
rpmlog(RPMLOG_DEBUG, " %8s (%s %" PRIu64 " bytes [%d]) %s\n", __func__,
|
||||||
|
rpmfiFN(fi), rpmfiFSize(fi), Fileno(fd),
|
||||||
|
(rc < 0 ? strerror(errno) : ""));
|
||||||
|
}
|
||||||
|
+ Fclose(fd);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
rpmpsm psm, int nodigest,
|
||||||
|
- struct filedata_s ** firstlink, FD_t *firstlinkfile)
|
||||||
|
+ struct filedata_s ** firstlink, int *firstlinkfile)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
- FD_t fd = NULL;
|
||||||
|
+ int fd = -1;
|
||||||
|
|
||||||
|
if (*firstlink == NULL) {
|
||||||
|
/* First encounter, open file for writing */
|
||||||
|
@@ -206,7 +201,7 @@ static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
if (*firstlink) {
|
||||||
|
fp->setmeta = 1;
|
||||||
|
*firstlink = NULL;
|
||||||
|
- *firstlinkfile = NULL;
|
||||||
|
+ *firstlinkfile = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -811,7 +806,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
int fc = rpmfilesFC(files);
|
||||||
|
int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
|
||||||
|
int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
|
||||||
|
- FD_t firstlinkfile = NULL;
|
||||||
|
+ int firstlinkfile = -1;
|
||||||
|
char *tid = NULL;
|
||||||
|
struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
||||||
|
struct filedata_s *firstlink = NULL;
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
281
backport-CVE-2021-35937-CVE-2021-35939.patch
Normal file
281
backport-CVE-2021-35937-CVE-2021-35939.patch
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
From 96ec957e281220f8e137a2d5eb23b83a6377d556 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Panu Matilainen <pmatilai@redhat.com>
|
||||||
|
Date: Thu, 10 Feb 2022 14:32:43 +0200
|
||||||
|
Subject: [PATCH] Validate intermediate symlinks during installation,
|
||||||
|
CVE-2021-35939
|
||||||
|
|
||||||
|
Whenever directory changes during unpacking, walk the entire tree from
|
||||||
|
starting from / and validate any symlinks crossed, fail the install
|
||||||
|
on invalid links.
|
||||||
|
|
||||||
|
This is the first of step of many towards securing our file operations
|
||||||
|
against local tamperers and besides plugging that one CVE, paves the way
|
||||||
|
for the next step by adding the necessary directory fd tracking.
|
||||||
|
This also bumps the rpm OS requirements to a whole new level by requiring
|
||||||
|
the *at() family of calls from POSIX-1.2008.
|
||||||
|
|
||||||
|
This necessarily does a whole lot of huffing and puffing we previously
|
||||||
|
did not do. It should be possible to cache secure (ie root-owned)
|
||||||
|
directory structures to avoid validating everything a million times
|
||||||
|
but for now, just keeping things simple.
|
||||||
|
---
|
||||||
|
INSTALL | 2 +
|
||||||
|
configure.ac | 3 +-
|
||||||
|
lib/fsm.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
3 files changed, 142 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/INSTALL b/INSTALL
|
||||||
|
index 677ef88..961a160 100644
|
||||||
|
--- a/INSTALL
|
||||||
|
+++ b/INSTALL
|
||||||
|
@@ -103,6 +103,8 @@ option to configure). For GCC, OpenMP 4.5 is fully supported since GCC 6.1,
|
||||||
|
which is available from
|
||||||
|
http://www.gnu.org/
|
||||||
|
|
||||||
|
+Rpm requires a POSIX.1-2008 level operating system.
|
||||||
|
+
|
||||||
|
To compile RPM:
|
||||||
|
--------------
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 3ee3407..0099e5f 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -580,7 +580,8 @@ AC_CHECK_FUNCS([secure_getenv __secure_getenv])
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS(
|
||||||
|
[mkstemp getcwd basename dirname realpath setenv unsetenv regcomp lchown \
|
||||||
|
- utimes getline localtime_r statvfs getaddrinfo ],
|
||||||
|
+ utimes getline localtime_r statvfs getaddrinfo \
|
||||||
|
+ openat mkdirat fstatat ],
|
||||||
|
[], [AC_MSG_ERROR([function required by rpm])])
|
||||||
|
|
||||||
|
AC_LIBOBJ(fnmatch)
|
||||||
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||||
|
index 9118983..b6b152a 100644
|
||||||
|
--- a/lib/fsm.c
|
||||||
|
+++ b/lib/fsm.c
|
||||||
|
@@ -8,6 +8,7 @@
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <utime.h>
|
||||||
|
#include <errno.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
#if WITH_CAP
|
||||||
|
#include <sys/capability.h>
|
||||||
|
#endif
|
||||||
|
@@ -20,6 +21,7 @@
|
||||||
|
#include "rpmio/rpmio_internal.h" /* fdInit/FiniDigest */
|
||||||
|
#include "lib/fsm.h"
|
||||||
|
#include "lib/rpmte_internal.h" /* XXX rpmfs */
|
||||||
|
+#include "lib/rpmfi_internal.h" /* rpmfiSetOnChdir */
|
||||||
|
#include "lib/rpmplugins.h" /* rpm plugins hooks */
|
||||||
|
#include "lib/rpmug.h"
|
||||||
|
|
||||||
|
@@ -406,17 +408,118 @@ static int fsmRmdir(const char *path)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmMkdir(const char *path, mode_t mode)
|
||||||
|
+static int fsmMkdir(int dirfd, const char *path, mode_t mode)
|
||||||
|
{
|
||||||
|
- int rc = mkdir(path, (mode & 07777));
|
||||||
|
+ int rc = mkdirat(dirfd, path, (mode & 07777));
|
||||||
|
if (_fsm_debug)
|
||||||
|
- rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n", __func__,
|
||||||
|
- path, (unsigned)(mode & 07777),
|
||||||
|
+ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%04o) %s\n", __func__,
|
||||||
|
+ dirfd, path, (unsigned)(mode & 07777),
|
||||||
|
(rc < 0 ? strerror(errno) : ""));
|
||||||
|
if (rc < 0) rc = RPMERR_MKDIR_FAILED;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int fsmOpenat(int dirfd, const char *path, int flags)
|
||||||
|
+{
|
||||||
|
+ struct stat lsb, sb;
|
||||||
|
+ int sflags = flags | O_NOFOLLOW;
|
||||||
|
+ int fd = openat(dirfd, path, sflags);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Only ever follow symlinks by root or target owner. Since we can't
|
||||||
|
+ * open the symlink itself, the order matters: we stat the link *after*
|
||||||
|
+ * opening the target, and if the link ownership changed between the calls
|
||||||
|
+ * it could've only been the link owner or root.
|
||||||
|
+ */
|
||||||
|
+ if (fd < 0 && errno == ELOOP && flags != sflags) {
|
||||||
|
+ int ffd = openat(dirfd, path, flags);
|
||||||
|
+ if (ffd >= 0 && fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) {
|
||||||
|
+ if (fstat(ffd, &sb) == 0) {
|
||||||
|
+ if (lsb.st_uid == 0 || lsb.st_uid == sb.st_uid) {
|
||||||
|
+ fd = ffd;
|
||||||
|
+ } else {
|
||||||
|
+ close(ffd);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return fd;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int fsmDoMkDir(rpmPlugins plugins, int dirfd, const char *dn,
|
||||||
|
+ int owned, mode_t mode)
|
||||||
|
+{
|
||||||
|
+ int rc;
|
||||||
|
+ rpmFsmOp op = (FA_CREATE);
|
||||||
|
+ if (!owned)
|
||||||
|
+ op |= FAF_UNOWNED;
|
||||||
|
+
|
||||||
|
+ /* Run fsm file pre hook for all plugins */
|
||||||
|
+ rc = rpmpluginsCallFsmFilePre(plugins, NULL, dn, mode, op);
|
||||||
|
+
|
||||||
|
+ if (!rc)
|
||||||
|
+ rc = fsmMkdir(dirfd, dn, mode);
|
||||||
|
+
|
||||||
|
+ if (!rc) {
|
||||||
|
+ rc = rpmpluginsCallFsmFilePrepare(plugins, NULL, dn, dn, mode, op);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Run fsm file post hook for all plugins */
|
||||||
|
+ rpmpluginsCallFsmFilePost(plugins, NULL, dn, mode, op, rc);
|
||||||
|
+
|
||||||
|
+ if (!rc) {
|
||||||
|
+ rpmlog(RPMLOG_DEBUG,
|
||||||
|
+ "%s directory created with perms %04o\n",
|
||||||
|
+ dn, (unsigned)(mode & 07777));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ensureDir(rpmPlugins plugins, const char *p, int owned, int create)
|
||||||
|
+{
|
||||||
|
+ char *path = xstrdup(p);
|
||||||
|
+ char *dp = path;
|
||||||
|
+ char *sp = NULL, *bn;
|
||||||
|
+ int oflags = O_RDONLY;
|
||||||
|
+
|
||||||
|
+ int dirfd = fsmOpenat(-1, "/", oflags);
|
||||||
|
+ int fd = dirfd; /* special case of "/" */
|
||||||
|
+
|
||||||
|
+ while ((bn = strtok_r(dp, "/", &sp)) != NULL) {
|
||||||
|
+ struct stat sb;
|
||||||
|
+ fd = fsmOpenat(dirfd, bn, oflags);
|
||||||
|
+
|
||||||
|
+ if (fd < 0 && errno == ENOENT && create) {
|
||||||
|
+ mode_t mode = S_IFDIR | (_dirPerms & 07777);
|
||||||
|
+ if (fsmDoMkDir(plugins, dirfd, bn, owned, mode) == 0) {
|
||||||
|
+ fd = fsmOpenat(dirfd, bn, oflags|O_NOFOLLOW);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
|
||||||
|
+ close(fd);
|
||||||
|
+ errno = ENOTDIR;
|
||||||
|
+ fd = -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ close(dirfd);
|
||||||
|
+ if (fd >= 0) {
|
||||||
|
+ dirfd = fd;
|
||||||
|
+ } else {
|
||||||
|
+ dirfd = -1;
|
||||||
|
+ rpmlog(RPMLOG_ERR, _("failed to open dir %s of %s: %s\n"),
|
||||||
|
+ bn, p, strerror(errno));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dp = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free(path);
|
||||||
|
+ return dirfd;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int fsmMkfifo(const char *path, mode_t mode)
|
||||||
|
{
|
||||||
|
int rc = mkfifo(path, (mode & 07777));
|
||||||
|
@@ -507,7 +610,7 @@ static int fsmMkdirs(rpmfiles files, rpmfs fs, rpmPlugins plugins)
|
||||||
|
rc = rpmpluginsCallFsmFilePre(plugins, NULL, dn, mode, op);
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
|
- rc = fsmMkdir(dn, mode);
|
||||||
|
+ rc = fsmMkdir(-1, dn, mode);
|
||||||
|
|
||||||
|
if (!rc) {
|
||||||
|
rc = rpmpluginsCallFsmFilePrepare(plugins, NULL, dn, dn,
|
||||||
|
@@ -874,6 +977,21 @@ static void setFileState(rpmfs fs, int i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct diriter_s {
|
||||||
|
+ int dirfd;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int onChdir(rpmfi fi, void *data)
|
||||||
|
+{
|
||||||
|
+ struct diriter_s *di = data;
|
||||||
|
+
|
||||||
|
+ if (di->dirfd >= 0) {
|
||||||
|
+ close(di->dirfd);
|
||||||
|
+ di->dirfd = -1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
rpmpsm psm, char ** failedFile)
|
||||||
|
{
|
||||||
|
@@ -890,6 +1008,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
char *tid = NULL;
|
||||||
|
struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
||||||
|
struct filedata_s *firstlink = NULL;
|
||||||
|
+ struct diriter_s di = { -1 };
|
||||||
|
|
||||||
|
/* transaction id used for temporary path suffix while installing */
|
||||||
|
rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
|
||||||
|
@@ -932,6 +1051,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
rc = RPMERR_BAD_MAGIC;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
+ rpmfiSetOnChdir(fi, onChdir, &di);
|
||||||
|
|
||||||
|
/* Detect and create directories not explicitly in package. */
|
||||||
|
if (!rc)
|
||||||
|
@@ -1063,6 +1063,16 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
if (!fp->suffix) {
|
||||||
|
rc = fsmBackup(fi, fp->action);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (di.dirfd == -1) {
|
||||||
|
+ di.dirfd = ensureDir(plugins, rpmfiDN(fi), 0,
|
||||||
|
+ (fp->action == FA_CREATE));
|
||||||
|
+ if (di.dirfd == -1) {
|
||||||
|
+ rc = RPMERR_OPEN_FAILED;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Assume file does't exist when tmp suffix is in use */
|
||||||
|
if (!fp->suffix) {
|
||||||
|
rc = fsmVerify(fp->fpath, fi);
|
||||||
|
@@ -980,7 +1110,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
mode_t mode = fp->sb.st_mode;
|
||||||
|
mode &= ~07777;
|
||||||
|
mode |= 00700;
|
||||||
|
- rc = fsmMkdir(fp->fpath, mode);
|
||||||
|
+ rc = fsmMkdir(di.dirfd, fp->fpath, mode);
|
||||||
|
}
|
||||||
|
} else if (S_ISLNK(fp->sb.st_mode)) {
|
||||||
|
if (rc == RPMERR_ENOENT) {
|
||||||
|
@@ -1022,6 +1152,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
fp->stage = FILE_UNPACK;
|
||||||
|
}
|
||||||
|
fi = rpmfiFree(fi);
|
||||||
|
+ close(di.dirfd);
|
||||||
|
+ di.dirfd = -1;
|
||||||
|
|
||||||
|
if (!rc && fx < 0 && fx != RPMERR_ITER_END)
|
||||||
|
rc = fx;
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
40
backport-CVE-2021-35938.patch
Normal file
40
backport-CVE-2021-35938.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
From 25a435e90844ea98fe5eb7bef22c1aecf3a9c033 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Panu Matilainen <pmatilai@redhat.com>
|
||||||
|
Date: Mon, 14 Feb 2022 14:29:33 +0200
|
||||||
|
Subject: [PATCH] Set file metadata via fd-based ops for everything but
|
||||||
|
symlinks
|
||||||
|
|
||||||
|
Regular file ops are fd-based already, for the rest we need to open them
|
||||||
|
manually. Files with temporary suffix must never be followed, for
|
||||||
|
directories (and pre-existing FA_TOUCHed files) use the rpm symlink
|
||||||
|
"root or target owner allowed" rule wrt following.
|
||||||
|
|
||||||
|
This mostly fixes CVE-2021-35938, but as we're not yet using dirfd-based
|
||||||
|
operatiosn for everything there are corner cases left undone. And then
|
||||||
|
there's the plugin API which needs updating for all this.
|
||||||
|
---
|
||||||
|
lib/fsm.c | 8 ++++++++
|
||||||
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||||
|
index 913e9de..6f781c6 100644
|
||||||
|
--- a/lib/fsm.c
|
||||||
|
+++ b/lib/fsm.c
|
||||||
|
@@ -1133,6 +1133,14 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
rc = RPMERR_UNKNOWN_FILETYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (!rc && fd == -1 && !S_ISLNK(fp->sb.st_mode)) {
|
||||||
|
+ /* Only follow safe symlinks, and never on temporary files */
|
||||||
|
+ fd = fsmOpenat(di.dirfd, fp->fpath,
|
||||||
|
+ fp->suffix ? AT_SYMLINK_NOFOLLOW : 0);
|
||||||
|
+ if (fd < 0)
|
||||||
|
+ rc = RPMERR_OPEN_FAILED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (fd != firstlinkfile)
|
||||||
|
fsmClose(&fd);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
From cc22fc694d30a64862f0b16d137deaab5416382d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Panu Matilainen <pmatilai@redhat.com>
|
||||||
|
Date: Fri, 11 Feb 2022 13:05:45 +0200
|
||||||
|
Subject: [PATCH] Consolidate skipped hardlink with content case with the
|
||||||
|
others
|
||||||
|
|
||||||
|
Handling this in a separate clause makes the logic much clearer and
|
||||||
|
(in theory at least) lets us handle hardlinks to any content, not
|
||||||
|
just regular files.
|
||||||
|
---
|
||||||
|
lib/fsm.c | 20 ++++++++++----------
|
||||||
|
1 file changed, 10 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||||
|
index ec6ee2c..82610c7 100644
|
||||||
|
--- a/lib/fsm.c
|
||||||
|
+++ b/lib/fsm.c
|
||||||
|
@@ -832,9 +832,18 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||||
|
struct filedata_s *fp = &fdata[fx];
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Tricksy case: this file is a being skipped, but it's part of
|
||||||
|
+ * a hardlinked set and has the actual content linked with it.
|
||||||
|
+ * Write the content to the first non-skipped file of the set
|
||||||
|
+ * instead.
|
||||||
|
+ */
|
||||||
|
+ if (fp->skip && firstlink && rpmfiArchiveHasContent(fi))
|
||||||
|
+ fp = firstlink;
|
||||||
|
+
|
||||||
|
if (!fp->skip) {
|
||||||
|
/* Directories replacing something need early backup */
|
||||||
|
- if (!fp->suffix) {
|
||||||
|
+ if (!fp->suffix && fp != firstlink) {
|
||||||
|
rc = fsmBackup(fi, fp->action);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -904,15 +913,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
if (!IS_DEV_LOG(fp->fpath))
|
||||||
|
rc = RPMERR_UNKNOWN_FILETYPE;
|
||||||
|
}
|
||||||
|
- } else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
||||||
|
- /*
|
||||||
|
- * Tricksy case: this file is a being skipped, but it's part of
|
||||||
|
- * a hardlinked set and has the actual content linked with it.
|
||||||
|
- * Write the content to the first non-skipped file of the set
|
||||||
|
- * instead.
|
||||||
|
- */
|
||||||
|
- rc = fsmMkfile(fi, firstlink, files, psm, nodigest,
|
||||||
|
- &firstlink, &firstlinkfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notify on success. */
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
@ -0,0 +1,189 @@
|
|||||||
|
From b599e28112ce5cee98b9ffa7bd96886ec5155e9c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Panu Matilainen <pmatilai@redhat.com>
|
||||||
|
Date: Fri, 11 Feb 2022 15:35:16 +0200
|
||||||
|
Subject: [PATCH] Convert the file creation steps the *at() family of calls
|
||||||
|
|
||||||
|
Supposedly no functional changes here, we just need all these things
|
||||||
|
converted before we can swap over to relative paths.
|
||||||
|
---
|
||||||
|
configure.ac | 2 +-
|
||||||
|
lib/fsm.c | 59 ++++++++++++++++++++++++++++++-----------------------------
|
||||||
|
2 files changed, 31 insertions(+), 30 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 0099e5f..ac90037 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -581,7 +581,7 @@ AC_CHECK_FUNCS([secure_getenv __secure_getenv])
|
||||||
|
AC_CHECK_FUNCS(
|
||||||
|
[mkstemp getcwd basename dirname realpath setenv unsetenv regcomp lchown \
|
||||||
|
utimes getline localtime_r statvfs getaddrinfo \
|
||||||
|
- openat mkdirat fstatat ],
|
||||||
|
+ openat mkdirat fstatat linkat symlinkat mkfifoat mknodat ],
|
||||||
|
[], [AC_MSG_ERROR([function required by rpm])])
|
||||||
|
|
||||||
|
AC_LIBOBJ(fnmatch)
|
||||||
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||||
|
index ae1bd3f..8443954 100644
|
||||||
|
--- a/lib/fsm.c
|
||||||
|
+++ b/lib/fsm.c
|
||||||
|
@@ -214,13 +214,13 @@ const char * dnlNextIterator(DNLI_t dnli)
|
||||||
|
return dn;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmLink(const char *opath, const char *path)
|
||||||
|
+static int fsmLink(int odirfd, const char *opath, int dirfd, const char *path)
|
||||||
|
{
|
||||||
|
- int rc = link(opath, path);
|
||||||
|
+ int rc = linkat(odirfd, opath, dirfd, path, 0);
|
||||||
|
|
||||||
|
if (_fsm_debug) {
|
||||||
|
- rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", __func__,
|
||||||
|
- opath, path, (rc < 0 ? strerror(errno) : ""));
|
||||||
|
+ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, %d %s) %s\n", __func__,
|
||||||
|
+ odirfd, opath, dirfd, path, (rc < 0 ? strerror(errno) : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
@@ -139,17 +139,18 @@ static int fsmClose(FD_t *wfdp)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmOpen(FD_t *wfdp, const char *dest)
|
||||||
|
+static int fsmOpen(FD_t *wfdp, int dirfd, const char *dest)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
/* Create the file with 0200 permissions (write by owner). */
|
||||||
|
- {
|
||||||
|
- mode_t old_umask = umask(0577);
|
||||||
|
- *wfdp = Fopen(dest, "wx.ufdio");
|
||||||
|
- umask(old_umask);
|
||||||
|
+ int fd = openat(dirfd, dest, O_WRONLY|O_EXCL|O_CREAT, 0200);
|
||||||
|
+
|
||||||
|
+ if (fd >= 0) {
|
||||||
|
+ *wfdp = fdDup(fd);
|
||||||
|
+ close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (Ferror(*wfdp))
|
||||||
|
+ if (fd < 0 || Ferror(*wfdp))
|
||||||
|
rc = RPMERR_OPEN_FAILED;
|
||||||
|
|
||||||
|
if (_fsm_debug) {
|
||||||
|
@@ -174,7 +175,7 @@ static int fsmUnpack(rpmfi fi, FD_t fd, rpmpsm psm, int nodigest)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
+static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
rpmpsm psm, int nodigest,
|
||||||
|
struct filedata_s ** firstlink, FD_t *firstlinkfile)
|
||||||
|
{
|
||||||
|
@@ -183,7 +184,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
|
||||||
|
if (*firstlink == NULL) {
|
||||||
|
/* First encounter, open file for writing */
|
||||||
|
- rc = fsmOpen(&fd, fp->fpath);
|
||||||
|
+ rc = fsmOpen(&fd, dirfd, fp->fpath);
|
||||||
|
/* If it's a part of a hardlinked set, the content may come later */
|
||||||
|
if (fp->sb.st_nlink > 1) {
|
||||||
|
*firstlink = fp;
|
||||||
|
@@ -192,7 +193,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
} else {
|
||||||
|
/* Create hard links for others and avoid redundant metadata setting */
|
||||||
|
if (*firstlink != fp) {
|
||||||
|
- rc = fsmLink((*firstlink)->fpath, fp->fpath);
|
||||||
|
+ rc = fsmLink(dirfd, (*firstlink)->fpath, dirfd, fp->fpath);
|
||||||
|
}
|
||||||
|
fd = *firstlinkfile;
|
||||||
|
}
|
||||||
|
@@ -382,13 +383,13 @@ static int ensureDir(rpmPlugins plugins, const char *p, int owned, int create)
|
||||||
|
return dirfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmMkfifo(const char *path, mode_t mode)
|
||||||
|
+static int fsmMkfifo(int dirfd, const char *path, mode_t mode)
|
||||||
|
{
|
||||||
|
- int rc = mkfifo(path, (mode & 07777));
|
||||||
|
+ int rc = mkfifoat(dirfd, path, (mode & 07777));
|
||||||
|
|
||||||
|
if (_fsm_debug) {
|
||||||
|
- rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%04o) %s\n",
|
||||||
|
- __func__, path, (unsigned)(mode & 07777),
|
||||||
|
+ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%04o) %s\n",
|
||||||
|
+ __func__, dirfd, path, (unsigned)(mode & 07777),
|
||||||
|
(rc < 0 ? strerror(errno) : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -398,14 +399,14 @@ static int fsmMkfifo(const char *path, mode_t mode)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmMknod(const char *path, mode_t mode, dev_t dev)
|
||||||
|
+static int fsmMknod(int dirfd, const char *path, mode_t mode, dev_t dev)
|
||||||
|
{
|
||||||
|
/* FIX: check S_IFIFO or dev != 0 */
|
||||||
|
- int rc = mknod(path, (mode & ~07777), dev);
|
||||||
|
+ int rc = mknodat(dirfd, path, (mode & ~07777), dev);
|
||||||
|
|
||||||
|
if (_fsm_debug) {
|
||||||
|
- rpmlog(RPMLOG_DEBUG, " %8s (%s, 0%o, 0x%x) %s\n",
|
||||||
|
- __func__, path, (unsigned)(mode & ~07777),
|
||||||
|
+ rpmlog(RPMLOG_DEBUG, " %8s (%d %s, 0%o, 0x%x) %s\n",
|
||||||
|
+ __func__, dirfd, path, (unsigned)(mode & ~07777),
|
||||||
|
(unsigned)dev, (rc < 0 ? strerror(errno) : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -440,13 +441,13 @@ static void fsmDebug(const char *fpath, rpmFileAction action,
|
||||||
|
(fpath ? fpath : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int fsmSymlink(const char *opath, const char *path)
|
||||||
|
+static int fsmSymlink(const char *opath, int dirfd, const char *path)
|
||||||
|
{
|
||||||
|
- int rc = symlink(opath, path);
|
||||||
|
+ int rc = symlinkat(opath, dirfd, path);
|
||||||
|
|
||||||
|
if (_fsm_debug) {
|
||||||
|
- rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", __func__,
|
||||||
|
- opath, path, (rc < 0 ? strerror(errno) : ""));
|
||||||
|
+ rpmlog(RPMLOG_DEBUG, " %8s (%s, %d %s) %s\n", __func__,
|
||||||
|
+ opath, dirfd, path, (rc < 0 ? strerror(errno) : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
@@ -884,7 +885,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
|
||||||
|
if (S_ISREG(fp->sb.st_mode)) {
|
||||||
|
if (rc == RPMERR_ENOENT) {
|
||||||
|
- rc = fsmMkfile(fi, fp, files, psm, nodigest,
|
||||||
|
+ rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
|
||||||
|
&firstlink, &firstlinkfile);
|
||||||
|
}
|
||||||
|
} else if (S_ISDIR(fp->sb.st_mode)) {
|
||||||
|
@@ -896,19 +897,19 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
}
|
||||||
|
} else if (S_ISLNK(fp->sb.st_mode)) {
|
||||||
|
if (rc == RPMERR_ENOENT) {
|
||||||
|
- rc = fsmSymlink(rpmfiFLink(fi), fp->fpath);
|
||||||
|
+ rc = fsmSymlink(rpmfiFLink(fi), di.dirfd, fp->fpath);
|
||||||
|
}
|
||||||
|
} else if (S_ISFIFO(fp->sb.st_mode)) {
|
||||||
|
/* This mimics cpio S_ISSOCK() behavior but probably isn't right */
|
||||||
|
if (rc == RPMERR_ENOENT) {
|
||||||
|
- rc = fsmMkfifo(fp->fpath, 0000);
|
||||||
|
+ rc = fsmMkfifo(di.dirfd, fp->fpath, 0000);
|
||||||
|
}
|
||||||
|
} else if (S_ISCHR(fp->sb.st_mode) ||
|
||||||
|
S_ISBLK(fp->sb.st_mode) ||
|
||||||
|
S_ISSOCK(fp->sb.st_mode))
|
||||||
|
{
|
||||||
|
if (rc == RPMERR_ENOENT) {
|
||||||
|
- rc = fsmMknod(fp->fpath, fp->sb.st_mode, fp->sb.st_rdev);
|
||||||
|
+ rc = fsmMknod(di.dirfd, fp->fpath, fp->sb.st_mode, fp->sb.st_rdev);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* XXX Special case /dev/log, which shouldn't be packaged anyways */
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
From dce44771b2a3325b3dc1ebfe41027df9910a39fd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Panu Matilainen <pmatilai@redhat.com>
|
||||||
|
Date: Fri, 11 Feb 2022 13:18:11 +0200
|
||||||
|
Subject: [PATCH] Fix + sanitize the hardlink metadata setting logic
|
||||||
|
|
||||||
|
Fix the initial setmeta value to something meaningful: we will never
|
||||||
|
set metadata on skipped files, and hardlinks are handled with a special
|
||||||
|
logic during install. They'd need different kind of special logic on
|
||||||
|
FA_TOUCH so just play it safe and always apply metadata on those.
|
||||||
|
|
||||||
|
Harlink metadata setting on install should happen on the *last* entry
|
||||||
|
of hardlinked set that gets installed (wrt various skip scenarios)
|
||||||
|
as otherwise creating those additional links affects the timestamp.
|
||||||
|
Note in particular the "last file of..." case in fsmMkfile() where we
|
||||||
|
the comment said just that, but set the metadata on the *first* file
|
||||||
|
which would then be NULL'ed away.
|
||||||
|
|
||||||
|
This all gets current masked by the fact that we do the metadata setting on
|
||||||
|
a separate round, but that is about to change plus this makes the overall
|
||||||
|
logic clearer anyhow.
|
||||||
|
---
|
||||||
|
lib/fsm.c | 8 +++++---
|
||||||
|
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||||
|
index 82610c7..d9cfe6f 100644
|
||||||
|
--- a/lib/fsm.c
|
||||||
|
+++ b/lib/fsm.c
|
||||||
|
@@ -193,7 +193,6 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
/* Create hard links for others and avoid redundant metadata setting */
|
||||||
|
if (*firstlink != fp) {
|
||||||
|
rc = fsmLink((*firstlink)->fpath, fp->fpath);
|
||||||
|
- fp->setmeta = 0;
|
||||||
|
}
|
||||||
|
fd = *firstlinkfile;
|
||||||
|
}
|
||||||
|
@@ -204,7 +203,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
rc = fsmUnpack(fi, fd, psm, nodigest);
|
||||||
|
/* Last file of hardlink set, ensure metadata gets set */
|
||||||
|
if (*firstlink) {
|
||||||
|
- (*firstlink)->setmeta = 1;
|
||||||
|
+ fp->setmeta = 1;
|
||||||
|
*firstlink = NULL;
|
||||||
|
*firstlinkfile = NULL;
|
||||||
|
}
|
||||||
|
@@ -797,7 +796,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
else
|
||||||
|
fp->action = rpmfsGetAction(fs, fx);
|
||||||
|
fp->skip = XFA_SKIPPING(fp->action);
|
||||||
|
- fp->setmeta = 1;
|
||||||
|
if (XFA_CREATING(fp->action) && !S_ISDIR(rpmfiFMode(fi)))
|
||||||
|
fp->suffix = tid;
|
||||||
|
fp->fpath = fsmFsPath(fi, fp->suffix);
|
||||||
|
@@ -805,6 +803,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
/* Remap file perms, owner, and group. */
|
||||||
|
rc = rpmfiStat(fi, 1, &fp->sb);
|
||||||
|
|
||||||
|
+ /* Hardlinks are tricky and handled elsewhere for install */
|
||||||
|
+ fp->setmeta = (fp->skip == 0) &&
|
||||||
|
+ (fp->sb.st_nlink == 1 || fp->action == FA_TOUCH);
|
||||||
|
+
|
||||||
|
setFileState(fs, fx);
|
||||||
|
fsmDebug(fp->fpath, fp->action, &fp->sb);
|
||||||
|
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
From 693d828c035848585b500dfde6f4e58cfb8d4de4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Panu Matilainen <pmatilai@redhat.com>
|
||||||
|
Date: Mon, 14 Feb 2022 12:44:42 +0200
|
||||||
|
Subject: [PATCH] Return descriptor of created file from fsmMkfile()
|
||||||
|
|
||||||
|
This will be needed for using fd-based metadata operations.
|
||||||
|
---
|
||||||
|
lib/fsm.c | 13 ++++++++-----
|
||||||
|
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||||
|
index b019f57..7c4796f 100644
|
||||||
|
--- a/lib/fsm.c
|
||||||
|
+++ b/lib/fsm.c
|
||||||
|
@@ -172,7 +172,8 @@ static int fsmUnpack(rpmfi fi, int fdno, rpmpsm psm, int nodigest)
|
||||||
|
|
||||||
|
static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
rpmpsm psm, int nodigest,
|
||||||
|
- struct filedata_s ** firstlink, int *firstlinkfile)
|
||||||
|
+ struct filedata_s ** firstlink, int *firstlinkfile,
|
||||||
|
+ int *fdp)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
int fd = -1;
|
||||||
|
@@ -204,9 +205,7 @@ static int fsmMkfile(int dirfd, rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||||
|
*firstlinkfile = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- if (fd != *firstlinkfile)
|
||||||
|
- fsmClose(&fd);
|
||||||
|
+ *fdp = fd;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
@@ -1065,6 +1065,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
fp = firstlink;
|
||||||
|
|
||||||
|
if (!fp->skip) {
|
||||||
|
+ int fd = -1;
|
||||||
|
/* Directories replacing something need early backup */
|
||||||
|
if (!fp->suffix && fp != firstlink) {
|
||||||
|
rc = fsmBackup(fi, fp->action);
|
||||||
|
@@ -910,7 +910,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
if (S_ISREG(fp->sb.st_mode)) {
|
||||||
|
if (rc == RPMERR_ENOENT) {
|
||||||
|
rc = fsmMkfile(di.dirfd, fi, fp, files, psm, nodigest,
|
||||||
|
- &firstlink, &firstlinkfile);
|
||||||
|
+ &firstlink, &firstlinkfile, &fd);
|
||||||
|
}
|
||||||
|
} else if (S_ISDIR(fp->sb.st_mode)) {
|
||||||
|
if (rc == RPMERR_ENOENT) {
|
||||||
|
@@ -1131,6 +1132,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||||
|
if (!IS_DEV_LOG(fp->fpath))
|
||||||
|
rc = RPMERR_UNKNOWN_FILETYPE;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (fd != firstlinkfile)
|
||||||
|
+ fsmClose(&fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notify on success. */
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
14
rpm.spec
14
rpm.spec
@ -1,6 +1,6 @@
|
|||||||
Name: rpm
|
Name: rpm
|
||||||
Version: 4.17.0
|
Version: 4.17.0
|
||||||
Release: 10
|
Release: 11
|
||||||
Summary: RPM Package Manager
|
Summary: RPM Package Manager
|
||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
URL: http://www.rpm.org/
|
URL: http://www.rpm.org/
|
||||||
@ -69,6 +69,15 @@ Patch6035: backport-rpm2cpio.sh-Don-t-drop-newlines-from-header-sizes.patch
|
|||||||
Patch6036: backport-Prevent-readelf-internet-access-during-rpaths-checki.patch
|
Patch6036: backport-Prevent-readelf-internet-access-during-rpaths-checki.patch
|
||||||
Patch6037: backport-Fix-short-circuiting-of-version-strings-in-expressio.patch
|
Patch6037: backport-Fix-short-circuiting-of-version-strings-in-expressio.patch
|
||||||
|
|
||||||
|
Patch6038: backport-Add-optional-callback-on-directory-changes-during-rp.patch
|
||||||
|
Patch6039: backport-CVE-2021-35937-CVE-2021-35939.patch
|
||||||
|
Patch6040: backport-Consolidate-skipped-hardlink-with-content-case-with-.patch
|
||||||
|
Patch6041: backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch
|
||||||
|
Patch6042: backport-Convert-the-file-creation-steps-the-at-family-of-cal.patch
|
||||||
|
Patch6043: backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
|
||||||
|
Patch6044: backport-Return-descriptor-of-created-file-from-fsmMkfile.patch
|
||||||
|
Patch6045: backport-CVE-2021-35938.patch
|
||||||
|
|
||||||
BuildRequires: gcc autoconf automake libtool make gawk popt-devel openssl-devel readline-devel
|
BuildRequires: gcc autoconf automake libtool make gawk popt-devel openssl-devel readline-devel
|
||||||
BuildRequires: zlib-devel zstd-devel >= 1.3.8 xz-devel bzip2-devel libarchive-devel ima-evm-utils-devel
|
BuildRequires: zlib-devel zstd-devel >= 1.3.8 xz-devel bzip2-devel libarchive-devel ima-evm-utils-devel
|
||||||
BuildRequires: dbus-devel fakechroot elfutils-devel elfutils-libelf-devel ima-evm-utils
|
BuildRequires: dbus-devel fakechroot elfutils-devel elfutils-libelf-devel ima-evm-utils
|
||||||
@ -337,6 +346,9 @@ make check || (cat tests/rpmtests.log; exit 0)
|
|||||||
%{_mandir}/man1/gendiff.1*
|
%{_mandir}/man1/gendiff.1*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Aug 31 2022 Hongxun Ren<renhongxun@h-partners.com> - 4.17.0-11
|
||||||
|
- fix CVE-2021-35937 CVE-2021-35938 CVE-2021-35939
|
||||||
|
|
||||||
* Tue Aug 16 2022 Kou Wenqi<kouwenqi@kylinos.cn> - 4.17.0-10
|
* Tue Aug 16 2022 Kou Wenqi<kouwenqi@kylinos.cn> - 4.17.0-10
|
||||||
- Type:enhancement
|
- Type:enhancement
|
||||||
- ID:NA
|
- ID:NA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user