summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/fsm.c9
-rw-r--r--tests/data/SPECS/replacetest.spec3
-rw-r--r--tests/rpmreplace.at34
3 files changed, 42 insertions, 4 deletions
diff --git a/lib/fsm.c b/lib/fsm.c
index 659559441..c4164ad4d 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -638,7 +638,7 @@ static int fsmUtime(const char *path, mode_t mode, time_t mtime)
return rc;
}
-static int fsmVerify(const char *path, rpmfi fi)
+static int fsmVerify(const char *path, rpmfi fi, const struct stat *fsb)
{
int rc;
int saveerrno = errno;
@@ -663,11 +663,14 @@ static int fsmVerify(const char *path, rpmfi fi)
} else if (S_ISDIR(mode)) {
if (S_ISDIR(dsb.st_mode)) return 0;
if (S_ISLNK(dsb.st_mode)) {
+ uid_t luid = dsb.st_uid;
rc = fsmStat(path, 0, &dsb);
if (rc == RPMERR_ENOENT) rc = 0;
if (rc) return rc;
errno = saveerrno;
- if (S_ISDIR(dsb.st_mode)) return 0;
+ /* Only permit directory symlinks by target owner and root */
+ if (S_ISDIR(dsb.st_mode) && (luid == 0 || luid == fsb->st_uid))
+ return 0;
}
} else if (S_ISLNK(mode)) {
if (S_ISLNK(dsb.st_mode)) {
@@ -899,7 +902,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
}
/* Assume file does't exist when tmp suffix is in use */
if (!suffix) {
- rc = fsmVerify(fpath, fi);
+ rc = fsmVerify(fpath, fi, &sb);
} else {
rc = RPMERR_ENOENT;
}
diff --git a/tests/data/SPECS/replacetest.spec b/tests/data/SPECS/replacetest.spec
index e8a64e803..c764adc27 100644
--- a/tests/data/SPECS/replacetest.spec
+++ b/tests/data/SPECS/replacetest.spec
@@ -1,5 +1,6 @@
%{!?filetype: %global filetype file}
%{?fixit: %global havepretrans 1}
+%{!?user: %global user root}
Name: replacetest%{?sub:-%{sub}}
Version: %{ver}
@@ -43,5 +44,5 @@ rm -rf $RPM_BUILD_ROOT
%endif
%files
-%defattr(-,root,root,-)
+%defattr(-,%{user},%{user},-)
/opt/*
diff --git a/tests/rpmreplace.at b/tests/rpmreplace.at
index 90a85bfb8..11e6221d7 100644
--- a/tests/rpmreplace.at
+++ b/tests/rpmreplace.at
@@ -402,12 +402,14 @@ runroot rpmbuild --quiet -bb \
--define "ver 1.0" \
--define "filetype datadir" \
--define "filedata README1" \
+ --define "user $(id -u -n)" \
/data/SPECS/replacetest.spec
runroot rpmbuild --quiet -bb \
--define "ver 2.0" \
--define "filetype datadir" \
--define "filedata README2" \
+ --define "user $(id -u -n)" \
/data/SPECS/replacetest.spec
mkdir "${RPMTEST}"/opt/f00f
@@ -421,6 +423,38 @@ test -L "${tf}" && test -d "${tf}"
[])
AT_CLEANUP
+AT_SETUP([upgrade invalid locally symlinked directory])
+AT_KEYWORDS([install])
+AT_CHECK([
+RPMDB_CLEAR
+RPMDB_INIT
+tf="${RPMTEST}"/opt/foo
+rm -rf "${RPMTEST}"/opt/*
+rm -rf "${TOPDIR}"
+
+runroot rpmbuild --quiet -bb \
+ --define "ver 1.0" \
+ --define "filetype datadir" \
+ --define "filedata README1" \
+ /data/SPECS/replacetest.spec
+
+runroot rpmbuild --quiet -bb \
+ --define "ver 2.0" \
+ --define "filetype datadir" \
+ --define "filedata README2" \
+ /data/SPECS/replacetest.spec
+
+mkdir "${RPMTEST}"/opt/f00f
+ln -s f00f "${RPMTEST}"/opt/foo
+runroot rpm -U /build/RPMS/noarch/replacetest-1.0-1.noarch.rpm
+test -L "${tf}" && test -d "${tf}" && runroot rpm -U /build/RPMS/noarch/replacetest-2.0-1.noarch.rpm
+test -d "${tf}"
+],
+[0],
+[],
+[])
+AT_CLEANUP
+
AT_SETUP([upgrade empty directory to broken link])
AT_KEYWORDS([install])
AT_CHECK([