File safesymlinks.diff of Package rpm

--- ./lib/fsm.c.orig	2018-05-24 14:35:41.136841262 +0000
+++ ./lib/fsm.c	2018-09-19 14:23:49.206077104 +0000
@@ -722,7 +722,7 @@ static int fsmMapAttrs(FSM_t fsm)
  * @param archive	payload archive
  * @return		0 on success
  */
-static int expandRegular(FSM_t fsm, rpmpsm psm, rpmcpio_t archive, int nodigest)
+static int expandRegular(FSM_t fsm, rpmpsm psm, rpmcpio_t archive, int exclusive, int nodigest)
 {
     FD_t wfd = NULL;
     const struct stat * st = &fsm->sb;
@@ -735,7 +735,7 @@ static int expandRegular(FSM_t fsm, rpmp
     /* Create the file with 000 permissions. */
     {
 	mode_t old_umask = umask(0777);
-	wfd = Fopen(fsm->path, "w.ufdio");
+	wfd = Fopen(fsm->path, exclusive ? "wx.ufdio" : "w.ufdio");
 	umask(old_umask);
     }
     if (Ferror(wfd)) {
@@ -1472,11 +1472,14 @@ static int fsmVerify(FSM_t fsm)
     } else if (S_ISDIR(st->st_mode)) {
         if (S_ISDIR(ost->st_mode)) return 0;
         if (S_ISLNK(ost->st_mode)) {
+	    uid_t luid = ost->st_uid;
             rc = fsmStat(fsm->path, 0, &fsm->osb);
             if (rc == CPIOERR_ENOENT) rc = 0;
             if (rc) return rc;
             errno = saveerrno;
-            if (S_ISDIR(ost->st_mode)) return 0;
+	    /* Only permit directory symlinks by target owner and root */
+	    if (S_ISDIR(ost->st_mode) && (luid == 0 || luid == ost->st_uid))
+		return 0;
         }
     } else if (S_ISLNK(st->st_mode)) {
         if (S_ISLNK(ost->st_mode)) {
@@ -1699,7 +1702,7 @@ int rpmPackageFilesInstall(rpmts ts, rpm
             if (S_ISREG(st->st_mode)) {
                 rc = fsmVerify(fsm);
                 if (!(rc == CPIOERR_ENOENT)) return rc;
-                rc = expandRegular(fsm, psm, archive, nodigest);
+                rc = expandRegular(fsm, psm, archive, fsm->suffix ? 1 : 0, nodigest);
             } else if (S_ISDIR(st->st_mode)) {
 		/* Directories replacing something need early backup */
                 rc = fsmBackup(fsm);
--- ./lib/verify.c.orig	2018-05-24 14:35:41.136841262 +0000
+++ ./lib/verify.c	2018-09-19 14:31:10.888882282 +0000
@@ -96,6 +96,18 @@ int rpmVerifyFile(const rpmts ts, const
 	return 1;
     }
 
+    /* If we expected a directory but got a symlink to one, follow the link */
+    if (S_ISDIR(fmode) && S_ISLNK(sb.st_mode)) {
+	struct stat dsb;
+	/* ...if it actually points to a directory  */
+	if (stat(fn, &dsb) == 0 && S_ISDIR(dsb.st_mode)) {
+	    /* ...and is by a legit user, to match fsmVerify() behavior */
+	    if (sb.st_uid == 0 || sb.st_uid == dsb.st_uid) {
+		sb = dsb; /* struct assignment */
+	    }
+	}
+    }
+
     /* Links have no mode, other types have no linkto */
     if (S_ISLNK(sb.st_mode))
 	flags &= ~(RPMVERIFY_MODE);
openSUSE Build Service is sponsored by