Blame 0001-Stop-papering-over-the-security-disaster-known-as-pr.patch

Bernhard M. Wiedemann 9cd258
From 5bc138a7663e471edad24cc662366bc743d3d3e0 Mon Sep 17 00:00:00 2001
Bernhard M. Wiedemann 9cd258
From: Panu Matilainen <pmatilai@redhat.com>
Bernhard M. Wiedemann 9cd258
Date: Fri, 10 May 2019 13:10:00 +0300
Bernhard M. Wiedemann 9cd258
Subject: [PATCH 1/2] Stop papering over the security disaster known as prelink
Bernhard M. Wiedemann 9cd258
Bernhard M. Wiedemann 9cd258
Back in the turn of the century somebody thought it was a neat idea
Bernhard M. Wiedemann 9cd258
to completely compromise system security to improve program start-up
Bernhard M. Wiedemann 9cd258
start-up times a wee bit. Since then, people have thankfully started
Bernhard M. Wiedemann 9cd258
coming to their senses and removed prelink from distros entirely.
Bernhard M. Wiedemann 9cd258
Bernhard M. Wiedemann 9cd258
Lets stop papering over the security disaster: we obviously cannot
Bernhard M. Wiedemann 9cd258
stop people from using prelink, but instead of trying to undo the
Bernhard M. Wiedemann 9cd258
damage for verification purposes, we'll now report such a system as
Bernhard M. Wiedemann 9cd258
compromised. Which is how it should be, IMNSHO.
Bernhard M. Wiedemann 9cd258
Bernhard M. Wiedemann 9cd258
This eliminates a whole lot of extra junk from each and every file
Bernhard M. Wiedemann 9cd258
digest calculation that we do, so it might even show up on somebodys
Bernhard M. Wiedemann 9cd258
performance charts. It also gets rid of libelf dependency outside
Bernhard M. Wiedemann 9cd258
librpmbuild, which is a nice little bonus.
Bernhard M. Wiedemann 9cd258
Bernhard M. Wiedemann 9cd258
Inspired by a patch to eliminate a rendundant double open of regular
Bernhard M. Wiedemann 9cd258
files in rpmDoDigest() from Denys Vlasenko, taken a little further...
Bernhard M. Wiedemann 9cd258
---
Bernhard M. Wiedemann 9cd258
 macros.in           |  10 ---
Bernhard M. Wiedemann 9cd258
 rpmio/Makefile.am   |   1 -
Bernhard M. Wiedemann 9cd258
 rpmio/rpmfileutil.c | 176 +++-----------------------------------------
Bernhard M. Wiedemann 9cd258
 3 files changed, 9 insertions(+), 178 deletions(-)
Bernhard M. Wiedemann 9cd258
Bernhard M. Wiedemann 9cd258
diff --git a/macros.in b/macros.in
Bernhard M. Wiedemann 9cd258
index a6069ee4d..32c453479 100644
Bernhard M. Wiedemann 9cd258
--- a/macros.in
Bernhard M. Wiedemann 9cd258
+++ b/macros.in
Bernhard M. Wiedemann 9cd258
@@ -685,16 +685,6 @@ package or when debugging this package.\
Bernhard M. Wiedemann 9cd258
 #	gpg --batch --no-verbose --verify --no-secmem-warning \
Bernhard M. Wiedemann 9cd258
 #	%{__signature_filename} %{__plaintext_filename}
Bernhard M. Wiedemann 9cd258
 #
Bernhard M. Wiedemann 9cd258
-# XXX rpm-4.1 verifies prelinked libraries using a prelink undo helper.
Bernhard M. Wiedemann 9cd258
-#	Normally this macro is defined in /etc/rpm/macros.prelink, installed
Bernhard M. Wiedemann 9cd258
-#	with the prelink package. If the macro is undefined, then prelinked
Bernhard M. Wiedemann 9cd258
-#	shared libraries contents are MD5 digest verified (as usual), rather
Bernhard M. Wiedemann 9cd258
-#	than MD5 verifying the output of the prelink undo helper.
Bernhard M. Wiedemann 9cd258
-#
Bernhard M. Wiedemann 9cd258
-#	Note: The 2nd token is used as argv[0] and "library" is a
Bernhard M. Wiedemann 9cd258
-#	placeholder that will be deleted and replaced with the appropriate
Bernhard M. Wiedemann 9cd258
-#	library file path.
Bernhard M. Wiedemann 9cd258
-#%__prelink_undo_cmd     /usr/sbin/prelink prelink -y library
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
 # Horowitz Key Protocol server configuration
Bernhard M. Wiedemann 9cd258
 #
Bernhard M. Wiedemann 9cd258
diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am
Bernhard M. Wiedemann 9cd258
index 6024ae4e2..cedd784de 100644
Bernhard M. Wiedemann 9cd258
--- a/rpmio/Makefile.am
Bernhard M. Wiedemann 9cd258
+++ b/rpmio/Makefile.am
Bernhard M. Wiedemann 9cd258
@@ -42,7 +42,6 @@ librpmio_la_LIBADD = \
Bernhard M. Wiedemann 9cd258
 	@WITH_OPENSSL_LIB@ \
Bernhard M. Wiedemann 9cd258
 	@WITH_BZ2_LIB@ \
Bernhard M. Wiedemann 9cd258
 	@WITH_ZLIB_LIB@ \
Bernhard M. Wiedemann 9cd258
-	@WITH_LIBELF_LIB@ \
Bernhard M. Wiedemann 9cd258
 	@WITH_POPT_LIB@ \
Bernhard M. Wiedemann 9cd258
 	@WITH_LZMA_LIB@ \
Bernhard M. Wiedemann 9cd258
 	$(ZSTD_LIBS) \
Bernhard M. Wiedemann 9cd258
diff --git a/rpmio/rpmfileutil.c b/rpmio/rpmfileutil.c
Bernhard M. Wiedemann 9cd258
index 98f19e8a6..4349c64a7 100644
Bernhard M. Wiedemann 9cd258
--- a/rpmio/rpmfileutil.c
Bernhard M. Wiedemann 9cd258
+++ b/rpmio/rpmfileutil.c
Bernhard M. Wiedemann 9cd258
@@ -1,18 +1,5 @@
Bernhard M. Wiedemann 9cd258
 #include "system.h"
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
-#if HAVE_GELF_H
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-#include <gelf.h>
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-#if !defined(DT_GNU_PRELINKED)
Bernhard M. Wiedemann 9cd258
-#define DT_GNU_PRELINKED        0x6ffffdf5
Bernhard M. Wiedemann 9cd258
-#endif
Bernhard M. Wiedemann 9cd258
-#if !defined(DT_GNU_LIBLIST)
Bernhard M. Wiedemann 9cd258
-#define DT_GNU_LIBLIST          0x6ffffef9
Bernhard M. Wiedemann 9cd258
-#endif
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-#endif
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
 #include <sys/types.h>
Bernhard M. Wiedemann 9cd258
 #include <sys/stat.h>
Bernhard M. Wiedemann 9cd258
 #include <sys/wait.h>
Bernhard M. Wiedemann 9cd258
@@ -34,178 +21,33 @@
Bernhard M. Wiedemann 9cd258
 static const char *rpm_config_dir = NULL;
Bernhard M. Wiedemann 9cd258
 static pthread_once_t configDirSet = PTHREAD_ONCE_INIT;
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
-static int is_prelinked(int fdno)
Bernhard M. Wiedemann 9cd258
-{
Bernhard M. Wiedemann 9cd258
-    int prelinked = 0;
Bernhard M. Wiedemann 9cd258
-#if HAVE_GELF_H && HAVE_LIBELF
Bernhard M. Wiedemann 9cd258
-    Elf *elf = NULL;
Bernhard M. Wiedemann 9cd258
-    Elf_Scn *scn = NULL;
Bernhard M. Wiedemann 9cd258
-    Elf_Data *data = NULL;
Bernhard M. Wiedemann 9cd258
-    GElf_Ehdr ehdr;
Bernhard M. Wiedemann 9cd258
-    GElf_Shdr shdr;
Bernhard M. Wiedemann 9cd258
-    GElf_Dyn dyn;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    (void) elf_version(EV_CURRENT);
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL ||
Bernhard M. Wiedemann 9cd258
-	       elf_kind(elf) != ELF_K_ELF || gelf_getehdr(elf, &ehdr) == NULL ||
Bernhard M. Wiedemann 9cd258
-	       !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
Bernhard M. Wiedemann 9cd258
-	goto exit;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    while (!prelinked && (scn = elf_nextscn(elf, scn)) != NULL) {
Bernhard M. Wiedemann 9cd258
-	(void) gelf_getshdr(scn, &shdr);
Bernhard M. Wiedemann 9cd258
-	if (shdr.sh_type != SHT_DYNAMIC || shdr.sh_entsize == 0)
Bernhard M. Wiedemann 9cd258
-	    continue;
Bernhard M. Wiedemann 9cd258
-	while (!prelinked && (data = elf_getdata (scn, data)) != NULL) {
Bernhard M. Wiedemann 9cd258
-	    int maxndx = data->d_size / shdr.sh_entsize;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-            for (int ndx = 0; ndx < maxndx; ++ndx) {
Bernhard M. Wiedemann 9cd258
-		(void) gelf_getdyn (data, ndx, &dyn);
Bernhard M. Wiedemann 9cd258
-		if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
Bernhard M. Wiedemann 9cd258
-		    continue;
Bernhard M. Wiedemann 9cd258
-		prelinked = 1;
Bernhard M. Wiedemann 9cd258
-		break;
Bernhard M. Wiedemann 9cd258
-	    }
Bernhard M. Wiedemann 9cd258
-	}
Bernhard M. Wiedemann 9cd258
-    }
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-exit:
Bernhard M. Wiedemann 9cd258
-    if (elf) (void) elf_end(elf);
Bernhard M. Wiedemann 9cd258
-#endif
Bernhard M. Wiedemann 9cd258
-    return prelinked;
Bernhard M. Wiedemann 9cd258
-}
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-static int open_dso(const char * path, pid_t * pidp, rpm_loff_t *fsizep)
Bernhard M. Wiedemann 9cd258
-{
Bernhard M. Wiedemann 9cd258
-    static const char * cmd = NULL;
Bernhard M. Wiedemann 9cd258
-    static int initted = 0;
Bernhard M. Wiedemann 9cd258
-    int fdno;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    if (!initted) {
Bernhard M. Wiedemann 9cd258
-	cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
Bernhard M. Wiedemann 9cd258
-	initted++;
Bernhard M. Wiedemann 9cd258
-    }
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    if (pidp) *pidp = 0;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    if (fsizep) {
Bernhard M. Wiedemann 9cd258
-	struct stat sb, * st = &sb;
Bernhard M. Wiedemann 9cd258
-	if (stat(path, st) < 0)
Bernhard M. Wiedemann 9cd258
-	    return -1;
Bernhard M. Wiedemann 9cd258
-	*fsizep = st->st_size;
Bernhard M. Wiedemann 9cd258
-    }
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    fdno = open(path, O_RDONLY);
Bernhard M. Wiedemann 9cd258
-    if (fdno < 0)
Bernhard M. Wiedemann 9cd258
-	return fdno;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    if (!(cmd && *cmd))
Bernhard M. Wiedemann 9cd258
-	return fdno;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    if (pidp != NULL && is_prelinked(fdno)) {
Bernhard M. Wiedemann 9cd258
-	int pipes[2];
Bernhard M. Wiedemann 9cd258
-	pid_t pid;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-	close(fdno);
Bernhard M. Wiedemann 9cd258
-	pipes[0] = pipes[1] = -1;
Bernhard M. Wiedemann 9cd258
-	if (pipe(pipes) < 0)
Bernhard M. Wiedemann 9cd258
-	    return -1;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-	pid = fork();
Bernhard M. Wiedemann 9cd258
-	if (pid < 0) {
Bernhard M. Wiedemann 9cd258
-	    close(pipes[0]);
Bernhard M. Wiedemann 9cd258
-	    close(pipes[1]);
Bernhard M. Wiedemann 9cd258
-	    return -1;
Bernhard M. Wiedemann 9cd258
-	}
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-	if (pid == 0) {
Bernhard M. Wiedemann 9cd258
-	    ARGV_t av, lib;
Bernhard M. Wiedemann 9cd258
-	    int dfd;
Bernhard M. Wiedemann 9cd258
-	    argvSplit(&av, cmd, " ");
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-	    close(pipes[0]);
Bernhard M. Wiedemann 9cd258
-	    dfd = dup2(pipes[1], STDOUT_FILENO);
Bernhard M. Wiedemann 9cd258
-	    close(pipes[1]);
Bernhard M. Wiedemann 9cd258
-	    if (dfd >= 0 && (lib = argvSearch(av, "library", NULL)) != NULL) {
Bernhard M. Wiedemann 9cd258
-		*lib = (char *) path;
Bernhard M. Wiedemann 9cd258
-		unsetenv("MALLOC_CHECK_");
Bernhard M. Wiedemann 9cd258
-		execve(av[0], av+1, environ);
Bernhard M. Wiedemann 9cd258
-	    }
Bernhard M. Wiedemann 9cd258
-	    _exit(127); /* not normally reached */
Bernhard M. Wiedemann 9cd258
-	} else {
Bernhard M. Wiedemann 9cd258
-	    *pidp = pid;
Bernhard M. Wiedemann 9cd258
-	    fdno = pipes[0];
Bernhard M. Wiedemann 9cd258
-	    close(pipes[1]);
Bernhard M. Wiedemann 9cd258
-	}
Bernhard M. Wiedemann 9cd258
-    }
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-    return fdno;
Bernhard M. Wiedemann 9cd258
-}
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
 int rpmDoDigest(int algo, const char * fn,int asAscii,
Bernhard M. Wiedemann 9cd258
                 unsigned char * digest, rpm_loff_t * fsizep)
Bernhard M. Wiedemann 9cd258
 {
Bernhard M. Wiedemann 9cd258
-    const char * path;
Bernhard M. Wiedemann 9cd258
-    urltype ut = urlPath(fn, &path);
Bernhard M. Wiedemann 9cd258
     unsigned char * dig = NULL;
Bernhard M. Wiedemann 9cd258
     size_t diglen, buflen = 32 * BUFSIZ;
Bernhard M. Wiedemann 9cd258
     unsigned char *buf = xmalloc(buflen);
Bernhard M. Wiedemann 9cd258
-    FD_t fd;
Bernhard M. Wiedemann 9cd258
     rpm_loff_t fsize = 0;
Bernhard M. Wiedemann 9cd258
-    pid_t pid = 0;
Bernhard M. Wiedemann 9cd258
     int rc = 0;
Bernhard M. Wiedemann 9cd258
-    int fdno;
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
-    fdno = open_dso(path, &pid, &fsize);
Bernhard M. Wiedemann 9cd258
-    if (fdno < 0) {
Bernhard M. Wiedemann 9cd258
-	rc = 1;
Bernhard M. Wiedemann 9cd258
-	goto exit;
Bernhard M. Wiedemann 9cd258
-    }
Bernhard M. Wiedemann 9cd258
+    FD_t fd = Fopen(fn, "r.ufdio");
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
-    switch (ut) {
Bernhard M. Wiedemann 9cd258
-    case URL_IS_PATH:
Bernhard M. Wiedemann 9cd258
-    case URL_IS_UNKNOWN:
Bernhard M. Wiedemann 9cd258
-    case URL_IS_HTTPS:
Bernhard M. Wiedemann 9cd258
-    case URL_IS_HTTP:
Bernhard M. Wiedemann 9cd258
-    case URL_IS_FTP:
Bernhard M. Wiedemann 9cd258
-    case URL_IS_HKP:
Bernhard M. Wiedemann 9cd258
-    case URL_IS_DASH:
Bernhard M. Wiedemann 9cd258
-    default:
Bernhard M. Wiedemann 9cd258
-	/* Either use the pipe to prelink -y or open the URL. */
Bernhard M. Wiedemann 9cd258
-	fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
Bernhard M. Wiedemann 9cd258
-	(void) close(fdno);
Bernhard M. Wiedemann 9cd258
-	if (fd == NULL || Ferror(fd)) {
Bernhard M. Wiedemann 9cd258
-	    rc = 1;
Bernhard M. Wiedemann 9cd258
-	    if (fd != NULL)
Bernhard M. Wiedemann 9cd258
-		(void) Fclose(fd);
Bernhard M. Wiedemann 9cd258
-	    break;
Bernhard M. Wiedemann 9cd258
-	}
Bernhard M. Wiedemann 9cd258
-	
Bernhard M. Wiedemann 9cd258
+    if (fd) {
Bernhard M. Wiedemann 9cd258
 	fdInitDigest(fd, algo, 0);
Bernhard M. Wiedemann 9cd258
-	fsize = 0;
Bernhard M. Wiedemann 9cd258
 	while ((rc = Fread(buf, sizeof(*buf), buflen, fd)) > 0)
Bernhard M. Wiedemann 9cd258
 	    fsize += rc;
Bernhard M. Wiedemann 9cd258
 	fdFiniDigest(fd, algo, (void **)&dig, &diglen, asAscii);
Bernhard M. Wiedemann 9cd258
-	if (dig == NULL || Ferror(fd))
Bernhard M. Wiedemann 9cd258
-	    rc = 1;
Bernhard M. Wiedemann 9cd258
-
Bernhard M. Wiedemann 9cd258
-	(void) Fclose(fd);
Bernhard M. Wiedemann 9cd258
-	break;
Bernhard M. Wiedemann 9cd258
+	Fclose(fd);
Bernhard M. Wiedemann 9cd258
     }
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
-    /* Reap the prelink -y helper. */
Bernhard M. Wiedemann 9cd258
-    if (pid) {
Bernhard M. Wiedemann 9cd258
-	int status;
Bernhard M. Wiedemann 9cd258
-	(void) waitpid(pid, &status, 0);
Bernhard M. Wiedemann 9cd258
-	if (!WIFEXITED(status) || WEXITSTATUS(status))
Bernhard M. Wiedemann 9cd258
-	    rc = 1;
Bernhard M. Wiedemann 9cd258
+    if (dig == NULL || Ferror(fd)) {
Bernhard M. Wiedemann 9cd258
+	rc = 1;
Bernhard M. Wiedemann 9cd258
+    } else {
Bernhard M. Wiedemann 9cd258
+	memcpy(digest, dig, diglen);
Bernhard M. Wiedemann 9cd258
+	if (fsizep)
Bernhard M. Wiedemann 9cd258
+	    *fsizep = fsize;
Bernhard M. Wiedemann 9cd258
     }
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
-exit:
Bernhard M. Wiedemann 9cd258
-    if (fsizep)
Bernhard M. Wiedemann 9cd258
-	*fsizep = fsize;
Bernhard M. Wiedemann 9cd258
-    if (!rc)
Bernhard M. Wiedemann 9cd258
-	memcpy(digest, dig, diglen);
Bernhard M. Wiedemann 9cd258
     dig = _free(dig);
Bernhard M. Wiedemann 9cd258
     free(buf);
Bernhard M. Wiedemann 9cd258
 
Bernhard M. Wiedemann 9cd258
-- 
Bernhard M. Wiedemann 9cd258
2.20.1
Bernhard M. Wiedemann 9cd258