diff options
-rw-r--r-- | lib/fsm.c | 9 | ||||
-rw-r--r-- | tests/data/SPECS/replacetest.spec | 3 | ||||
-rw-r--r-- | tests/rpmreplace.at | 34 |
3 files changed, 42 insertions, 4 deletions
@@ -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([ |