rpm 5.3.12
|
00001 00005 #include "system.h" 00006 00007 #if defined(HAVE_GELF_H) 00008 #if LIBELF_H_LFS_CONFLICT 00009 /* some gelf.h/libelf.h implementations (Solaris) are 00010 * incompatible with the Large File API 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 /*@-incondefs@*/ 00019 typedef long long loff_t; 00020 /*@=incondefs@*/ 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 /*@-compdef -moduncon -noeffectuncon @*/ 00049 static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep) 00050 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00051 /*@modifies *pidp, *fsizep, rpmGlobalMacroContext, 00052 fileSystem, internalState @*/ 00053 { 00054 int fdno; 00055 00056 if (pidp) *pidp = 0; 00057 00058 if (fsizep) { 00059 struct stat sb, * st = &sb; 00060 if (stat(path, st) < 0) 00061 return -1; 00062 *fsizep = (size_t)st->st_size; 00063 } 00064 00065 fdno = open(path, O_RDONLY); 00066 if (fdno < 0) 00067 goto exit; 00068 00069 #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF) 00070 { Elf *elf = NULL; 00071 Elf_Scn *scn = NULL; 00072 Elf_Data *data = NULL; 00073 GElf_Ehdr ehdr; 00074 GElf_Shdr shdr; 00075 GElf_Dyn dyn; 00076 int bingo; 00077 static const char * cmd = NULL; /* XXX memleak */ 00078 static yarnLock oneshot = NULL; /* XXX memleak */ 00079 00080 if (oneshot == NULL) { 00081 cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL); 00082 VALGRIND_HG_CLEAN_MEMORY(cmd, sizeof(cmd)); 00083 oneshot = yarnNewLock(0); 00084 VALGRIND_HG_CLEAN_MEMORY(oneshot, sizeof(oneshot)); 00085 } 00086 yarnPossess(oneshot); 00087 if (!(cmd && *cmd)) 00088 goto elfexit; 00089 00090 (void) elf_version(EV_CURRENT); 00091 00092 /*@-evalorder@*/ 00093 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL 00094 || elf_kind(elf) != ELF_K_ELF 00095 || gelf_getehdr(elf, &ehdr) == NULL 00096 || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC)) 00097 goto elfexit; 00098 /*@=evalorder@*/ 00099 00100 bingo = 0; 00101 while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) { 00102 (void) gelf_getshdr(scn, &shdr); 00103 if (shdr.sh_type != SHT_DYNAMIC) 00104 continue; 00105 while (!bingo && (data = elf_getdata (scn, data)) != NULL) { 00106 unsigned maxndx = (unsigned) (data->d_size / shdr.sh_entsize); 00107 unsigned ndx; 00108 00109 for (ndx = 0; ndx < maxndx; ++ndx) { 00110 /*@-uniondef@*/ 00111 (void) gelf_getdyn (data, ndx, &dyn); 00112 /*@=uniondef@*/ 00113 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST)) 00114 /*@innercontinue@*/ continue; 00115 bingo = 1; 00116 /*@innerbreak@*/ break; 00117 } 00118 } 00119 } 00120 00121 if (pidp != NULL && bingo) { 00122 int pipes[2]; 00123 pid_t pid; 00124 int xx; 00125 00126 xx = close(fdno); 00127 pipes[0] = pipes[1] = -1; 00128 xx = pipe(pipes); 00129 if (!(pid = fork())) { 00130 const char ** av; 00131 int ac; 00132 xx = close(pipes[0]); 00133 xx = dup2(pipes[1], STDOUT_FILENO); 00134 xx = close(pipes[1]); 00135 if (!poptParseArgvString(cmd, &ac, &av)) { 00136 av[ac-1] = path; 00137 av[ac] = NULL; 00138 unsetenv("MALLOC_CHECK_"); 00139 xx = execve(av[0], (char *const *)av+1, environ); 00140 } 00141 _exit(127); 00142 } 00143 *pidp = pid; 00144 fdno = pipes[0]; 00145 xx = close(pipes[1]); 00146 } 00147 00148 elfexit: 00149 if (elf) (void) elf_end(elf); 00150 yarnRelease(oneshot); 00151 } 00152 #endif 00153 00154 exit: 00155 return fdno; 00156 } 00157 /*@=compdef =moduncon =noeffectuncon @*/ 00158 00159 static const char hmackey[] = "orboDeJITITejsirpADONivirpUkvarP"; 00160 00161 int dodigest(int dalgo, const char * fn, unsigned char * digest, 00162 unsigned dflags, size_t *fsizep) 00163 { 00164 int asAscii = dflags & 0x01; 00165 int doHmac = dflags & 0x02; 00166 const char * path; 00167 urltype ut = urlPath(fn, &path); 00168 unsigned char * dsum = NULL; 00169 size_t dlen; 00170 unsigned char buf[32*BUFSIZ]; 00171 FD_t fd; 00172 size_t fsize = 0; 00173 pid_t pid = 0; 00174 int use_mmap; 00175 int rc = 0; 00176 int fdno; 00177 #if defined(HAVE_MMAP) 00178 int xx; 00179 #endif 00180 00181 /*@-globs -internalglobs -mods @*/ 00182 fdno = open_dso(path, &pid, &fsize); 00183 /*@=globs =internalglobs =mods @*/ 00184 if (fdno < 0) { 00185 rc = 1; 00186 goto exit; 00187 } 00188 00189 /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */ 00190 use_mmap = (pid == 0 && fsize <= 0x07ffffff); 00191 00192 switch(ut) { 00193 case URL_IS_PATH: 00194 case URL_IS_UNKNOWN: 00195 #if defined(HAVE_MMAP) 00196 if (use_mmap) { 00197 DIGEST_CTX ctx; 00198 void * mapped = NULL; 00199 00200 if (fsize) { 00201 mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0); 00202 if (mapped == (void *)-1) { 00203 xx = close(fdno); 00204 rc = 1; 00205 break; 00206 } 00207 00208 #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL) 00209 xx = madvise(mapped, fsize, MADV_SEQUENTIAL); 00210 #endif 00211 } 00212 00213 ctx = rpmDigestInit(dalgo, RPMDIGEST_NONE); 00214 if (doHmac) 00215 xx = rpmHmacInit(ctx, hmackey, 0); 00216 if (fsize) 00217 xx = rpmDigestUpdate(ctx, mapped, fsize); 00218 xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii); 00219 if (fsize) 00220 xx = munmap(mapped, fsize); 00221 xx = close(fdno); 00222 break; 00223 } /*@fallthrough@*/ 00224 #endif 00225 case URL_IS_HTTPS: 00226 case URL_IS_HTTP: 00227 case URL_IS_FTP: 00228 case URL_IS_HKP: 00229 case URL_IS_DASH: 00230 default: 00231 /* Either use the pipe to prelink -y or open the URL. */ 00232 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.fdio"); 00233 (void) close(fdno); 00234 if (fd == NULL || Ferror(fd)) { 00235 rc = 1; 00236 if (fd != NULL) 00237 (void) Fclose(fd); 00238 break; 00239 } 00240 00241 fdInitDigest(fd, dalgo, 0); 00242 if (doHmac) 00243 fdInitHmac(fd, hmackey, 0); 00244 fsize = 0; 00245 while ((rc = (int) Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) 00246 fsize += rc; 00247 fdFiniDigest(fd, dalgo, &dsum, &dlen, asAscii); 00248 if (Ferror(fd)) 00249 rc = 1; 00250 00251 (void) Fclose(fd); 00252 break; 00253 } 00254 00255 /* Reap the prelink -y helper. */ 00256 if (pid) { 00257 int status; 00258 /*@+longunsignedintegral@*/ 00259 (void) waitpid(pid, &status, 0); 00260 /*@=longunsignedintegral@*/ 00261 if (!WIFEXITED(status) || WEXITSTATUS(status)) 00262 rc = 1; 00263 } 00264 00265 exit: 00266 if (fsizep) 00267 *fsizep = fsize; 00268 if (!rc) 00269 memcpy(digest, dsum, dlen); 00270 dsum = _free(dsum); 00271 00272 return rc; 00273 }