File sbitcheck.diff of Package rpm

When deleting files, drop any s-bit first, so that a malicious
user does not have access to old programs if he hard links them
to some other directory. [#50376] rh#125517

Already in rpm-4.4.7.

Index: lib/cpio.h
===================================================================
--- lib/cpio.h.orig
+++ lib/cpio.h
@@ -64,7 +64,8 @@ typedef enum cpioMapFlags_e {
     CPIO_MAP_ABSOLUTE	= (1 << 5),
     CPIO_MAP_ADDDOT	= (1 << 6),
     CPIO_ALL_HARDLINKS	= (1 << 7), /*!< fail if hardlinks are missing. */
-    CPIO_MAP_TYPE	= (1 << 8)  /*!< only for building. */
+    CPIO_MAP_TYPE	= (1 << 8),  /*!< only for building. */
+    CPIO_SBIT_CHECK	= (1 << 9)
 } cpioMapFlags;
 
 #define CPIO_NEWC_MAGIC	"070701"
Index: lib/fsm.c
===================================================================
--- lib/fsm.c.orig
+++ lib/fsm.c
@@ -2127,6 +2127,11 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS
 	/*@notreached@*/ break;
 
     case FSM_UNLINK:
+	if (fsm->mapFlags & CPIO_SBIT_CHECK) {
+	    struct stat stb;
+	    if (Lstat(fsm->path, &stb) == 0 && S_ISREG(stb.st_mode) && (stb.st_mode & 06000) != 0)
+		chmod(fsm->path, stb.st_mode & 0777);
+	}
 	rc = Unlink(fsm->path);
 	if (_fsm_debug && (stage & FSM_SYSCALL))
 	    rpmMessage(RPMMESS_DEBUG, " %8s (%s) %s\n", cur,
Index: lib/psm.c
===================================================================
--- lib/psm.c.orig
+++ lib/psm.c
@@ -1472,7 +1472,7 @@ assert(psm->mi == NULL);
 		fi->striplen = (xx ? strlen(p) + 1 : 1);
 	    }
 	    fi->mapflags =
-		CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
+		CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID | (fi->mapflags & CPIO_SBIT_CHECK);
 	
 	    if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
 		rpmfiBuildFNames(fi->h, RPMTAG_ORIGBASENAMES, &fi->apath, NULL);
Index: lib/transaction.c
===================================================================
--- lib/transaction.c.orig
+++ lib/transaction.c
@@ -187,6 +187,13 @@ static int handleInstInstalledFiles(cons
 	if (XFA_SKIPPING(fi->actions[fileNum]))
 	    continue;
 
+	if (!(fi->mapflags & CPIO_SBIT_CHECK)) {
+	    int_16 omode = rpmfiFMode(otherFi);
+	    if (S_ISREG(omode) && (omode & 06000) != 0) {
+		fi->mapflags |= CPIO_SBIT_CHECK;
+	    }
+	}
+
 	if (rpmfiCompare(otherFi, fi)) {
 	    int rConflicts;
 
@@ -1843,6 +1850,20 @@ rpmMessage(RPMMESS_DEBUG, _("computing f
 	case TR_REMOVED:
 	    /*@switchbreak@*/ break;
 	}
+	/* check for s-bit files to be removed */
+	if (rpmteType(p) == TR_REMOVED) {
+	    fi = rpmfiInit(fi, 0);
+	    while ((i = rpmfiNext(fi)) >= 0) {
+		int_16 mode;
+		if (XFA_SKIPPING(fi->actions[i]))
+		    continue;
+		(void) rpmfiSetFX(fi, i);
+		mode = rpmfiFMode(fi);
+		if (S_ISREG(mode) && (mode & 06000) != 0) {
+		    fi->mapflags |= CPIO_SBIT_CHECK;
+		}
+	    }
+	}
 	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
     }
     pi = rpmtsiFree(pi);
@@ -2088,6 +2109,7 @@ assert(psm != NULL);
 		{
 		    char * fstates = fi->fstates;
 		    fileAction * actions = fi->actions;
+		    int mapflags = fi->mapflags;
 		    rpmte savep;
 
 		    fi->fstates = NULL;
@@ -2106,6 +2128,8 @@ assert(psm != NULL);
 			fi->fstates = fstates;
 			fi->actions = _free(fi->actions);
 			fi->actions = actions;
+			if (mapflags & CPIO_SBIT_CHECK)
+			    fi->mapflags |= CPIO_SBIT_CHECK;
 			p->fi = fi;
 		    }
 		}
openSUSE Build Service is sponsored by