rpm
4.5
|
00001 00005 #include "system.h" 00006 00007 #if 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 #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 static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep) 00045 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00046 /*@modifies *pidp, *fsizep, rpmGlobalMacroContext, 00047 fileSystem, internalState @*/ 00048 { 00049 /*@only@*/ 00050 static const char * cmd = NULL; 00051 static int initted = 0; 00052 int fdno; 00053 00054 if (!initted) { 00055 cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL); 00056 initted++; 00057 } 00058 00059 /*@-boundswrite@*/ 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 /*@=boundswrite@*/ 00069 00070 fdno = open(path, O_RDONLY); 00071 if (fdno < 0) 00072 return fdno; 00073 00074 /*@-boundsread@*/ 00075 if (!(cmd && *cmd)) 00076 return fdno; 00077 /*@=boundsread@*/ 00078 00079 #if HAVE_GELF_H && HAVE_LIBELF 00080 { Elf *elf = NULL; 00081 Elf_Scn *scn = NULL; 00082 Elf_Data *data = NULL; 00083 GElf_Ehdr ehdr; 00084 GElf_Shdr shdr; 00085 GElf_Dyn dyn; 00086 int bingo; 00087 00088 (void) elf_version(EV_CURRENT); 00089 00090 /*@-evalorder@*/ 00091 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL 00092 || elf_kind(elf) != ELF_K_ELF 00093 || gelf_getehdr(elf, &ehdr) == NULL 00094 || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC)) 00095 goto exit; 00096 /*@=evalorder@*/ 00097 00098 bingo = 0; 00099 /*@-branchstate -uniondef @*/ 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 int maxndx = data->d_size / shdr.sh_entsize; 00106 int ndx; 00107 00108 for (ndx = 0; ndx < maxndx; ++ndx) { 00109 (void) gelf_getdyn (data, ndx, &dyn); 00110 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST)) 00111 /*@innercontinue@*/ continue; 00112 bingo = 1; 00113 /*@innerbreak@*/ break; 00114 } 00115 } 00116 } 00117 /*@=branchstate =uniondef @*/ 00118 00119 /*@-boundswrite@*/ 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 /*@=boundswrite@*/ 00147 00148 exit: 00149 if (elf) (void) elf_end(elf); 00150 } 00151 #endif 00152 00153 return fdno; 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 int xx; 00170 00171 /*@-globs -internalglobs -mods @*/ 00172 fdno = open_dso(path, &pid, &fsize); 00173 /*@=globs =internalglobs =mods @*/ 00174 if (fdno < 0) { 00175 rc = 1; 00176 goto exit; 00177 } 00178 00179 /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */ 00180 use_mmap = (pid == 0 && fsize <= 0x07ffffff); 00181 00182 switch(ut) { 00183 case URL_IS_PATH: 00184 case URL_IS_UNKNOWN: 00185 #if HAVE_MMAP 00186 if (use_mmap) { 00187 DIGEST_CTX ctx; 00188 void * mapped = NULL; 00189 00190 if (fsize) { 00191 mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0); 00192 if (mapped == (void *)-1) { 00193 xx = close(fdno); 00194 rc = 1; 00195 break; 00196 } 00197 00198 #ifdef MADV_SEQUENTIAL 00199 xx = madvise(mapped, fsize, MADV_SEQUENTIAL); 00200 #endif 00201 } 00202 00203 ctx = rpmDigestInit(digestalgo, RPMDIGEST_NONE); 00204 if (fsize) 00205 xx = rpmDigestUpdate(ctx, mapped, fsize); 00206 xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii); 00207 if (fsize) 00208 xx = munmap(mapped, fsize); 00209 xx = close(fdno); 00210 break; 00211 } /*@fallthrough@*/ 00212 #endif 00213 case URL_IS_HTTPS: 00214 case URL_IS_HTTP: 00215 case URL_IS_FTP: 00216 case URL_IS_HKP: 00217 case URL_IS_DASH: 00218 default: 00219 /* Either use the pipe to prelink -y or open the URL. */ 00220 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r"); 00221 (void) close(fdno); 00222 if (fd == NULL || Ferror(fd)) { 00223 rc = 1; 00224 if (fd != NULL) 00225 (void) Fclose(fd); 00226 break; 00227 } 00228 00229 fdInitDigest(fd, digestalgo, 0); 00230 fsize = 0; 00231 while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) 00232 fsize += rc; 00233 fdFiniDigest(fd, digestalgo, &dsum, &dlen, asAscii); 00234 if (Ferror(fd)) 00235 rc = 1; 00236 00237 (void) Fclose(fd); 00238 break; 00239 } 00240 00241 /* Reap the prelink -y helper. */ 00242 if (pid) { 00243 int status; 00244 (void) waitpid(pid, &status, 0); 00245 if (!WIFEXITED(status) || WEXITSTATUS(status)) 00246 rc = 1; 00247 } 00248 00249 exit: 00250 /*@-boundswrite@*/ 00251 if (fsizep) 00252 *fsizep = fsize; 00253 if (!rc) 00254 memcpy(digest, dsum, dlen); 00255 /*@=boundswrite@*/ 00256 dsum = _free(dsum); 00257 00258 return rc; 00259 } 00260 00261 int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep) 00262 { 00263 return dodigest(PGPHASHALGO_MD5, fn, digest, asAscii, fsizep); 00264 } 00265 00266 void rpmfiBuildFNames(Header h, rpmTag tagN, 00267 /*@out@*/ const char *** fnp, /*@out@*/ int * fcp) 00268 { 00269 HGE_t hge = (HGE_t)headerGetEntryMinMemory; 00270 HFD_t hfd = headerFreeData; 00271 const char ** baseNames; 00272 const char ** dirNames; 00273 int * dirIndexes; 00274 int count; 00275 const char ** fileNames; 00276 int size; 00277 rpmTag dirNameTag = 0; 00278 rpmTag dirIndexesTag = 0; 00279 rpmTagType bnt, dnt; 00280 char * t; 00281 int i, xx; 00282 00283 if (tagN == RPMTAG_BASENAMES) { 00284 dirNameTag = RPMTAG_DIRNAMES; 00285 dirIndexesTag = RPMTAG_DIRINDEXES; 00286 } else if (tagN == RPMTAG_ORIGBASENAMES) { 00287 dirNameTag = RPMTAG_ORIGDIRNAMES; 00288 dirIndexesTag = RPMTAG_ORIGDIRINDEXES; 00289 } 00290 00291 if (!hge(h, tagN, &bnt, &baseNames, &count)) { 00292 if (fnp) *fnp = NULL; 00293 if (fcp) *fcp = 0; 00294 return; /* no file list */ 00295 } 00296 00297 xx = hge(h, dirNameTag, &dnt, &dirNames, NULL); 00298 xx = hge(h, dirIndexesTag, NULL, &dirIndexes, &count); 00299 00300 size = sizeof(*fileNames) * count; 00301 for (i = 0; i < count; i++) { 00302 const char * dn = NULL; 00303 (void) urlPath(dirNames[dirIndexes[i]], &dn); 00304 size += strlen(baseNames[i]) + strlen(dn) + 1; 00305 } 00306 00307 fileNames = xmalloc(size); 00308 t = ((char *) fileNames) + (sizeof(*fileNames) * count); 00309 /*@-branchstate@*/ 00310 for (i = 0; i < count; i++) { 00311 const char * dn = NULL; 00312 fileNames[i] = t; 00313 (void) urlPath(dirNames[dirIndexes[i]], &dn); 00314 t = stpcpy( stpcpy(t, dn), baseNames[i]); 00315 *t++ = '\0'; 00316 } 00317 /*@=branchstate@*/ 00318 baseNames = hfd(baseNames, bnt); 00319 dirNames = hfd(dirNames, dnt); 00320 00321 /*@-branchstate@*/ 00322 if (fnp) 00323 *fnp = fileNames; 00324 else 00325 fileNames = _free(fileNames); 00326 /*@=branchstate@*/ 00327 if (fcp) *fcp = count; 00328 }