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