summaryrefslogtreecommitdiff
path: root/lib/fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fsm.c')
-rw-r--r--lib/fsm.c9
1 files changed, 6 insertions, 3 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;
}