[Rpm-maint] [rpm-software-management/rpm] Relocatable packages with plain `/` in `%files` can't be installed as regular user (Issue #3173)
Michal Domonkos
notifications at github.com
Tue Jun 18 15:25:44 UTC 2024
**Describe the bug**
An attempt to install a relocatable package as a regular user that was built from a spec file that contains
```
Prefix: /
%files
%{prefix}
```
results in a failure.
**To Reproduce**
1. Build the following package:
```
Name: reproducer
Version: 0.0.1
Release: 1%{?dist}
Summary: Reproducer for JIRA
License: GPL
Prefix: /
%description
%{summary}.
%install
mkdir -p $RPM_BUILD_ROOT/foo
touch $RPM_BUILD_ROOT/foo/bar
%files
%{prefix}
%changelog
* Wed Mar 13 2024 root
-
```
2. Install the package locally as non-root user:
```
$ rpm -Uhv --prefix $PWD/RPMROOTDIR --dbpath $PWD/RPMDB /path/to/reproducer.rpm
```
**Actual behavior**
```
Verifying... ################################# [100%]
Preparing... ################################# [100%]
Updating / installing...
1:reproducer-0.0.1-1 ################################# [100%]
error: unpacking of archive failed on file [...]/RPMROOTDIR//: cpio: chmod failed - Device or resource busy
error: reproducer-0.0.1-1.x86_64: install failed
```
**Expected behavior**
No failure, package gets installed successfully.
**Environment**
- OS / Distribution: RHEL-9.5 and later
- Version: RPM 4.16.1.3
**Additional context**
This is a regression introduced with fsm rework to use the `*at()` family of calls that was made to address the symlink CVEs (#1919).
The root cause seems to be this:
When processing the payload files, we eventually call `fsmSetmeta()` for the top-level directory `/` which obviously fails for a regular user. This happens despite us already being (via `di.dirfd`) in the right top-level directory `$PWD/RPMROOTDIR`, because `fp->fpath` is set to `/` there and when we pass it to `fchownat(2)`, since the path is absolute, `di.dirfd` is ignored by the function (as per specification).
One fix that works (but I haven't yet thought about its consequences) is simply making sure `fp->fpath` is never an absolute path, i.e. replacing the `/` with a `.`, like so:
```diff
diff --git a/lib/fsm.c b/lib/fsm.c
index 20b270cf5..938a2db1d 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -78,7 +78,7 @@ static int fsmClose(int *wfdp);
static char * fsmFsPath(rpmfi fi, const char * suffix)
{
const char *bn = rpmfiBN(fi);
- return rstrscat(NULL, *bn ? bn : "/", suffix ? suffix : "", NULL);
+ return rstrscat(NULL, *bn ? bn : ".", suffix ? suffix : "", NULL);
}
static int fsmLink(int odirfd, const char *opath, int dirfd, const char *path)
```
This use case comes from a RHEL customer and was filed as https://issues.redhat.com/browse/RHEL-28967.
--
Reply to this email directly or view it on GitHub:
https://github.com/rpm-software-management/rpm/issues/3173
You are receiving this because you are subscribed to this thread.
Message ID: <rpm-software-management/rpm/issues/3173 at github.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rpm.org/pipermail/rpm-maint/attachments/20240618/2e89515b/attachment.html>
More information about the Rpm-maint
mailing list