Michal Domonkos 671ef9
From bce17e42f2301a88574d757740627480a38d86aa Mon Sep 17 00:00:00 2001
Michal Domonkos 671ef9
From: Michal Domonkos <mdomonko@redhat.com>
Michal Domonkos 671ef9
Date: Fri, 26 Jul 2024 10:44:04 +0200
Michal Domonkos 671ef9
Subject: [PATCH] Fix root relocation regression
Michal Domonkos 671ef9
Michal Domonkos 671ef9
When relocating the root directory, make sure we insert the new path's
Michal Domonkos 671ef9
dirname to dirNames[] even if the root itself is owned by the package.
Michal Domonkos 671ef9
Michal Domonkos 671ef9
This appears to have been the intention from the first version (largely
Michal Domonkos 671ef9
untouched since) of this code as we allow the root to pass through the
Michal Domonkos 671ef9
first checks (by setting len to 0 in that case) as well as the second
Michal Domonkos 671ef9
for loop where we do the relocations.
Michal Domonkos 671ef9
Michal Domonkos 671ef9
This allows fsm to properly create and remove the relocated directory
Michal Domonkos 671ef9
since we're now using fd-based calls (#1919) and the parent directory
Michal Domonkos 671ef9
needs to be opened first.
Michal Domonkos 671ef9
Michal Domonkos 671ef9
No need to do string comparison here, the empty basename signals that
Michal Domonkos 671ef9
we're processing the root directory, so just use that.
Michal Domonkos 671ef9
Michal Domonkos 671ef9
Building a relocatable package that owns the root directory seems to be
Michal Domonkos 671ef9
a handy way to create user-installable packages (see RHEL-28967) and it
Michal Domonkos 671ef9
happened to work before with the path-based calls so this technically
Michal Domonkos 671ef9
was a regression.  Add a test that emulates this use case.
Michal Domonkos 671ef9
Michal Domonkos 671ef9
Backported from commits:
Michal Domonkos 671ef9
31c14ba6610568c2d634647fed1fb57221178da9
Michal Domonkos 671ef9
308ac60677732e9979b9ce11e5a3085906da1901
Michal Domonkos 671ef9
Michal Domonkos 671ef9
Fixes: RHEL-28967
Michal Domonkos 671ef9
---
Michal Domonkos 671ef9
 lib/relocation.c | 14 ++++++++------
Michal Domonkos 671ef9
 1 file changed, 8 insertions(+), 6 deletions(-)
Michal Domonkos 671ef9
Michal Domonkos 671ef9
diff --git a/lib/relocation.c b/lib/relocation.c
Michal Domonkos 671ef9
index 3ba4cfeab..8c35bc1a7 100644
Michal Domonkos 671ef9
--- a/lib/relocation.c
Michal Domonkos 671ef9
+++ b/lib/relocation.c
Michal Domonkos 671ef9
@@ -123,7 +123,7 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,
Michal Domonkos 671ef9
     char ** baseNames;
Michal Domonkos 671ef9
     char ** dirNames;
Michal Domonkos 671ef9
     uint32_t * dirIndexes;
Michal Domonkos 671ef9
-    rpm_count_t fileCount, dirCount;
Michal Domonkos 671ef9
+    rpm_count_t fileCount, dirCount, dirCountOrig;
Michal Domonkos 671ef9
     int nrelocated = 0;
Michal Domonkos 671ef9
     int fileAlloced = 0;
Michal Domonkos 671ef9
     char * fn = NULL;
Michal Domonkos 671ef9
@@ -162,7 +162,7 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,
Michal Domonkos 671ef9
     baseNames = bnames.data;
Michal Domonkos 671ef9
     dirIndexes = dindexes.data;
Michal Domonkos 671ef9
     fileCount = rpmtdCount(&bnames);
Michal Domonkos 671ef9
-    dirCount = rpmtdCount(&dnames);
Michal Domonkos 671ef9
+    dirCount = dirCountOrig = rpmtdCount(&dnames);
Michal Domonkos 671ef9
     /* XXX TODO: use rpmtdDup() instead */
Michal Domonkos 671ef9
     dirNames = dnames.data = duparray(dnames.data, dirCount);
Michal Domonkos 671ef9
     dnames.flags |= RPMTD_PTR_ALLOCED;
Michal Domonkos 671ef9
@@ -179,8 +179,9 @@ void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations,
Michal Domonkos 671ef9
 	rpmFileTypes ft;
Michal Domonkos 671ef9
 	int fnlen;
Michal Domonkos 671ef9
 
Michal Domonkos 671ef9
+	size_t baselen = strlen(baseNames[i]);
Michal Domonkos 671ef9
 	size_t len = maxlen +
Michal Domonkos 671ef9
-		strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;
Michal Domonkos 671ef9
+		strlen(dirNames[dirIndexes[i]]) + baselen + 1;
Michal Domonkos 671ef9
 	if (len >= fileAlloced) {
Michal Domonkos 671ef9
 	    fileAlloced = len * 2;
Michal Domonkos 671ef9
 	    fn = xrealloc(fn, fileAlloced);
Michal Domonkos 671ef9
@@ -242,8 +243,9 @@ assert(fn != NULL);		/* XXX can't happen */
Michal Domonkos 671ef9
 	    continue;
Michal Domonkos 671ef9
 	}
Michal Domonkos 671ef9
 
Michal Domonkos 671ef9
-	/* Relocation on full paths only, please. */
Michal Domonkos 671ef9
-	if (fnlen != len) continue;
Michal Domonkos 671ef9
+	/* Relocation on '/' and full paths only, please. */
Michal Domonkos 671ef9
+	if (baselen && fnlen != len)
Michal Domonkos 671ef9
+	    continue;
Michal Domonkos 671ef9
 
Michal Domonkos 671ef9
 	rpmlog(RPMLOG_DEBUG, "relocating %s to %s\n",
Michal Domonkos 671ef9
 	       fn, relocations[j].newPath);
Michal Domonkos 671ef9
@@ -294,7 +296,7 @@ assert(fn != NULL);		/* XXX can't happen */
Michal Domonkos 671ef9
     }
Michal Domonkos 671ef9
 
Michal Domonkos 671ef9
     /* Finish off by relocating directories. */
Michal Domonkos 671ef9
-    for (i = dirCount - 1; i >= 0; i--) {
Michal Domonkos 671ef9
+    for (i = dirCountOrig - 1; i >= 0; i--) {
Michal Domonkos 671ef9
 	for (j = numRelocations - 1; j >= 0; j--) {
Michal Domonkos 671ef9
 
Michal Domonkos 671ef9
 	    if (relocations[j].oldPath == NULL) /* XXX can't happen */
Michal Domonkos 671ef9
-- 
Michal Domonkos 671ef9
2.45.2
Michal Domonkos 671ef9