rpm
5.2.1
|
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 /*@only@*/ 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 /*@-evalorder@*/ 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 /*@=evalorder@*/ 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 /*@-uniondef@*/ 00110 (void) gelf_getdyn (data, ndx, &dyn); 00111 /*@=uniondef@*/ 00112 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST)) 00113 /*@innercontinue@*/ continue; 00114 bingo = 1; 00115 /*@innerbreak@*/ 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 /*@=compdef =moduncon =noeffectuncon @*/ 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 /*@-globs -internalglobs -mods @*/ 00174 fdno = open_dso(path, &pid, &fsize); 00175 /*@=globs =internalglobs =mods @*/ 00176 if (fdno < 0) { 00177 rc = 1; 00178 goto exit; 00179 } 00180 00181 /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */ 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 } /*@fallthrough@*/ 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 /* Either use the pipe to prelink -y or open the URL. */ 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 /* Reap the prelink -y helper. */ 00244 if (pid) { 00245 int status; 00246 /*@+longunsignedintegral@*/ 00247 (void) waitpid(pid, &status, 0); 00248 /*@=longunsignedintegral@*/ 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 }