!156 rpm: fix CVE-2021-25937,CVE-2021-25938,CVE-2021-25939
From: @xujing99 Reviewed-by: @licunlong Signed-off-by: @licunlong
This commit is contained in:
commit
dc59f85034
43
backport-0001-CVE-2021-35938.patch
Normal file
43
backport-0001-CVE-2021-35938.patch
Normal file
@ -0,0 +1,43 @@
|
||||
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
|
||||
|
||||
Conflict:adapt context
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/25a435e90844ea98fe5eb7bef22c1aecf3a9c033
|
||||
|
||||
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 913e9de2d..6f781c64d 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -990,6 +990,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;
|
||||
+ }
|
||||
+
|
||||
setmeta:
|
||||
if (!rc && fp->setmeta) {
|
||||
rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
285
backport-0001-CVE-2021-35939-CVE-2021-35937.patch
Normal file
285
backport-0001-CVE-2021-35939-CVE-2021-35937.patch
Normal file
@ -0,0 +1,285 @@
|
||||
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
|
||||
|
||||
Conflict:adapt context; adapt configure.ac because c223d84fbf,f8b8e86ae3,
|
||||
9fe75561f9 is not merged.
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/96ec957e281220f8e137a2d5eb23b83a6377d556
|
||||
|
||||
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 677ef88c4..961a160e0 100644
|
||||
--- a/INSTALL
|
||||
+++ b/INSTALL
|
||||
@@ -103,6 +103,8 @@ option to configure). For GCC, OpenMP 4.5 is fully supported since GCC 6.1,
|
||||
of GPG, available from
|
||||
http://www.gnupg.org/
|
||||
|
||||
+Rpm requires a POSIX.1-2008 level operating system.
|
||||
+
|
||||
To compile RPM:
|
||||
--------------
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 3ee340726..0099e5f34 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],
|
||||
+ utimes getline \
|
||||
+ openat mkdirat fstatat ],
|
||||
[], [AC_MSG_ERROR([function required by rpm])])
|
||||
|
||||
AC_LIBOBJ(fnmatch)
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 911898347..b6b152ab1 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#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)
|
||||
@@ -946,6 +1066,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;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
47
backport-Add-diagnostics-to-archive-unpacking.patch
Normal file
47
backport-Add-diagnostics-to-archive-unpacking.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From f9b90179b7c80a170969d9ab4c77c0a311635e3f Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Thu, 11 Feb 2021 14:18:37 +0200
|
||||
Subject: [PATCH] Add diagnostics to archive unpacking
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/f9b90179b7c80a170969d9ab4c77c0a311635e3f
|
||||
|
||||
Move to a clearly defined helper function, add fsmdebug output.
|
||||
---
|
||||
lib/fsm.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index bd2481a50..c065bd55a 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -297,6 +297,17 @@ static int fsmOpen(FD_t *wfdp, const char *dest)
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static int fsmUnpack(rpmfi fi, FD_t fd, rpmpsm psm, int nodigest)
|
||||
+{
|
||||
+ int rc = rpmfiArchiveReadToFilePsm(fi, fd, nodigest, psm);
|
||||
+ if (_fsm_debug) {
|
||||
+ rpmlog(RPMLOG_DEBUG, " %8s (%s %lu bytes [%d]) %s\n", __func__,
|
||||
+ rpmfiFN(fi), rpmfiFSize(fi), Fileno(fd),
|
||||
+ (rc < 0 ? strerror(errno) : ""));
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
rpmpsm psm, int nodigest,
|
||||
struct filedata_s ** firstlink, FD_t *firstlinkfile)
|
||||
@@ -324,7 +335,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
/* If the file has content, unpack it */
|
||||
if (rpmfiArchiveHasContent(fi)) {
|
||||
if (!rc)
|
||||
- rc = rpmfiArchiveReadToFilePsm(fi, fd, nodigest, psm);
|
||||
+ rc = fsmUnpack(fi, fd, psm, nodigest);
|
||||
/* Last file of hardlink set, ensure metadata gets set */
|
||||
if (*firstlink) {
|
||||
(*firstlink)->setmeta = 1;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
From bbd30984dcedd2de4762b96c92b62a32f9448b03 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Thu, 11 Feb 2021 09:54:41 +0200
|
||||
Subject: [PATCH] Add hardlink helper to fsm to make it debuggable
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/bbd30984dcedd2de4762b96c92b62a32f9448b03
|
||||
|
||||
---
|
||||
lib/fsm.c | 19 +++++++++++++++----
|
||||
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 6efd25bdd..f8038e09b 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -211,6 +211,20 @@ const char * dnlNextIterator(DNLI_t dnli)
|
||||
return dn;
|
||||
}
|
||||
|
||||
+static int fsmLink(const char *opath, const char *path)
|
||||
+{
|
||||
+ int rc = link(opath, path);
|
||||
+
|
||||
+ if (_fsm_debug) {
|
||||
+ rpmlog(RPMLOG_DEBUG, " %8s (%s, %s) %s\n", __func__,
|
||||
+ opath, path, (rc < 0 ? strerror(errno) : ""));
|
||||
+ }
|
||||
+
|
||||
+ if (rc < 0)
|
||||
+ rc = RPMERR_LINK_FAILED;
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
static int fsmSetFCaps(const char *path, const char *captxt)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -304,10 +318,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
rc = wfd_open(firstlinkfile, fp->fpath);
|
||||
} else {
|
||||
/* Create hard links for others */
|
||||
- rc = link((*firstlink)->fpath, fp->fpath);
|
||||
- if (rc < 0) {
|
||||
- rc = RPMERR_LINK_FAILED;
|
||||
- }
|
||||
+ rc = fsmLink((*firstlink)->fpath, fp->fpath);
|
||||
}
|
||||
}
|
||||
/* Write normal files or fill the last hardlinked (already
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
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
|
||||
|
||||
Conflict:adapt rpmfi.c because 318efbaec is not merged.
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/fb13f7fd9eff012cb7b9dbf94ac5381c69404055
|
||||
|
||||
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 4673fbb85..e8e7d08bf 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 */
|
||||
@@ -303,6 +306,17 @@ rpm_count_t rpmfiDC(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 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.27.0
|
||||
|
||||
132
backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
Normal file
132
backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
Normal file
@ -0,0 +1,132 @@
|
||||
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()
|
||||
|
||||
Conflict:adapt context
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/bbc270d78fb361bd78eac9a9117070caeb537d4a
|
||||
|
||||
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 13b114220..b019f5711 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}");
|
||||
@@ -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 %lu 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;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
70
backport-Clean-up-file-unpack-iteration-logic-a-bit.patch
Normal file
70
backport-Clean-up-file-unpack-iteration-logic-a-bit.patch
Normal file
@ -0,0 +1,70 @@
|
||||
From 073bcf7ff6d580e5bafee0ef762cf7ce71bc486d Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Mon, 8 Feb 2021 10:45:59 +0200
|
||||
Subject: [PATCH] Clean up file unpack iteration logic a bit
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/073bcf7ff6d580e5bafee0ef762cf7ce71bc486d
|
||||
|
||||
Handle rpmfiNext() in the while-condition directly to make it more like
|
||||
similar other constructs elsewhere, adjust for the end of iteration
|
||||
code after the loop. Also take the file index from rpmfiNext() so
|
||||
we don't need multiple calls to rpmfiFX() later.
|
||||
---
|
||||
lib/fsm.c | 19 +++++++------------
|
||||
1 file changed, 7 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 35dcda081..7c291adb0 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -841,6 +841,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
struct stat sb;
|
||||
int saveerrno = errno;
|
||||
int rc = 0;
|
||||
+ int fx = -1;
|
||||
int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
|
||||
int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
|
||||
int firsthardlink = -1;
|
||||
@@ -862,17 +863,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
/* Detect and create directories not explicitly in package. */
|
||||
rc = fsmMkdirs(files, fs, plugins);
|
||||
|
||||
- while (!rc) {
|
||||
- /* Read next payload header. */
|
||||
- rc = rpmfiNext(fi);
|
||||
-
|
||||
- if (rc < 0) {
|
||||
- if (rc == RPMERR_ITER_END)
|
||||
- rc = 0;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- action = rpmfsGetAction(fs, rpmfiFX(fi));
|
||||
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
+ action = rpmfsGetAction(fs, fx);
|
||||
skip = XFA_SKIPPING(action);
|
||||
if (action != FA_TOUCH) {
|
||||
suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
||||
@@ -896,7 +888,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
if (rc) {
|
||||
skip = 1;
|
||||
} else {
|
||||
- setFileState(fs, rpmfiFX(fi));
|
||||
+ setFileState(fs, fx);
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
@@ -1005,6 +997,9 @@ touch:
|
||||
fpath = _free(fpath);
|
||||
}
|
||||
|
||||
+ if (!rc && fx != RPMERR_ITER_END)
|
||||
+ rc = fx;
|
||||
+
|
||||
rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS), fdOp(payload, FDSTAT_READ));
|
||||
rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST), fdOp(payload, FDSTAT_DIGEST));
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
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
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/cc22fc694d30a64862f0b16d137deaab5416382d
|
||||
|
||||
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 ec6ee2c36..82610c77d 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. */
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,192 @@
|
||||
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
|
||||
|
||||
Conflict:adapt context
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/b599e28112ce5cee98b9ffa7bd96886ec5155e9c
|
||||
|
||||
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 0099e5f34..ac9003768 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 \
|
||||
- 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 ae1bd3f48..8443954f2 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -77,13 +77,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 */
|
||||
--
|
||||
2.27.0
|
||||
|
||||
31
backport-Drop-unused-filename-variable.patch
Normal file
31
backport-Drop-unused-filename-variable.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 8a9147f7d182e1a5aa55ac019c32a4ba765fae62 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 08:25:28 +0200
|
||||
Subject: [PATCH] Drop unused filename variable
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/8a9147f7d182e1a5aa55ac019c32a4ba765fae62
|
||||
|
||||
---
|
||||
lib/fsm.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 7c291adb0..41b6267dd 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -959,11 +959,9 @@ touch:
|
||||
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
||||
/* we skip the hard linked file containing the content */
|
||||
/* write the content to the first used instead */
|
||||
- char *fn = rpmfilesFN(files, firsthardlink);
|
||||
rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm);
|
||||
wfd_close(&firstlinkfile);
|
||||
firsthardlink = -1;
|
||||
- free(fn);
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
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
|
||||
|
||||
Conflict:adapt context
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/dce44771b2a3325b3dc1ebfe41027df9910a39fd
|
||||
|
||||
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 82610c77d..d9cfe6fa9 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 (fp->action != FA_TOUCH) {
|
||||
fp->suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
||||
} else {
|
||||
@@ -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);
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
261
backport-Handle-file-install-failures-more-gracefully.patch
Normal file
261
backport-Handle-file-install-failures-more-gracefully.patch
Normal file
@ -0,0 +1,261 @@
|
||||
From a82251b44ee2d2802ee8aea1b3d89f88beee4bad Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 14:15:33 +0200
|
||||
Subject: [PATCH] Handle file install failures more gracefully
|
||||
|
||||
Conflict:adapt context; delete testcode
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/a82251b44ee2d2802ee8aea1b3d89f88beee4bad
|
||||
Run the file installation in multiple stages:
|
||||
1) gather intel
|
||||
2) unpack the archive to temporary files
|
||||
3) set file metadatas
|
||||
4) commit files to final location
|
||||
5) mop up leftovers on failure
|
||||
|
||||
This means we no longer leave behind a trail of untracked, potentially
|
||||
harmful junk on installation failure.
|
||||
|
||||
If commit step fails the package can still be left in an inconsistent stage,
|
||||
this could be further improved by first backing up old files to temporary
|
||||
location to allow undo on failure, but leaving that for some other day.
|
||||
Also unowned directories will still be left behind.
|
||||
|
||||
And yes, this is a somewhat scary change as it's the biggest ever change
|
||||
to how rpm lays down files on install. Adopt the hardlink test spec
|
||||
over to install tests and add some more tests for the new behavior.
|
||||
|
||||
Fixes: #967 (+ multiple reports over the years)
|
||||
---
|
||||
lib/fsm.c | 147 ++++++++++++++++++++------------
|
||||
1 files changed, 93 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index f86383a98..6efd25bdd 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -38,7 +38,17 @@ static int strict_erasures = 0;
|
||||
#define _dirPerms 0755
|
||||
#define _filePerms 0644
|
||||
|
||||
+enum filestage_e {
|
||||
+ FILE_COMMIT = -1,
|
||||
+ FILE_NONE = 0,
|
||||
+ FILE_PRE = 1,
|
||||
+ FILE_UNPACK = 2,
|
||||
+ FILE_PREP = 3,
|
||||
+ FILE_POST = 4,
|
||||
+};
|
||||
+
|
||||
struct filedata_s {
|
||||
+ int stage;
|
||||
int setmeta;
|
||||
int skip;
|
||||
rpmFileAction action;
|
||||
@@ -844,10 +854,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
rpmpsm psm, char ** failedFile)
|
||||
{
|
||||
FD_t payload = rpmtePayload(te);
|
||||
- rpmfi fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
||||
+ rpmfi fi = NULL;
|
||||
rpmfs fs = rpmteGetFileStates(te);
|
||||
rpmPlugins plugins = rpmtsPlugins(ts);
|
||||
- int saveerrno = errno;
|
||||
int rc = 0;
|
||||
int fx = -1;
|
||||
int fc = rpmfilesFC(files);
|
||||
@@ -858,20 +867,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
||||
struct filedata_s *firstlink = NULL;
|
||||
|
||||
- if (fi == NULL) {
|
||||
- rc = RPMERR_BAD_MAGIC;
|
||||
- goto exit;
|
||||
- }
|
||||
-
|
||||
/* transaction id used for temporary path suffix while installing */
|
||||
rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
|
||||
|
||||
- /* Detect and create directories not explicitly in package. */
|
||||
- rc = fsmMkdirs(files, fs, plugins);
|
||||
-
|
||||
+ /* Collect state data for the whole operation */
|
||||
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
||||
while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
struct filedata_s *fp = &fdata[fx];
|
||||
- fp->action = rpmfsGetAction(fs, fx);
|
||||
+ if (rpmfiFFlags(fi) & RPMFILE_GHOST)
|
||||
+ fp->action = FA_SKIP;
|
||||
+ else
|
||||
+ fp->action = rpmfsGetAction(fs, fx);
|
||||
fp->skip = XFA_SKIPPING(fp->action);
|
||||
fp->setmeta = 1;
|
||||
if (fp->action != FA_TOUCH) {
|
||||
@@ -881,20 +887,32 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
/* Remap file perms, owner, and group. */
|
||||
rc = rpmfiStat(fi, 1, &fp->sb);
|
||||
|
||||
+ setFileState(fs, fx);
|
||||
fsmDebug(fp->fpath, fp->action, &fp->sb);
|
||||
|
||||
- /* Exit on error. */
|
||||
- if (rc)
|
||||
- break;
|
||||
-
|
||||
/* Run fsm file pre hook for all plugins */
|
||||
rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
||||
fp->sb.st_mode, fp->action);
|
||||
- if (rc) {
|
||||
- fp->skip = 1;
|
||||
- } else {
|
||||
- setFileState(fs, fx);
|
||||
- }
|
||||
+ fp->stage = FILE_PRE;
|
||||
+ }
|
||||
+ fi = rpmfiFree(fi);
|
||||
+
|
||||
+ if (rc)
|
||||
+ goto exit;
|
||||
+
|
||||
+ fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
||||
+ if (fi == NULL) {
|
||||
+ rc = RPMERR_BAD_MAGIC;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ /* Detect and create directories not explicitly in package. */
|
||||
+ if (!rc)
|
||||
+ rc = fsmMkdirs(files, fs, plugins);
|
||||
+
|
||||
+ /* Process the payload */
|
||||
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
+ struct filedata_s *fp = &fdata[fx];
|
||||
|
||||
if (!fp->skip) {
|
||||
/* Directories replacing something need early backup */
|
||||
@@ -918,7 +936,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
|
||||
/* When touching we don't need any of this... */
|
||||
if (fp->action == FA_TOUCH)
|
||||
- goto touch;
|
||||
+ continue;
|
||||
|
||||
if (S_ISREG(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
@@ -954,12 +972,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
rc = RPMERR_UNKNOWN_FILETYPE;
|
||||
}
|
||||
|
||||
-touch:
|
||||
- /* Set permissions, timestamps etc for non-hardlink entries */
|
||||
- if (!rc && fp->setmeta) {
|
||||
- rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
- &fp->sb, nofcaps);
|
||||
- }
|
||||
} else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
||||
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
||||
/* we skip the hard linked file containing the content */
|
||||
@@ -969,47 +981,74 @@ touch:
|
||||
firstlink = NULL;
|
||||
}
|
||||
|
||||
- if (rc) {
|
||||
- if (!fp->skip) {
|
||||
- /* XXX only erase if temp fn w suffix is in use */
|
||||
- if (fp->suffix) {
|
||||
- (void) fsmRemove(fp->fpath, fp->sb.st_mode);
|
||||
- }
|
||||
- errno = saveerrno;
|
||||
- }
|
||||
- } else {
|
||||
- /* Notify on success. */
|
||||
+ /* Notify on success. */
|
||||
+ if (rc)
|
||||
+ *failedFile = xstrdup(fp->fpath);
|
||||
+ else
|
||||
rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, rpmfiArchiveTell(fi));
|
||||
+ fp->stage = FILE_UNPACK;
|
||||
+ }
|
||||
+ fi = rpmfiFree(fi);
|
||||
|
||||
- if (!fp->skip) {
|
||||
- /* Backup file if needed. Directories are handled earlier */
|
||||
- if (fp->suffix)
|
||||
- rc = fsmBackup(fi, fp->action);
|
||||
+ if (!rc && fx < 0 && fx != RPMERR_ITER_END)
|
||||
+ rc = fx;
|
||||
|
||||
- if (!rc)
|
||||
- rc = fsmCommit(&fp->fpath, fi, fp->action, fp->suffix);
|
||||
- }
|
||||
+ /* Set permissions, timestamps etc for non-hardlink entries */
|
||||
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
||||
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
+ struct filedata_s *fp = &fdata[fx];
|
||||
+ if (!fp->skip && fp->setmeta) {
|
||||
+ rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
+ &fp->sb, nofcaps);
|
||||
}
|
||||
-
|
||||
if (rc)
|
||||
*failedFile = xstrdup(fp->fpath);
|
||||
+ fp->stage = FILE_PREP;
|
||||
+ }
|
||||
+ fi = rpmfiFree(fi);
|
||||
|
||||
- /* Run fsm file post hook for all plugins */
|
||||
- rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
||||
- fp->sb.st_mode, fp->action, rc);
|
||||
+ /* If all went well, commit files to final destination */
|
||||
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
||||
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
+ struct filedata_s *fp = &fdata[fx];
|
||||
+
|
||||
+ if (!fp->skip) {
|
||||
+ /* Backup file if needed. Directories are handled earlier */
|
||||
+ if (!rc && fp->suffix)
|
||||
+ rc = fsmBackup(fi, fp->action);
|
||||
+
|
||||
+ if (!rc)
|
||||
+ rc = fsmCommit(&fp->fpath, fi, fp->action, fp->suffix);
|
||||
+
|
||||
+ if (!rc)
|
||||
+ fp->stage = FILE_COMMIT;
|
||||
+ else
|
||||
+ *failedFile = xstrdup(fp->fpath);
|
||||
+ }
|
||||
}
|
||||
+ fi = rpmfiFree(fi);
|
||||
|
||||
- if (!rc && fx != RPMERR_ITER_END)
|
||||
- rc = fx;
|
||||
+ /* Walk backwards in case we need to erase */
|
||||
+ fi = rpmfilesIter(files, RPMFI_ITER_BACK);
|
||||
+ while ((fx = rpmfiNext(fi)) >= 0) {
|
||||
+ struct filedata_s *fp = &fdata[fx];
|
||||
+ /* Run fsm file post hook for all plugins for all processed files */
|
||||
+ if (fp->stage) {
|
||||
+ rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
||||
+ fp->sb.st_mode, fp->action, rc);
|
||||
+ }
|
||||
+
|
||||
+ /* On failure, erase non-committed files */
|
||||
+ if (rc && fp->stage > FILE_NONE && !fp->skip) {
|
||||
+ (void) fsmRemove(fp->fpath, fp->sb.st_mode);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS), fdOp(payload, FDSTAT_READ));
|
||||
rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST), fdOp(payload, FDSTAT_DIGEST));
|
||||
|
||||
exit:
|
||||
-
|
||||
- /* No need to bother with close errors on read */
|
||||
- rpmfiArchiveClose(fi);
|
||||
- rpmfiFree(fi);
|
||||
+ fi = rpmfiFree(fi);
|
||||
Fclose(payload);
|
||||
free(tid);
|
||||
for (int i = 0; i < fc; i++)
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
From 1c23cff7296cec56379ee41077145c29d6841a12 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 11:25:10 +0200
|
||||
Subject: [PATCH] Handle hardlink tracking with a file state pointer
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/1c23cff7296cec56379ee41077145c29d6841a12
|
||||
|
||||
No functional changes, just makes it a little cleaner as firstlink now
|
||||
points to the actual file data instead of a index number somewhere.
|
||||
---
|
||||
lib/fsm.c | 20 +++++++++-----------
|
||||
1 file changed, 9 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 094f5e2bb..f86383a98 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -282,24 +282,22 @@ exit:
|
||||
|
||||
static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
rpmpsm psm, int nodigest,
|
||||
- int * firsthardlink, FD_t *firstlinkfile)
|
||||
+ struct filedata_s ** firstlink, FD_t *firstlinkfile)
|
||||
{
|
||||
int rc = 0;
|
||||
int numHardlinks = rpmfiFNlink(fi);
|
||||
|
||||
if (numHardlinks > 1) {
|
||||
/* Create first hardlinked file empty */
|
||||
- if (*firsthardlink < 0) {
|
||||
- *firsthardlink = rpmfiFX(fi);
|
||||
+ if (*firstlink == NULL) {
|
||||
+ *firstlink = fp;
|
||||
rc = wfd_open(firstlinkfile, fp->fpath);
|
||||
} else {
|
||||
/* Create hard links for others */
|
||||
- char *fn = rpmfilesFN(files, *firsthardlink);
|
||||
- rc = link(fn, fp->fpath);
|
||||
+ rc = link((*firstlink)->fpath, fp->fpath);
|
||||
if (rc < 0) {
|
||||
rc = RPMERR_LINK_FAILED;
|
||||
}
|
||||
- free(fn);
|
||||
}
|
||||
}
|
||||
/* Write normal files or fill the last hardlinked (already
|
||||
@@ -311,7 +309,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
if (!rc)
|
||||
rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
|
||||
wfd_close(firstlinkfile);
|
||||
- *firsthardlink = -1;
|
||||
+ *firstlink = NULL;
|
||||
} else {
|
||||
fp->setmeta = 0;
|
||||
}
|
||||
@@ -855,10 +853,10 @@ 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;
|
||||
- int firsthardlink = -1;
|
||||
FD_t firstlinkfile = NULL;
|
||||
char *tid = NULL;
|
||||
struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
||||
+ struct filedata_s *firstlink = NULL;
|
||||
|
||||
if (fi == NULL) {
|
||||
rc = RPMERR_BAD_MAGIC;
|
||||
@@ -925,7 +923,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,
|
||||
- &firsthardlink, &firstlinkfile);
|
||||
+ &firstlink, &firstlinkfile);
|
||||
}
|
||||
} else if (S_ISDIR(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
@@ -962,13 +960,13 @@ touch:
|
||||
rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
&fp->sb, nofcaps);
|
||||
}
|
||||
- } else if (firsthardlink >= 0 && rpmfiArchiveHasContent(fi)) {
|
||||
+ } else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
||||
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
||||
/* we skip the hard linked file containing the content */
|
||||
/* write the content to the first used instead */
|
||||
rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm);
|
||||
wfd_close(&firstlinkfile);
|
||||
- firsthardlink = -1;
|
||||
+ firstlink = NULL;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
148
backport-Make-file-open-and-close-in-fsm-debuggable.patch
Normal file
148
backport-Make-file-open-and-close-in-fsm-debuggable.patch
Normal file
@ -0,0 +1,148 @@
|
||||
From 2efdc55e15b21a80dcc414aa95e433c3adf4516c Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Thu, 11 Feb 2021 10:36:28 +0200
|
||||
Subject: [PATCH] Make file open and close in fsm debuggable
|
||||
|
||||
Conflict:adapt context
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/2efdc55e15b21a80dcc414aa95e433c3adf4516c
|
||||
|
||||
Add debugging facilities to file open and close routines in fsm, rename
|
||||
wfd_open/close to fsmOpen/Close to bring the messages in line with
|
||||
our other stuff.
|
||||
|
||||
Slight reorganization needed for the error paths, in particular in
|
||||
case of file close we haven't even been recording the close result
|
||||
with can be critical when writing files. Add an error code for close
|
||||
failure and return it from fsmClose(), but updating the calling code
|
||||
to take this into account is out of scope in this commit.
|
||||
---
|
||||
lib/fsm.c | 40 ++++++++++++++++++++++++++--------------
|
||||
lib/rpmarchive.h | 1 +
|
||||
2 files changed, 27 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index f8038e09b..ffafa5d68 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -244,27 +244,36 @@ static int fsmSetFCaps(const char *path, const char *captxt)
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static void wfd_close(FD_t *wfdp)
|
||||
+static int fsmClose(FD_t *wfdp)
|
||||
{
|
||||
+ int rc = 0;
|
||||
if (wfdp && *wfdp) {
|
||||
int myerrno = errno;
|
||||
static int oneshot = 0;
|
||||
static int flush_io = 0;
|
||||
+ int fdno = Fileno(*wfdp);
|
||||
+
|
||||
if (!oneshot) {
|
||||
flush_io = rpmExpandNumeric("%{?_flush_io}");
|
||||
oneshot = 1;
|
||||
}
|
||||
if (flush_io) {
|
||||
- int fdno = Fileno(*wfdp);
|
||||
fsync(fdno);
|
||||
}
|
||||
- Fclose(*wfdp);
|
||||
+ if (Fclose(*wfdp))
|
||||
+ rc = RPMERR_CLOSE_FAILED;
|
||||
+
|
||||
+ if (_fsm_debug) {
|
||||
+ rpmlog(RPMLOG_DEBUG, " %8s ([%d]) %s\n", __func__,
|
||||
+ fdno, (rc < 0 ? strerror(errno) : ""));
|
||||
+ }
|
||||
*wfdp = NULL;
|
||||
errno = myerrno;
|
||||
}
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
-static int wfd_open(FD_t *wfdp, const char *dest)
|
||||
+static int fsmOpen(FD_t *wfdp, const char *dest)
|
||||
{
|
||||
int rc = 0;
|
||||
/* Create the file with 0200 permissions (write by owner). */
|
||||
@@ -273,15 +282,18 @@ static int wfd_open(FD_t *wfdp, const char *dest)
|
||||
*wfdp = Fopen(dest, "wx.ufdio");
|
||||
umask(old_umask);
|
||||
}
|
||||
- if (Ferror(*wfdp)) {
|
||||
+
|
||||
+ if (Ferror(*wfdp))
|
||||
rc = RPMERR_OPEN_FAILED;
|
||||
- goto exit;
|
||||
+
|
||||
+ if (_fsm_debug) {
|
||||
+ rpmlog(RPMLOG_DEBUG, " %8s (%s [%d]) %s\n", __func__,
|
||||
+ dest, Fileno(*wfdp), (rc < 0 ? strerror(errno) : ""));
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ if (rc)
|
||||
+ fsmClose(wfdp);
|
||||
|
||||
-exit:
|
||||
- wfd_close(wfdp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -294,12 +306,12 @@ static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int nodigest)
|
||||
FD_t wfd = NULL;
|
||||
int rc;
|
||||
|
||||
- rc = wfd_open(&wfd, dest);
|
||||
+ rc = fsmOpen(&wfd, dest);
|
||||
if (rc != 0)
|
||||
goto exit;
|
||||
|
||||
rc = rpmfiArchiveReadToFilePsm(fi, wfd, nodigest, psm);
|
||||
- wfd_close(&wfd);
|
||||
+ fsmClose(&wfd);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
@@ -315,7 +327,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
/* Create first hardlinked file empty */
|
||||
if (*firstlink == NULL) {
|
||||
*firstlink = fp;
|
||||
- rc = wfd_open(firstlinkfile, fp->fpath);
|
||||
+ rc = fsmOpen(firstlinkfile, fp->fpath);
|
||||
} else {
|
||||
/* Create hard links for others */
|
||||
rc = fsmLink((*firstlink)->fpath, fp->fpath);
|
||||
@@ -329,7 +341,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
} else if (rpmfiArchiveHasContent(fi)) {
|
||||
if (!rc)
|
||||
rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
|
||||
- wfd_close(firstlinkfile);
|
||||
+ fsmClose(firstlinkfile);
|
||||
*firstlink = NULL;
|
||||
} else {
|
||||
fp->setmeta = 0;
|
||||
@@ -988,7 +1000,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
/* we skip the hard linked file containing the content */
|
||||
/* write the content to the first used instead */
|
||||
rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm);
|
||||
- wfd_close(&firstlinkfile);
|
||||
+ fsmClose(&firstlinkfile);
|
||||
firstlink = NULL;
|
||||
}
|
||||
|
||||
diff --git a/lib/rpmarchive.h b/lib/rpmarchive.h
|
||||
index 2484b4d71..ec6366c86 100644
|
||||
--- a/lib/rpmarchive.h
|
||||
+++ b/lib/rpmarchive.h
|
||||
@@ -47,6 +47,7 @@ enum rpmfilesErrorCodes {
|
||||
RPMERR_COPY_FAILED = -32785,
|
||||
RPMERR_LSETFCON_FAILED = -32786,
|
||||
RPMERR_SETCAP_FAILED = -32787,
|
||||
+ RPMERR_CLOSE_FAILED = -32788,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
From da79e3c3ae7da8719f0bf87a1a60e046597b8240 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Fri, 11 Feb 2022 13:28:25 +0200
|
||||
Subject: [PATCH] Move file metadata setting back to unpack stage
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/da79e3c3ae7da8719f0bf87a1a60e046597b8240
|
||||
|
||||
Commit a82251b44ee2d2802ee8aea1b3d89f88beee4bad moved metadata setting
|
||||
to a separate step because there are potential benefits to doing so, but
|
||||
the current downsides are worse: as long as we operate in potentially
|
||||
untrusted directories, we'd need to somehow verify the content is what we
|
||||
initially laid down to avoid possible privilege escalation from non-root
|
||||
owned directories.
|
||||
|
||||
This commit does not fix that vulnerability, only makes the window much
|
||||
smaller and paves the way for the real fix(es) without introducing a
|
||||
second round of directory tree validation chase to the picture.
|
||||
---
|
||||
lib/fsm.c | 22 +++++++---------------
|
||||
1 file changed, 7 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index d9cfe6fa9..ae1bd3f48 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -880,7 +880,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
|
||||
/* When touching we don't need any of this... */
|
||||
if (fp->action == FA_TOUCH)
|
||||
- continue;
|
||||
+ goto setmeta;
|
||||
|
||||
if (S_ISREG(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
@@ -915,6 +915,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
if (!IS_DEV_LOG(fp->fpath))
|
||||
rc = RPMERR_UNKNOWN_FILETYPE;
|
||||
}
|
||||
+
|
||||
+setmeta:
|
||||
+ if (!rc && fp->setmeta) {
|
||||
+ rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
+ &fp->sb, nofcaps);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Notify on success. */
|
||||
@@ -931,20 +937,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
if (!rc && fx < 0 && fx != RPMERR_ITER_END)
|
||||
rc = fx;
|
||||
|
||||
- /* Set permissions, timestamps etc for non-hardlink entries */
|
||||
- fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
||||
- while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
- struct filedata_s *fp = &fdata[fx];
|
||||
- if (!fp->skip && fp->setmeta) {
|
||||
- rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
- &fp->sb, nofcaps);
|
||||
- }
|
||||
- if (rc)
|
||||
- *failedFile = xstrdup(fp->fpath);
|
||||
- fp->stage = FILE_PREP;
|
||||
- }
|
||||
- fi = rpmfiFree(fi);
|
||||
-
|
||||
/* If all went well, commit files to final destination */
|
||||
fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
||||
while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,340 @@
|
||||
From 924cb31c53dcf60ff0cce650851dba354f383f15 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 09:47:19 +0200
|
||||
Subject: [PATCH] Refactor file install and remove around a common struct
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/924cb31c53dcf60ff0cce650851dba354f383f15
|
||||
|
||||
Collect the common state info into a struct shared by both file install
|
||||
and remove, update code accordingly. The change looks much more drastic
|
||||
than it is - it's just adding fp-> prefix to a lot of places.
|
||||
While we're at it, remember the state data throughout the operation.
|
||||
|
||||
No functional changes here, just paving way for the next steps which
|
||||
will look clearer with these pre-requisites in place.
|
||||
---
|
||||
lib/fsm.c | 158 +++++++++++++++++++++++++++++-------------------------
|
||||
1 file changed, 85 insertions(+), 73 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index c581a918a..9dba30560 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -38,6 +38,14 @@ static int strict_erasures = 0;
|
||||
#define _dirPerms 0755
|
||||
#define _filePerms 0644
|
||||
|
||||
+struct filedata_s {
|
||||
+ int skip;
|
||||
+ rpmFileAction action;
|
||||
+ const char *suffix;
|
||||
+ char *fpath;
|
||||
+ struct stat sb;
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* XXX Forward declarations for previously exported functions to avoid moving
|
||||
* things around needlessly
|
||||
@@ -840,19 +848,16 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
rpmfi fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
||||
rpmfs fs = rpmteGetFileStates(te);
|
||||
rpmPlugins plugins = rpmtsPlugins(ts);
|
||||
- struct stat sb;
|
||||
int saveerrno = errno;
|
||||
int rc = 0;
|
||||
int fx = -1;
|
||||
+ int fc = rpmfilesFC(files);
|
||||
int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
|
||||
int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
|
||||
int firsthardlink = -1;
|
||||
FD_t firstlinkfile = NULL;
|
||||
- int skip;
|
||||
- rpmFileAction action;
|
||||
char *tid = NULL;
|
||||
- const char *suffix;
|
||||
- char *fpath = NULL;
|
||||
+ struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
||||
|
||||
if (fi == NULL) {
|
||||
rc = RPMERR_BAD_MAGIC;
|
||||
@@ -866,96 +871,99 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
rc = fsmMkdirs(files, fs, plugins);
|
||||
|
||||
while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
- action = rpmfsGetAction(fs, fx);
|
||||
- skip = XFA_SKIPPING(action);
|
||||
- if (action != FA_TOUCH) {
|
||||
- suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
||||
+ struct filedata_s *fp = &fdata[fx];
|
||||
+ fp->action = rpmfsGetAction(fs, fx);
|
||||
+ fp->skip = XFA_SKIPPING(fp->action);
|
||||
+ if (fp->action != FA_TOUCH) {
|
||||
+ fp->suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
||||
} else {
|
||||
- suffix = NULL;
|
||||
+ fp->suffix = NULL;
|
||||
}
|
||||
- fpath = fsmFsPath(fi, suffix);
|
||||
+ fp->fpath = fsmFsPath(fi, fp->suffix);
|
||||
|
||||
/* Remap file perms, owner, and group. */
|
||||
- rc = rpmfiStat(fi, 1, &sb);
|
||||
+ rc = rpmfiStat(fi, 1, &fp->sb);
|
||||
|
||||
- fsmDebug(fpath, action, &sb);
|
||||
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
|
||||
|
||||
/* Exit on error. */
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
/* Run fsm file pre hook for all plugins */
|
||||
- rc = rpmpluginsCallFsmFilePre(plugins, fi, fpath,
|
||||
- sb.st_mode, action);
|
||||
+ rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
||||
+ fp->sb.st_mode, fp->action);
|
||||
if (rc) {
|
||||
- skip = 1;
|
||||
+ fp->skip = 1;
|
||||
} else {
|
||||
setFileState(fs, fx);
|
||||
}
|
||||
|
||||
- if (!skip) {
|
||||
+ if (!fp->skip) {
|
||||
int setmeta = 1;
|
||||
|
||||
/* Directories replacing something need early backup */
|
||||
- if (!suffix) {
|
||||
- rc = fsmBackup(fi, action);
|
||||
+ if (!fp->suffix) {
|
||||
+ rc = fsmBackup(fi, fp->action);
|
||||
}
|
||||
/* Assume file does't exist when tmp suffix is in use */
|
||||
- if (!suffix) {
|
||||
- rc = fsmVerify(fpath, fi);
|
||||
+ if (!fp->suffix) {
|
||||
+ rc = fsmVerify(fp->fpath, fi);
|
||||
} else {
|
||||
rc = RPMERR_ENOENT;
|
||||
}
|
||||
|
||||
/* See if the file was removed while our attention was elsewhere */
|
||||
- if (rc == RPMERR_ENOENT && action == FA_TOUCH) {
|
||||
- rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n", fpath);
|
||||
- action = FA_CREATE;
|
||||
- fsmDebug(fpath, action, &sb);
|
||||
+ if (rc == RPMERR_ENOENT && fp->action == FA_TOUCH) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n",
|
||||
+ fp->fpath);
|
||||
+ fp->action = FA_CREATE;
|
||||
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
|
||||
}
|
||||
|
||||
/* When touching we don't need any of this... */
|
||||
- if (action == FA_TOUCH)
|
||||
+ if (fp->action == FA_TOUCH)
|
||||
goto touch;
|
||||
|
||||
- if (S_ISREG(sb.st_mode)) {
|
||||
+ if (S_ISREG(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
- rc = fsmMkfile(fi, fpath, files, psm, nodigest,
|
||||
+ rc = fsmMkfile(fi, fp->fpath, files, psm, nodigest,
|
||||
&setmeta, &firsthardlink, &firstlinkfile);
|
||||
}
|
||||
- } else if (S_ISDIR(sb.st_mode)) {
|
||||
+ } else if (S_ISDIR(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
- mode_t mode = sb.st_mode;
|
||||
+ mode_t mode = fp->sb.st_mode;
|
||||
mode &= ~07777;
|
||||
mode |= 00700;
|
||||
- rc = fsmMkdir(fpath, mode);
|
||||
+ rc = fsmMkdir(fp->fpath, mode);
|
||||
}
|
||||
- } else if (S_ISLNK(sb.st_mode)) {
|
||||
+ } else if (S_ISLNK(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
- rc = fsmSymlink(rpmfiFLink(fi), fpath);
|
||||
+ rc = fsmSymlink(rpmfiFLink(fi), fp->fpath);
|
||||
}
|
||||
- } else if (S_ISFIFO(sb.st_mode)) {
|
||||
+ } 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(fpath, 0000);
|
||||
+ rc = fsmMkfifo(fp->fpath, 0000);
|
||||
}
|
||||
- } else if (S_ISCHR(sb.st_mode) ||
|
||||
- S_ISBLK(sb.st_mode) ||
|
||||
- S_ISSOCK(sb.st_mode))
|
||||
+ } 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(fpath, sb.st_mode, sb.st_rdev);
|
||||
+ rc = fsmMknod(fp->fpath, fp->sb.st_mode, fp->sb.st_rdev);
|
||||
}
|
||||
} else {
|
||||
/* XXX Special case /dev/log, which shouldn't be packaged anyways */
|
||||
- if (!IS_DEV_LOG(fpath))
|
||||
+ if (!IS_DEV_LOG(fp->fpath))
|
||||
rc = RPMERR_UNKNOWN_FILETYPE;
|
||||
}
|
||||
|
||||
touch:
|
||||
/* Set permissions, timestamps etc for non-hardlink entries */
|
||||
if (!rc && setmeta) {
|
||||
- rc = fsmSetmeta(fpath, fi, plugins, action, &sb, nofcaps);
|
||||
+ rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
+ &fp->sb, nofcaps);
|
||||
}
|
||||
} else if (firsthardlink >= 0 && rpmfiArchiveHasContent(fi)) {
|
||||
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
||||
@@ -967,10 +975,10 @@ touch:
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
- if (!skip) {
|
||||
+ if (!fp->skip) {
|
||||
/* XXX only erase if temp fn w suffix is in use */
|
||||
- if (suffix) {
|
||||
- (void) fsmRemove(fpath, sb.st_mode);
|
||||
+ if (fp->suffix) {
|
||||
+ (void) fsmRemove(fp->fpath, fp->sb.st_mode);
|
||||
}
|
||||
errno = saveerrno;
|
||||
}
|
||||
@@ -978,23 +986,22 @@ touch:
|
||||
/* Notify on success. */
|
||||
rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, rpmfiArchiveTell(fi));
|
||||
|
||||
- if (!skip) {
|
||||
+ if (!fp->skip) {
|
||||
/* Backup file if needed. Directories are handled earlier */
|
||||
- if (suffix)
|
||||
- rc = fsmBackup(fi, action);
|
||||
+ if (fp->suffix)
|
||||
+ rc = fsmBackup(fi, fp->action);
|
||||
|
||||
if (!rc)
|
||||
- rc = fsmCommit(&fpath, fi, action, suffix);
|
||||
+ rc = fsmCommit(&fp->fpath, fi, fp->action, fp->suffix);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc)
|
||||
- *failedFile = xstrdup(fpath);
|
||||
+ *failedFile = xstrdup(fp->fpath);
|
||||
|
||||
/* Run fsm file post hook for all plugins */
|
||||
- rpmpluginsCallFsmFilePost(plugins, fi, fpath,
|
||||
- sb.st_mode, action, rc);
|
||||
- fpath = _free(fpath);
|
||||
+ rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
||||
+ fp->sb.st_mode, fp->action, rc);
|
||||
}
|
||||
|
||||
if (!rc && fx != RPMERR_ITER_END)
|
||||
@@ -1010,7 +1017,9 @@ exit:
|
||||
rpmfiFree(fi);
|
||||
Fclose(payload);
|
||||
free(tid);
|
||||
- free(fpath);
|
||||
+ for (int i = 0; i < fc; i++)
|
||||
+ free(fdata[i].fpath);
|
||||
+ free(fdata);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1022,29 +1031,31 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
|
||||
rpmfi fi = rpmfilesIter(files, RPMFI_ITER_BACK);
|
||||
rpmfs fs = rpmteGetFileStates(te);
|
||||
rpmPlugins plugins = rpmtsPlugins(ts);
|
||||
- struct stat sb;
|
||||
+ int fc = rpmfilesFC(files);
|
||||
+ int fx = -1;
|
||||
+ struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
||||
int rc = 0;
|
||||
- char *fpath = NULL;
|
||||
|
||||
- while (!rc && rpmfiNext(fi) >= 0) {
|
||||
- rpmFileAction action = rpmfsGetAction(fs, rpmfiFX(fi));
|
||||
- fpath = fsmFsPath(fi, NULL);
|
||||
- rc = fsmStat(fpath, 1, &sb);
|
||||
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
||||
+ struct filedata_s *fp = &fdata[fx];
|
||||
+ fp->action = rpmfsGetAction(fs, rpmfiFX(fi));
|
||||
+ fp->fpath = fsmFsPath(fi, NULL);
|
||||
+ rc = fsmStat(fp->fpath, 1, &fp->sb);
|
||||
|
||||
- fsmDebug(fpath, action, &sb);
|
||||
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
|
||||
|
||||
/* Run fsm file pre hook for all plugins */
|
||||
- rc = rpmpluginsCallFsmFilePre(plugins, fi, fpath,
|
||||
- sb.st_mode, action);
|
||||
+ rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
||||
+ fp->sb.st_mode, fp->action);
|
||||
|
||||
- if (!XFA_SKIPPING(action))
|
||||
- rc = fsmBackup(fi, action);
|
||||
+ if (!XFA_SKIPPING(fp->action))
|
||||
+ rc = fsmBackup(fi, fp->action);
|
||||
|
||||
/* Remove erased files. */
|
||||
- if (action == FA_ERASE) {
|
||||
+ if (fp->action == FA_ERASE) {
|
||||
int missingok = (rpmfiFFlags(fi) & (RPMFILE_MISSINGOK | RPMFILE_GHOST));
|
||||
|
||||
- rc = fsmRemove(fpath, sb.st_mode);
|
||||
+ rc = fsmRemove(fp->fpath, fp->sb.st_mode);
|
||||
|
||||
/*
|
||||
* Missing %ghost or %missingok entries are not errors.
|
||||
@@ -1069,20 +1080,20 @@ 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"),
|
||||
- S_ISDIR(sb.st_mode) ? _("directory") : _("file"),
|
||||
- fpath, strerror(errno));
|
||||
+ S_ISDIR(fp->sb.st_mode) ? _("directory") : _("file"),
|
||||
+ fp->fpath, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* Run fsm file post hook for all plugins */
|
||||
- rpmpluginsCallFsmFilePost(plugins, fi, fpath,
|
||||
- sb.st_mode, action, rc);
|
||||
+ rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
||||
+ fp->sb.st_mode, fp->action, rc);
|
||||
|
||||
/* XXX Failure to remove is not (yet) cause for failure. */
|
||||
if (!strict_erasures) rc = 0;
|
||||
|
||||
if (rc)
|
||||
- *failedFile = xstrdup(fpath);
|
||||
+ *failedFile = xstrdup(fp->fpath);
|
||||
|
||||
if (rc == 0) {
|
||||
/* Notify on success. */
|
||||
@@ -1090,10 +1101,11 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
|
||||
rpm_loff_t amount = rpmfiFC(fi) - rpmfiFX(fi);
|
||||
rpmpsmNotify(psm, RPMCALLBACK_UNINST_PROGRESS, amount);
|
||||
}
|
||||
- fpath = _free(fpath);
|
||||
}
|
||||
|
||||
- free(fpath);
|
||||
+ for (int i = 0; i < fc; i++)
|
||||
+ free(fdata[i].fpath);
|
||||
+ free(fdata);
|
||||
rpmfiFree(fi);
|
||||
|
||||
return rc;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,112 @@
|
||||
From 210431f18338dfa2d579ea86776cd426a72bf971 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 10:08:27 +0200
|
||||
Subject: [PATCH] Refactor fsmMkfile() to take advantage of the new state
|
||||
struct
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/210431f18338dfa2d579ea86776cd426a72bf971
|
||||
|
||||
Move setmeta into the struct too (we'll want this later anyhow),
|
||||
and now we only need to pass the struct to fsmMkfile(). One less
|
||||
argument to pass around, it has way too many still.
|
||||
|
||||
No functional changes.
|
||||
---
|
||||
lib/fsm.c | 22 +++++++++++-----------
|
||||
1 file changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 9dba30560..80ca234b1 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -39,6 +39,7 @@ static int strict_erasures = 0;
|
||||
#define _filePerms 0644
|
||||
|
||||
struct filedata_s {
|
||||
+ int setmeta;
|
||||
int skip;
|
||||
rpmFileAction action;
|
||||
const char *suffix;
|
||||
@@ -279,8 +280,8 @@ exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
|
||||
- rpmpsm psm, int nodigest, int *setmeta,
|
||||
+static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
+ rpmpsm psm, int nodigest,
|
||||
int * firsthardlink, FD_t *firstlinkfile)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -290,11 +291,11 @@ static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
|
||||
/* Create first hardlinked file empty */
|
||||
if (*firsthardlink < 0) {
|
||||
*firsthardlink = rpmfiFX(fi);
|
||||
- rc = wfd_open(firstlinkfile, dest);
|
||||
+ rc = wfd_open(firstlinkfile, fp->fpath);
|
||||
} else {
|
||||
/* Create hard links for others */
|
||||
char *fn = rpmfilesFN(files, *firsthardlink);
|
||||
- rc = link(fn, dest);
|
||||
+ rc = link(fn, fp->fpath);
|
||||
if (rc < 0) {
|
||||
rc = RPMERR_LINK_FAILED;
|
||||
}
|
||||
@@ -305,14 +306,14 @@ static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
|
||||
existing) file with content */
|
||||
if (numHardlinks<=1) {
|
||||
if (!rc)
|
||||
- rc = expandRegular(fi, dest, psm, nodigest);
|
||||
+ rc = expandRegular(fi, fp->fpath, psm, nodigest);
|
||||
} else if (rpmfiArchiveHasContent(fi)) {
|
||||
if (!rc)
|
||||
rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
|
||||
wfd_close(firstlinkfile);
|
||||
*firsthardlink = -1;
|
||||
} else {
|
||||
- *setmeta = 0;
|
||||
+ fp->setmeta = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -874,6 +875,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
struct filedata_s *fp = &fdata[fx];
|
||||
fp->action = rpmfsGetAction(fs, fx);
|
||||
fp->skip = XFA_SKIPPING(fp->action);
|
||||
+ fp->setmeta = 1;
|
||||
if (fp->action != FA_TOUCH) {
|
||||
fp->suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
||||
} else {
|
||||
@@ -900,8 +902,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
}
|
||||
|
||||
if (!fp->skip) {
|
||||
- int setmeta = 1;
|
||||
-
|
||||
/* Directories replacing something need early backup */
|
||||
if (!fp->suffix) {
|
||||
rc = fsmBackup(fi, fp->action);
|
||||
@@ -927,8 +927,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
|
||||
if (S_ISREG(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
- rc = fsmMkfile(fi, fp->fpath, files, psm, nodigest,
|
||||
- &setmeta, &firsthardlink, &firstlinkfile);
|
||||
+ rc = fsmMkfile(fi, fp, files, psm, nodigest,
|
||||
+ &firsthardlink, &firstlinkfile);
|
||||
}
|
||||
} else if (S_ISDIR(fp->sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
@@ -961,7 +961,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
|
||||
touch:
|
||||
/* Set permissions, timestamps etc for non-hardlink entries */
|
||||
- if (!rc && setmeta) {
|
||||
+ if (!rc && fp->setmeta) {
|
||||
rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
&fp->sb, nofcaps);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
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()
|
||||
|
||||
Conflict:adapt context
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/693d828c035848585b500dfde6f4e58cfb8d4de4
|
||||
|
||||
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 b019f5711..7c4796f74 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;
|
||||
}
|
||||
@@ -867,6 +866,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) {
|
||||
@@ -946,6 +946,9 @@ setmeta:
|
||||
rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
||||
&fp->sb, nofcaps);
|
||||
}
|
||||
+
|
||||
+ if (fd != firstlinkfile)
|
||||
+ fsmClose(&fd);
|
||||
}
|
||||
|
||||
/* Notify on success. */
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
From 505699eb9789543a1b7bcaf8bb654d59b9d2623a Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Thu, 11 Feb 2021 14:06:29 +0200
|
||||
Subject: [PATCH] Streamline + consolidate the hardlink handling logic
|
||||
|
||||
Conflict:delete testcode
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/505699eb9789543a1b7bcaf8bb654d59b9d2623a
|
||||
|
||||
This is one tricksy piece of code, in particular wrt interactions with
|
||||
skipped files. Streamline the logic to make it easier to follow, and
|
||||
consolidate as much as possible inside fsmMkfile() so there's only
|
||||
one place opening, closing and writing to files. Add bunch of tests
|
||||
for partially skipped sets.
|
||||
|
||||
This actually also fixes a case where metadata does not get properly
|
||||
set on a partially skipped hardlink file set (the --excludepath=/foo/zzzz
|
||||
case would fail prior to this)
|
||||
---
|
||||
lib/fsm.c | 80 ++++++++++++++++++++++-----------------------------
|
||||
1 files changed, 35 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index ffafa5d68..bd2481a50 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -297,56 +297,45 @@ static int fsmOpen(FD_t *wfdp, const char *dest)
|
||||
return rc;
|
||||
}
|
||||
|
||||
-/** \ingroup payload
|
||||
- * Create file from payload stream.
|
||||
- * @return 0 on success
|
||||
- */
|
||||
-static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int nodigest)
|
||||
-{
|
||||
- FD_t wfd = NULL;
|
||||
- int rc;
|
||||
-
|
||||
- rc = fsmOpen(&wfd, dest);
|
||||
- if (rc != 0)
|
||||
- goto exit;
|
||||
-
|
||||
- rc = rpmfiArchiveReadToFilePsm(fi, wfd, nodigest, psm);
|
||||
- fsmClose(&wfd);
|
||||
-exit:
|
||||
- return rc;
|
||||
-}
|
||||
-
|
||||
static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
||||
rpmpsm psm, int nodigest,
|
||||
struct filedata_s ** firstlink, FD_t *firstlinkfile)
|
||||
{
|
||||
int rc = 0;
|
||||
- int numHardlinks = rpmfiFNlink(fi);
|
||||
+ FD_t fd = NULL;
|
||||
|
||||
- if (numHardlinks > 1) {
|
||||
- /* Create first hardlinked file empty */
|
||||
- if (*firstlink == NULL) {
|
||||
+ if (*firstlink == NULL) {
|
||||
+ /* First encounter, open file for writing */
|
||||
+ rc = fsmOpen(&fd, fp->fpath);
|
||||
+ /* If it's a part of a hardlinked set, the content may come later */
|
||||
+ if (fp->sb.st_nlink > 1) {
|
||||
*firstlink = fp;
|
||||
- rc = fsmOpen(firstlinkfile, fp->fpath);
|
||||
- } else {
|
||||
- /* Create hard links for others */
|
||||
+ *firstlinkfile = fd;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Create hard links for others and avoid redundant metadata setting */
|
||||
+ if (*firstlink != fp) {
|
||||
rc = fsmLink((*firstlink)->fpath, fp->fpath);
|
||||
+ fp->setmeta = 0;
|
||||
}
|
||||
+ fd = *firstlinkfile;
|
||||
}
|
||||
- /* Write normal files or fill the last hardlinked (already
|
||||
- existing) file with content */
|
||||
- if (numHardlinks<=1) {
|
||||
- if (!rc)
|
||||
- rc = expandRegular(fi, fp->fpath, psm, nodigest);
|
||||
- } else if (rpmfiArchiveHasContent(fi)) {
|
||||
+
|
||||
+ /* If the file has content, unpack it */
|
||||
+ if (rpmfiArchiveHasContent(fi)) {
|
||||
if (!rc)
|
||||
- rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
|
||||
- fsmClose(firstlinkfile);
|
||||
- *firstlink = NULL;
|
||||
- } else {
|
||||
- fp->setmeta = 0;
|
||||
+ rc = rpmfiArchiveReadToFilePsm(fi, fd, nodigest, psm);
|
||||
+ /* Last file of hardlink set, ensure metadata gets set */
|
||||
+ if (*firstlink) {
|
||||
+ (*firstlink)->setmeta = 1;
|
||||
+ *firstlink = NULL;
|
||||
+ *firstlinkfile = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ if (fd != *firstlinkfile)
|
||||
+ fsmClose(&fd);
|
||||
+
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -994,14 +983,15 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
if (!IS_DEV_LOG(fp->fpath))
|
||||
rc = RPMERR_UNKNOWN_FILETYPE;
|
||||
}
|
||||
-
|
||||
- } else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
||||
- /* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
||||
- /* we skip the hard linked file containing the content */
|
||||
- /* write the content to the first used instead */
|
||||
- rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm);
|
||||
- fsmClose(&firstlinkfile);
|
||||
- firstlink = NULL;
|
||||
+ } 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. */
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
From 886c24cfc6c0fec90d8db1406a0e32c0e09e92c9 Mon Sep 17 00:00:00 2001
|
||||
From: Panu Matilainen <pmatilai@redhat.com>
|
||||
Date: Thu, 27 Aug 2020 10:31:07 +0300
|
||||
Subject: [PATCH] Upgrade FA_TOUCH to FA_CREATE if the file went away
|
||||
(RhBug:1872141)
|
||||
|
||||
Conflict:delete testcode
|
||||
Reference:https://github.com/rpm-software-management/rpm/commit/886c24cfc6c0fec90d8db1406a0e32c0e09e92c9
|
||||
|
||||
When %_minimize_writes is enabled, we determine unchanged files during
|
||||
fingerprinting and only update their metadata (FA_TOUCH) instead of
|
||||
always recreating from scratch (FA_CREATE) during install. However
|
||||
package scriptlets (and administrators) can and will do arbitrary stuff
|
||||
in the meanwhile, such as rm -f their own files in %pre, hoping to
|
||||
get a fresh copy of contents no matter what. Or something.
|
||||
Now, if the file was determined to not need changing by rpm, this will
|
||||
just fail with chown & friends trying to touch non-existent file.
|
||||
One can consider this a case of package shooting itself in the foot, but
|
||||
when a package update fails or succeeds depending on %_minimize_writes this
|
||||
to me suggests the feature is at fault as much as the package.
|
||||
|
||||
Do fsmVerify() on all files to be FA_TOUCH'ed to detect files whose
|
||||
type changed or were removed since fingerprinting. This still doesn't
|
||||
ensure correctness if something tampers with the contents in the meanwhile,
|
||||
(for that we'd need to run the file through the whole machinery again,
|
||||
checksumming and all) but covers the most glaring cases.
|
||||
---
|
||||
lib/fsm.c | 15 +++++++++----
|
||||
1 files changed, 11 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/fsm.c b/lib/fsm.c
|
||||
index 5fb507993..08980d49b 100644
|
||||
--- a/lib/fsm.c
|
||||
+++ b/lib/fsm.c
|
||||
@@ -902,10 +902,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
if (!skip) {
|
||||
int setmeta = 1;
|
||||
|
||||
- /* When touching we don't need any of this... */
|
||||
- if (action == FA_TOUCH)
|
||||
- goto touch;
|
||||
-
|
||||
/* Directories replacing something need early backup */
|
||||
if (!suffix) {
|
||||
rc = fsmBackup(fi, action);
|
||||
@@ -917,6 +913,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
||||
rc = RPMERR_ENOENT;
|
||||
}
|
||||
|
||||
+ /* See if the file was removed while our attention was elsewhere */
|
||||
+ if (rc == RPMERR_ENOENT && action == FA_TOUCH) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n", fpath);
|
||||
+ action = FA_CREATE;
|
||||
+ fsmDebug(fpath, action, &sb);
|
||||
+ }
|
||||
+
|
||||
+ /* When touching we don't need any of this... */
|
||||
+ if (action == FA_TOUCH)
|
||||
+ goto touch;
|
||||
+
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
if (rc == RPMERR_ENOENT) {
|
||||
rc = fsmMkfile(fi, fpath, files, psm, nodigest,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
29
rpm.spec
29
rpm.spec
@ -1,6 +1,6 @@
|
||||
Name: rpm
|
||||
Version: 4.15.1
|
||||
Release: 36
|
||||
Release: 37
|
||||
Summary: RPM Package Manager
|
||||
License: GPLv2+
|
||||
URL: http://www.rpm.org/
|
||||
@ -93,6 +93,27 @@ Patch79: backport-0003-CVE-2021-3521.patch
|
||||
Patch80: rpm-selinux-plugin-check-context-file-exist.patch
|
||||
Patch81: backport-Use-root-as-default-UID_0_USER-and-UID_0_GROUP.patch
|
||||
|
||||
Patch82: backport-Upgrade-FA_TOUCH-to-FA_CREATE-if-the-file-went-away-.patch
|
||||
Patch83: backport-Clean-up-file-unpack-iteration-logic-a-bit.patch
|
||||
Patch84: backport-Refactor-file-install-and-remove-around-a-common-str.patch
|
||||
Patch85: backport-Refactor-fsmMkfile-to-take-advantage-of-the-new-stat.patch
|
||||
Patch86: backport-Drop-unused-filename-variable.patch
|
||||
Patch87: backport-Handle-hardlink-tracking-with-a-file-state-pointer.patch
|
||||
Patch88: backport-Handle-file-install-failures-more-gracefully.patch
|
||||
Patch89: backport-Add-hardlink-helper-to-fsm-to-make-it-debuggable.patch
|
||||
Patch90: backport-Make-file-open-and-close-in-fsm-debuggable.patch
|
||||
Patch91: backport-Streamline-consolidate-the-hardlink-handling-logic.patch
|
||||
Patch92: backport-Add-diagnostics-to-archive-unpacking.patch
|
||||
Patch93: backport-Add-optional-callback-on-directory-changes-during-rp.patch
|
||||
Patch94: backport-0001-CVE-2021-35939-CVE-2021-35937.patch
|
||||
Patch95: backport-Consolidate-skipped-hardlink-with-content-case-with-.patch
|
||||
Patch96: backport-Fix-sanitize-the-hardlink-metadata-setting-logic.patch
|
||||
Patch97: backport-Convert-the-file-creation-steps-the-at-family-of-cal.patch
|
||||
Patch98: backport-Bury-rpmio-FD-use-to-fsmUnpack.patch
|
||||
Patch99: backport-Move-file-metadata-setting-back-to-unpack-stage.patch
|
||||
Patch100: backport-Return-descriptor-of-created-file-from-fsmMkfile.patch
|
||||
Patch101: backport-0001-CVE-2021-35938.patch
|
||||
|
||||
BuildRequires: gcc autoconf automake libtool make gawk popt-devel openssl-devel readline-devel libdb-devel
|
||||
BuildRequires: zlib-devel libzstd-devel xz-devel bzip2-devel libarchive-devel ima-evm-utils-devel
|
||||
BuildRequires: dbus-devel fakechroot elfutils-devel elfutils-libelf-devel ima-evm-utils
|
||||
@ -375,6 +396,12 @@ make check || (cat tests/rpmtests.log; exit 0)
|
||||
%{_mandir}/man1/gendiff.1*
|
||||
|
||||
%changelog
|
||||
* Wed Sep 7 2022 xujing<xujing125@huawei.com> - 4.15.1-37
|
||||
- Type:CVE
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2021-35937,CVE-2021-35938,CVE-2021-35939
|
||||
|
||||
* Tue Dec 14 2021 renhongxun<renhongxun@huawei.com> - 4.15.1-36
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user