diff options
author | jbj <devnull@localhost> | 2002-06-20 02:19:21 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2002-06-20 02:19:21 +0000 |
commit | 0a7481d0f777a6fc0e578b31d08312f5376cb125 (patch) | |
tree | dd551f77e9a9fb87499e28b77115ca8ac6603a94 /rpmdb | |
parent | 3255a1e854607cd1f39e3f0688f63eb790387f87 (diff) | |
download | rpm-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.am | 3 | ||||
-rw-r--r-- | rpmdb/legacy.c | 183 | ||||
-rw-r--r-- | rpmdb/legacy.h | 39 |
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. |