diff options
-rw-r--r-- | lib/fsm.c | 29 |
1 files changed, 23 insertions, 6 deletions
@@ -206,11 +206,22 @@ static int fsmSetFCaps(const char *path, const char *captxt) return rc; } +/* Check dest is the same, empty and regular file with writeonly permissions */ +static int linkSane(FD_t wfd, const char *dest) +{ + struct stat sb, lsb; + + return (fstat(Fileno(wfd), &sb) == 0 && sb.st_size == 0 && + (sb.st_mode & ~S_IFMT) == S_IWUSR && + lstat(dest, &lsb) == 0 && S_ISREG(lsb.st_mode) && + sb.st_dev == lsb.st_dev && sb.st_ino == lsb.st_ino); +} + /** \ingroup payload * Create file from payload stream. * @return 0 on success */ -static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int nodigest, int nocontent) +static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int exclusive, int nodigest, int nocontent) { FD_t wfd = NULL; int rc = 0; @@ -218,8 +229,14 @@ static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int nodigest, i /* Create the file with 0200 permissions (write by owner). */ { mode_t old_umask = umask(0577); - wfd = Fopen(dest, "w.ufdio"); + wfd = Fopen(dest, exclusive ? "wx.ufdio" : "a.ufdio"); umask(old_umask); + + /* If reopening, make sure the file is what we expect */ + if (!exclusive && wfd != NULL && !linkSane(wfd, dest)) { + rc = RPMERR_OPEN_FAILED; + goto exit; + } } if (Ferror(wfd)) { rc = RPMERR_OPEN_FAILED; @@ -248,7 +265,7 @@ static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files, /* Create first hardlinked file empty */ if (*firsthardlink < 0) { *firsthardlink = rpmfiFX(fi); - rc = expandRegular(fi, dest, psm, nodigest, 1); + rc = expandRegular(fi, dest, psm, 1, nodigest, 1); } else { /* Create hard links for others */ char *fn = rpmfilesFN(files, *firsthardlink); @@ -263,10 +280,10 @@ 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, 0); + rc = expandRegular(fi, dest, psm, 1, nodigest, 0); } else if (rpmfiArchiveHasContent(fi)) { if (!rc) - rc = expandRegular(fi, dest, psm, nodigest, 0); + rc = expandRegular(fi, dest, psm, 0, nodigest, 0); *firsthardlink = -1; } else { *setmeta = 0; @@ -928,7 +945,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 */ char *fn = rpmfilesFN(files, firsthardlink); - rc = expandRegular(fi, fn, psm, nodigest, 0); + rc = expandRegular(fi, fn, psm, 0, nodigest, 0); firsthardlink = -1; free(fn); } |