00001
00005 #include "system.h"
00006
00007 #if defined(HAVE_GELF_H)
00008 #if LIBELF_H_LFS_CONFLICT
00009
00010
00011
00012 # undef _LARGEFILE64_SOURCE
00013 # undef _LARGEFILE_SOURCE
00014 # undef _FILE_OFFSET_BITS
00015 # define _FILE_OFFSET_BITS 32
00016 #endif
00017 #include <gelf.h>
00018
00019 #if !defined(DT_GNU_PRELINKED)
00020 #define DT_GNU_PRELINKED 0x6ffffdf5
00021 #endif
00022 #if !defined(DT_GNU_LIBLIST)
00023 #define DT_GNU_LIBLIST 0x6ffffef9
00024 #endif
00025
00026 #endif
00027
00028 #include "rpmio_internal.h"
00029 #include <rpmlib.h>
00030 #include <rpmmacro.h>
00031 #include "misc.h"
00032 #include "legacy.h"
00033 #include "debug.h"
00034
00035 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
00036
00044
00045 static int open_dso(const char * path, pid_t * pidp, size_t *fsizep)
00046
00047
00048
00049 {
00050
00051 static const char * cmd = NULL;
00052 static int oneshot = 0;
00053 int fdno;
00054
00055 if (!oneshot) {
00056 cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
00057 oneshot++;
00058 }
00059
00060 if (pidp) *pidp = 0;
00061
00062 if (fsizep) {
00063 struct stat sb, * st = &sb;
00064 if (stat(path, st) < 0)
00065 return -1;
00066 *fsizep = st->st_size;
00067 }
00068
00069 fdno = open(path, O_RDONLY);
00070 if (fdno < 0)
00071 return fdno;
00072
00073 if (!(cmd && *cmd))
00074 return fdno;
00075
00076 #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF)
00077 { Elf *elf = NULL;
00078 Elf_Scn *scn = NULL;
00079 Elf_Data *data = NULL;
00080 GElf_Ehdr ehdr;
00081 GElf_Shdr shdr;
00082 GElf_Dyn dyn;
00083 int bingo;
00084
00085 (void) elf_version(EV_CURRENT);
00086
00087
00088 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
00089 || elf_kind(elf) != ELF_K_ELF
00090 || gelf_getehdr(elf, &ehdr) == NULL
00091 || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
00092 goto exit;
00093
00094
00095 bingo = 0;
00096 while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
00097 (void) gelf_getshdr(scn, &shdr);
00098 if (shdr.sh_type != SHT_DYNAMIC)
00099 continue;
00100 while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
00101 unsigned maxndx = (unsigned) (data->d_size / shdr.sh_entsize);
00102 unsigned ndx;
00103
00104 for (ndx = 0; ndx < maxndx; ++ndx) {
00105
00106 (void) gelf_getdyn (data, ndx, &dyn);
00107
00108 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
00109 continue;
00110 bingo = 1;
00111 break;
00112 }
00113 }
00114 }
00115
00116 if (pidp != NULL && bingo) {
00117 int pipes[2];
00118 pid_t pid;
00119 int xx;
00120
00121 xx = close(fdno);
00122 pipes[0] = pipes[1] = -1;
00123 xx = pipe(pipes);
00124 if (!(pid = fork())) {
00125 const char ** av;
00126 int ac;
00127 xx = close(pipes[0]);
00128 xx = dup2(pipes[1], STDOUT_FILENO);
00129 xx = close(pipes[1]);
00130 if (!poptParseArgvString(cmd, &ac, &av)) {
00131 av[ac-1] = path;
00132 av[ac] = NULL;
00133 unsetenv("MALLOC_CHECK_");
00134 xx = execve(av[0], (char *const *)av+1, environ);
00135 }
00136 _exit(127);
00137 }
00138 *pidp = pid;
00139 fdno = pipes[0];
00140 xx = close(pipes[1]);
00141 }
00142
00143 exit:
00144 if (elf) (void) elf_end(elf);
00145 }
00146 #endif
00147
00148 return fdno;
00149 }
00150
00151
00152 int dodigest(int digestalgo, const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
00153 {
00154 const char * path;
00155 urltype ut = urlPath(fn, &path);
00156 unsigned char * dsum = NULL;
00157 size_t dlen;
00158 unsigned char buf[32*BUFSIZ];
00159 FD_t fd;
00160 size_t fsize = 0;
00161 pid_t pid = 0;
00162 int use_mmap;
00163 int rc = 0;
00164 int fdno;
00165 #if defined(HAVE_MMAP)
00166 int xx;
00167 #endif
00168
00169
00170 fdno = open_dso(path, &pid, &fsize);
00171
00172 if (fdno < 0) {
00173 rc = 1;
00174 goto exit;
00175 }
00176
00177
00178 use_mmap = (pid == 0 && fsize <= 0x07ffffff);
00179
00180 switch(ut) {
00181 case URL_IS_PATH:
00182 case URL_IS_UNKNOWN:
00183 #if defined(HAVE_MMAP)
00184 if (use_mmap) {
00185 DIGEST_CTX ctx;
00186 void * mapped = NULL;
00187
00188 if (fsize) {
00189 mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
00190 if (mapped == (void *)-1) {
00191 xx = close(fdno);
00192 rc = 1;
00193 break;
00194 }
00195
00196 #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL)
00197 xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
00198 #endif
00199 }
00200
00201 ctx = rpmDigestInit(digestalgo, RPMDIGEST_NONE);
00202 if (fsize)
00203 xx = rpmDigestUpdate(ctx, mapped, fsize);
00204 xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii);
00205 if (fsize)
00206 xx = munmap(mapped, fsize);
00207 xx = close(fdno);
00208 break;
00209 }
00210 #endif
00211 case URL_IS_HTTPS:
00212 case URL_IS_HTTP:
00213 case URL_IS_FTP:
00214 case URL_IS_HKP:
00215 case URL_IS_DASH:
00216 default:
00217
00218 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.fdio");
00219 (void) close(fdno);
00220 if (fd == NULL || Ferror(fd)) {
00221 rc = 1;
00222 if (fd != NULL)
00223 (void) Fclose(fd);
00224 break;
00225 }
00226
00227 fdInitDigest(fd, digestalgo, 0);
00228 fsize = 0;
00229 while ((rc = (int) Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00230 fsize += rc;
00231 fdFiniDigest(fd, digestalgo, &dsum, &dlen, asAscii);
00232 if (Ferror(fd))
00233 rc = 1;
00234
00235 (void) Fclose(fd);
00236 break;
00237 }
00238
00239
00240 if (pid) {
00241 int status;
00242 (void) waitpid(pid, &status, 0);
00243 if (!WIFEXITED(status) || WEXITSTATUS(status))
00244 rc = 1;
00245 }
00246
00247 exit:
00248 if (fsizep)
00249 *fsizep = fsize;
00250 if (!rc)
00251 memcpy(digest, dsum, dlen);
00252 dsum = _free(dsum);
00253
00254 return rc;
00255 }
00256
00257 int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
00258 {
00259 return dodigest(PGPHASHALGO_MD5, fn, digest, asAscii, fsizep);
00260 }