dcavalca / rpms / rpm

Forked from rpms/rpm a year ago
Clone

Blame 0001-Fix-FA_TOUCH-on-files-with-suid-sgid-bits-and-or-cap.patch

James Antill ee2eaf
From 13f70e3710b2df49a923cc6450ff4a8f86e65666 Mon Sep 17 00:00:00 2001
James Antill ee2eaf
Message-Id: <13f70e3710b2df49a923cc6450ff4a8f86e65666.1555050140.git.pmatilai@redhat.com>
James Antill ee2eaf
From: Panu Matilainen <pmatilai@redhat.com>
James Antill ee2eaf
Date: Wed, 20 Mar 2019 12:38:00 +0200
James Antill ee2eaf
Subject: [PATCH] Fix FA_TOUCH on files with suid/sgid bits and/or capabilities
James Antill ee2eaf
James Antill ee2eaf
FA_TOUCH used to set suffix to "" instead of NULL which causes fsmCommit()
James Antill ee2eaf
to rename the file onto itself, which is a bit dumb but mostly harmless
James Antill ee2eaf
with regular permission. On suid/sgid/capabilities we strip any extra
James Antill ee2eaf
privileges on rename to make sure hardlinks are neutered, and because
James Antill ee2eaf
rename occurs after other permissions etc setting, on FA_TOUCH those
James Antill ee2eaf
extra privileges are stripped and much brokenness will follow.
James Antill ee2eaf
James Antill ee2eaf
A more minimal fix would be a strategically placed strcmp(), but NULL
James Antill ee2eaf
is what the rest of the fsm expects for no suffix and differentiating
James Antill ee2eaf
between empty and NULL suffix is too subtle for its own good as
James Antill ee2eaf
witnessed here. So now, NULL suffix is no suffix again and the rest
James Antill ee2eaf
of the code will do the right thing except where related to creation,
James Antill ee2eaf
and creation is what FA_TOUCH wont do so lets just explicitly skip it
James Antill ee2eaf
and restore the original code otherwise. The goto is ugly but reindenting
James Antill ee2eaf
gets even uglier, shrug. Add a test-case to go with it.
James Antill ee2eaf
James Antill ee2eaf
This has been broken since its introduction in commit
James Antill ee2eaf
79ca74e15e15c1d91a9a31a9ee90abc91736f390 so all current 4.14.x versions
James Antill ee2eaf
are affected.
James Antill ee2eaf
---
James Antill ee2eaf
 lib/fsm.c                         | 17 ++++++++++----
James Antill ee2eaf
 tests/data/SPECS/replacetest.spec |  2 +-
James Antill ee2eaf
 tests/rpmverify.at                | 38 ++++++++++++++++++++++++++++++-
James Antill ee2eaf
 3 files changed, 50 insertions(+), 7 deletions(-)
James Antill ee2eaf
James Antill ee2eaf
diff --git a/lib/fsm.c b/lib/fsm.c
James Antill ee2eaf
index 8eb2c185c..432bcbd90 100644
James Antill ee2eaf
--- a/lib/fsm.c
James Antill ee2eaf
+++ b/lib/fsm.c
James Antill ee2eaf
@@ -898,12 +898,12 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
James Antill ee2eaf
 
James Antill ee2eaf
 	action = rpmfsGetAction(fs, rpmfiFX(fi));
James Antill ee2eaf
 	skip = XFA_SKIPPING(action);
James Antill ee2eaf
-	suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
James Antill ee2eaf
 	if (action != FA_TOUCH) {
James Antill ee2eaf
-	    fpath = fsmFsPath(fi, suffix);
James Antill ee2eaf
+	    suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
James Antill ee2eaf
 	} else {
James Antill ee2eaf
-	    fpath = fsmFsPath(fi, "");
James Antill ee2eaf
+	    suffix = NULL;
James Antill ee2eaf
 	}
James Antill ee2eaf
+	fpath = fsmFsPath(fi, suffix);
James Antill ee2eaf
 
James Antill ee2eaf
 	/* Remap file perms, owner, and group. */
James Antill ee2eaf
 	rc = rpmfiStat(fi, 1, &sb);
James Antill ee2eaf
@@ -926,6 +926,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
James Antill ee2eaf
         if (!skip) {
James Antill ee2eaf
 	    int setmeta = 1;
James Antill ee2eaf
 
James Antill ee2eaf
+	    /* When touching we don't need any of this... */
James Antill ee2eaf
+	    if (action == FA_TOUCH)
James Antill ee2eaf
+		goto touch;
James Antill ee2eaf
+
James Antill ee2eaf
 	    /* Directories replacing something need early backup */
James Antill ee2eaf
 	    if (!suffix) {
James Antill ee2eaf
 		rc = fsmBackup(fi, action);
James Antill ee2eaf
@@ -934,7 +938,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
James Antill ee2eaf
 	    if (!suffix) {
James Antill ee2eaf
 		rc = fsmVerify(fpath, fi);
James Antill ee2eaf
 	    } else {
James Antill ee2eaf
-		rc = (action == FA_TOUCH) ? 0 : RPMERR_ENOENT;
James Antill ee2eaf
+		rc = RPMERR_ENOENT;
James Antill ee2eaf
 	    }
James Antill ee2eaf
 
James Antill ee2eaf
             if (S_ISREG(sb.st_mode)) {
James Antill ee2eaf
@@ -970,11 +974,14 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
James Antill ee2eaf
                 if (!IS_DEV_LOG(fpath))
James Antill ee2eaf
                     rc = RPMERR_UNKNOWN_FILETYPE;
James Antill ee2eaf
             }
James Antill ee2eaf
+
James Antill ee2eaf
+touch:
James Antill ee2eaf
 	    /* Set permissions, timestamps etc for non-hardlink entries */
James Antill ee2eaf
 	    if (!rc && setmeta) {
James Antill ee2eaf
 		rc = fsmSetmeta(fpath, fi, plugins, action, &sb, nofcaps);
James Antill ee2eaf
 	    }
James Antill ee2eaf
         } else if (firsthardlink >= 0 && rpmfiArchiveHasContent(fi)) {
James Antill ee2eaf
+	    /* On FA_TOUCH no hardlinks are created thus this is skipped. */
James Antill ee2eaf
 	    /* we skip the hard linked file containing the content */
James Antill ee2eaf
 	    /* write the content to the first used instead */
James Antill ee2eaf
 	    char *fn = rpmfilesFN(files, firsthardlink);
James Antill ee2eaf
@@ -987,7 +994,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
James Antill ee2eaf
         if (rc) {
James Antill ee2eaf
             if (!skip) {
James Antill ee2eaf
                 /* XXX only erase if temp fn w suffix is in use */
James Antill ee2eaf
-                if (suffix && (action != FA_TOUCH)) {
James Antill ee2eaf
+                if (suffix) {
James Antill ee2eaf
 		    (void) fsmRemove(fpath, sb.st_mode);
James Antill ee2eaf
                 }
James Antill ee2eaf
                 errno = saveerrno;
James Antill ee2eaf
diff --git a/tests/data/SPECS/replacetest.spec b/tests/data/SPECS/replacetest.spec
James Antill ee2eaf
index 54974567b..d5a1729d3 100644
James Antill ee2eaf
--- a/tests/data/SPECS/replacetest.spec
James Antill ee2eaf
+++ b/tests/data/SPECS/replacetest.spec
James Antill ee2eaf
@@ -46,4 +46,4 @@ rm -rf $RPM_BUILD_ROOT
James Antill ee2eaf
 
James Antill ee2eaf
 %files
James Antill ee2eaf
 %defattr(-,%{user},%{grp},-)
James Antill ee2eaf
-/opt/*
James Antill ee2eaf
+%{?fileattr} /opt/*
James Antill ee2eaf
diff --git a/tests/rpmverify.at b/tests/rpmverify.at
James Antill ee2eaf
index 52ee2abfb..f7dd57531 100644
James Antill ee2eaf
--- a/tests/rpmverify.at
James Antill ee2eaf
+++ b/tests/rpmverify.at
James Antill ee2eaf
@@ -575,3 +575,39 @@
James Antill ee2eaf
 ],
James Antill ee2eaf
 [])
James Antill ee2eaf
 AT_CLEANUP
James Antill ee2eaf
+
James Antill ee2eaf
+AT_SETUP([Upgraded verification with min_writes 5 (suid files)])
James Antill ee2eaf
+AT_KEYWORDS([upgrade verify min_writes])
James Antill ee2eaf
+AT_CHECK([
James Antill ee2eaf
+RPMDB_CLEAR
James Antill ee2eaf
+RPMDB_INIT
James Antill ee2eaf
+tf="${RPMTEST}"/opt/foo
James Antill ee2eaf
+rm -rf "${tf}" "${tf}".rpm*
James Antill ee2eaf
+rm -rf "${TOPDIR}"
James Antill ee2eaf
+
James Antill ee2eaf
+for v in "1.0" "2.0"; do
James Antill ee2eaf
+    runroot rpmbuild --quiet -bb \
James Antill ee2eaf
+        --define "ver $v" \
James Antill ee2eaf
+	--define "filetype file" \
James Antill ee2eaf
+	--define "filedata foo" \
James Antill ee2eaf
+	--define "fileattr %attr(2755,-,-)" \
James Antill ee2eaf
+          /data/SPECS/replacetest.spec
James Antill ee2eaf
+done
James Antill ee2eaf
+
James Antill ee2eaf
+runroot rpm -U /build/RPMS/noarch/replacetest-1.0-1.noarch.rpm
James Antill ee2eaf
+runroot rpm -Va --nouser --nogroup replacetest
James Antill ee2eaf
+runroot rpm -U \
James Antill ee2eaf
+	--define "_minimize_writes 1" \
James Antill ee2eaf
+	 /build/RPMS/noarch/replacetest-2.0-1.noarch.rpm
James Antill ee2eaf
+runroot rpm -Va --nouser --nogroup replacetest
James Antill ee2eaf
+chmod 777 "${tf}"
James Antill ee2eaf
+runroot rpm -U \
James Antill ee2eaf
+	--oldpackage \
James Antill ee2eaf
+	--define "_minimize_writes 1" \
James Antill ee2eaf
+	 /build/RPMS/noarch/replacetest-1.0-1.noarch.rpm
James Antill ee2eaf
+runroot rpm -Va --nouser --nogroup replacetest
James Antill ee2eaf
+],
James Antill ee2eaf
+[0],
James Antill ee2eaf
+[],
James Antill ee2eaf
+[])
James Antill ee2eaf
+AT_CLEANUP
James Antill ee2eaf
-- 
James Antill ee2eaf
2.20.1
James Antill ee2eaf