summaryrefslogtreecommitdiff
path: root/rpmdb
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2002-06-20 02:19:21 +0000
committerjbj <devnull@localhost>2002-06-20 02:19:21 +0000
commit0a7481d0f777a6fc0e578b31d08312f5376cb125 (patch)
treedd551f77e9a9fb87499e28b77115ca8ac6603a94 /rpmdb
parent3255a1e854607cd1f39e3f0688f63eb790387f87 (diff)
downloadrpm-0a7481d0f777a6fc0e578b31d08312f5376cb125.tar.gz
rpm-0a7481d0f777a6fc0e578b31d08312f5376cb125.tar.bz2
rpm-0a7481d0f777a6fc0e578b31d08312f5376cb125.zip
- make sure that rpm can verify prelinked shared libraries.
- don't install /usr/lib/rpm/redhat per-vendor configuration anymore. CVS patchset: 5512 CVS date: 2002/06/20 02:19:21
Diffstat (limited to 'rpmdb')
-rw-r--r--rpmdb/Makefile.am3
-rw-r--r--rpmdb/legacy.c183
-rw-r--r--rpmdb/legacy.h39
3 files changed, 164 insertions, 61 deletions
diff --git a/rpmdb/Makefile.am b/rpmdb/Makefile.am
index 50e579178..9e585219f 100644
--- a/rpmdb/Makefile.am
+++ b/rpmdb/Makefile.am
@@ -8,6 +8,7 @@ INCLUDES = -I. \
-I$(top_srcdir)/rpmio \
-I$(top_srcdir)/beecrypt \
-I$(top_srcdir)/popt \
+ @WITH_LIBELF_INCLUDE@ \
@INCPATH@
EXTRA_DIST = db3.c
@@ -27,7 +28,7 @@ mylibpaths = \
-L$(top_builddir)/rpmio \
-L$(top_builddir)/popt
-mylibs = -lrpm -lrpmio -lpopt @LIBS@ @INTLLIBS@ @LIBMISC@
+mylibs = -lrpm -lrpmio -lpopt @WITH_LIBELF_LIB@ @LIBS@ @INTLLIBS@ @LIBMISC@
LIBS =
DB3LOBJS = $(shell cat $(top_builddir)/$(WITH_DB_SUBDIR)/db3lobjs)
diff --git a/rpmdb/legacy.c b/rpmdb/legacy.c
index d9e84e4d3..1607b452f 100644
--- a/rpmdb/legacy.c
+++ b/rpmdb/legacy.c
@@ -3,78 +3,211 @@
*/
#include "system.h"
+
+#if HAVE_LIBELF_GELF_H
+#include <gelf.h>
+#define DT_GNU_PRELINKED 0x6ffffdf5
+#endif
+
#include "rpmio_internal.h"
#include <rpmlib.h>
+#include <rpmmacro.h>
#include "misc.h"
#include "legacy.h"
#include "debug.h"
#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
-int domd5(const char * fn, unsigned char * digest, int asAscii)
+/**
+ * Open a file descriptor to verify file MD5 and size.
+ * @param path file path
+ * @retval pidp prelink helper pid or 0
+ * @retval fsizep file size
+ * @return -1 on error, otherwise open file descriptor
+ */
+static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep)
+ /*@globals rpmGlobalMacroContext, fileSystem @*/
+ /*@modifies *pidp, *fsizep, rpmGlobalMacroContext, fileSystem @*/
+{
+ static const char * cmd = NULL;
+ static int initted = 0;
+ pid_t pid;
+ int fdno;
+
+ if (!initted) {
+ cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
+ initted++;
+ }
+
+ if (pidp) *pidp = 0;
+
+ if (fsizep) {
+ struct stat sb, * st = &sb;
+ if (stat(path, st) < 0)
+ return -1;
+ *fsizep = st->st_size;
+ }
+
+ fdno = open(path, O_RDONLY);
+ if (fdno < 0)
+ return fdno;
+
+ if (!(cmd && *cmd))
+ return fdno;
+
+#if HAVE_LIBELF_GELF_H && HAVE_LIBELF
+ { Elf *elf = NULL;
+ Elf_Scn *scn = NULL;
+ Elf_Data *data = NULL;
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ GElf_Dyn dyn;
+ int bingo;
+
+ elf_version(EV_CURRENT);
+
+ if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
+ || elf_kind(elf) != ELF_K_ELF
+ || gelf_getehdr(elf, &ehdr) == NULL
+ || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
+ goto exit;
+
+ bingo = 0;
+ while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
+ gelf_getshdr(scn, &shdr);
+ if (shdr.sh_type != SHT_DYNAMIC)
+ continue;
+ while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
+ int maxndx = data->d_size / shdr.sh_entsize;
+ int ndx;
+
+ for (ndx = 0; ndx < maxndx; ++ndx) {
+ gelf_getdyn (data, ndx, &dyn);
+ if (dyn.d_tag != DT_GNU_PRELINKED)
+ continue;
+ bingo = 1;
+ break;
+ }
+ }
+ }
+
+ if (bingo) {
+ int pipes[2];
+ int xx;
+
+ xx = close(fdno);
+ pipes[0] = pipes[1] = -1;
+ xx = pipe(pipes);
+ if (!(pid = fork())) {
+ const char ** av;
+ int ac;
+ xx = close(pipes[0]);
+ xx = dup2(pipes[1], STDOUT_FILENO);
+ xx = close(pipes[1]);
+ if (!poptParseArgvString(cmd, &ac, &av)) {
+ av[ac-1] = path;
+ av[ac] = NULL;
+ xx = execve(av[0], (char *const *)av+1, environ);
+ }
+ _exit(127);
+ }
+ *pidp = pid;
+ fdno = pipes[0];
+ xx = close(pipes[1]);
+ }
+
+exit:
+ if (elf) (void) elf_end(elf);
+ }
+#endif
+
+ return fdno;
+}
+
+int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
{
const char * path;
+ urltype ut = urlPath(fn, &path);
unsigned char * md5sum = NULL;
size_t md5len;
+ unsigned char buf[32*BUFSIZ];
+ FD_t fd;
+ size_t fsize = 0;
+ pid_t pid = 0;
int rc = 0;
+ int fdno;
+ int xx;
- switch(urlPath(fn, &path)) {
+ fdno = open_dso(path, &pid, &fsize);
+ if (fdno < 0) {
+ rc = 1;
+ goto exit;
+ }
+
+ switch(ut) {
case URL_IS_PATH:
case URL_IS_UNKNOWN:
#if HAVE_MMAP
- { struct stat sb, * st = &sb;
+ if (pid == 0) {
DIGEST_CTX ctx;
void * mapped;
- int fdno;
- int xx;
- if (stat(path, st) < 0
- || (fdno = open(path, O_RDONLY)) < 0)
- return 1;
- mapped = mmap(NULL, st->st_size, PROT_READ, MAP_SHARED, fdno, 0);
+ mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
if (mapped == (void *)-1) {
xx = close(fdno);
- return 1;
+ rc = 1;
+ break;
}
#ifdef MADV_SEQUENTIAL
- xx = madvise(mapped, st->st_size, MADV_SEQUENTIAL);
+ xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
#endif
ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
- xx = rpmDigestUpdate(ctx, mapped, st->st_size);
+ xx = rpmDigestUpdate(ctx, mapped, fsize);
xx = rpmDigestFinal(ctx, (void **)&md5sum, &md5len, asAscii);
- xx = munmap(mapped, st->st_size);
+ xx = munmap(mapped, fsize);
xx = close(fdno);
-
- } break;
+ break;
+ } /*@fallthrough@*/
#endif
case URL_IS_FTP:
case URL_IS_HTTP:
case URL_IS_DASH:
default:
- { FD_t fd;
- unsigned char buf[32*BUFSIZ];
-
- fd = Fopen(fn, "r.ufdio");
+ /* Either use the pipe to prelink -y or open the URL. */
+ fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
+ (void) close(fdno);
if (fd == NULL || Ferror(fd)) {
+ rc = 1;
if (fd != NULL)
(void) Fclose(fd);
- return 1;
+ break;
}
-
+
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
-
+ fsize = 0;
while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
- {};
+ fsize += rc;
fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&md5sum, &md5len, asAscii);
-
if (Ferror(fd))
rc = 1;
+
(void) Fclose(fd);
- } break;
+ break;
+ }
+
+ /* Reap the prelink -y helper. */
+ if (pid) {
+ int status;
+ (void) waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status))
+ rc = 1;
}
+exit:
+ if (fsizep)
+ *fsizep = fsize;
if (!rc)
memcpy(digest, md5sum, md5len);
md5sum = _free(md5sum);
diff --git a/rpmdb/legacy.h b/rpmdb/legacy.h
index d0c6ac9cc..fcf4e7c85 100644
--- a/rpmdb/legacy.h
+++ b/rpmdb/legacy.h
@@ -18,48 +18,17 @@ extern "C" {
#endif
/**
- * Calculate MD5 sum for file.
- * @todo Eliminate, use beecrypt instead.
+ * Return MD5 sum and size of a file.
* @param fn file name
* @retval digest address of md5sum
* @param asAscii return md5sum as ascii string?
+ * @retval *fsizep file size pointer (or NULL)
* @return 0 on success, 1 on error
*/
-/*@-exportlocal@*/
-int domd5(const char * fn, /*@out@*/ unsigned char * digest, int asAscii)
+int domd5(const char * fn, /*@out@*/ unsigned char * digest, int asAscii,
+ /*@null@*/ /*@out@*/ size_t *fsizep)
/*@globals fileSystem@*/
/*@modifies digest, fileSystem @*/;
-/*@=exportlocal@*/
-
-/**
- * Return MD5 sum of file as ASCII string.
- * @todo Eliminate, use beecrypt instead.
- * @param fn file name
- * @retval digest MD5 digest
- * @return 0 on success, 1 on error
- */
-/*@unused@*/ static inline
-int mdfile(const char * fn, /*@out@*/ unsigned char * digest)
- /*@globals fileSystem@*/
- /*@modifies digest, fileSystem @*/
-{
- return domd5(fn, digest, 1);
-}
-
-/**
- * Return MD5 sum of file as binary data.
- * @todo Eliminate, use beecrypt instead.
- * @param fn file name
- * @retval bindigest MD5 digest
- * @return 0 on success, 1 on error
- */
-/*@unused@*/ static inline
-int mdbinfile(const char * fn, /*@out@*/ unsigned char * bindigest)
- /*@globals fileSystem@*/
- /*@modifies bindigest, fileSystem @*/
-{
- return domd5(fn, bindigest, 0);
-}
/**
* Convert absolute path tag to (dirname,basename,dirindex) tags.