|
rpm
5.4.4
|
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 pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; 00078 static yarnLock oneshot = NULL; /* XXX memleak */ 00079 static const char ** cmd_av = NULL; /* XXX memleak */ 00080 static int cmd_ac = 0; 00081 int xx; 00082 00083 xx = pthread_mutex_lock(&_mutex); 00084 if (oneshot == NULL) 00085 oneshot = yarnNewLock(0); 00086 if (cmd_av == NULL) { 00087 const char * cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL); 00088 (void) poptParseArgvString(cmd, &cmd_ac, &cmd_av); 00089 cmd = _free(cmd); 00090 } 00091 xx = pthread_mutex_unlock(&_mutex); 00092 00093 if (cmd_ac == 0) 00094 goto exit; 00095 00096 yarnPossess(oneshot); /* XXX thread-safe iff compiled w USE_LOCKS */ 00097 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); 00098 (void) elf_version(EV_CURRENT); 00099 00100 /*@-evalorder@*/ 00101 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL 00102 || elf_kind(elf) != ELF_K_ELF 00103 || gelf_getehdr(elf, &ehdr) == NULL 00104 || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC)) 00105 { 00106 if (elf) (void) elf_end(elf); 00107 ANNOTATE_IGNORE_READS_AND_WRITES_END(); 00108 yarnRelease(oneshot); 00109 goto exit; 00110 } 00111 /*@=evalorder@*/ 00112 00113 bingo = 0; 00114 while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) { 00115 (void) gelf_getshdr(scn, &shdr); 00116 if (shdr.sh_type != SHT_DYNAMIC) 00117 continue; 00118 while (!bingo && (data = elf_getdata (scn, data)) != NULL) { 00119 unsigned maxndx = (unsigned) (data->d_size / shdr.sh_entsize); 00120 unsigned ndx; 00121 00122 for (ndx = 0; ndx < maxndx; ++ndx) { 00123 /*@-uniondef@*/ 00124 (void) gelf_getdyn (data, ndx, &dyn); 00125 /*@=uniondef@*/ 00126 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST)) 00127 /*@innercontinue@*/ continue; 00128 bingo = 1; 00129 /*@innerbreak@*/ break; 00130 } 00131 } 00132 } 00133 00134 (void) elf_end(elf); 00135 ANNOTATE_IGNORE_READS_AND_WRITES_END(); 00136 yarnRelease(oneshot); 00137 00138 if (pidp != NULL && bingo) { 00139 int pipes[2] = { -1, -1 }; 00140 pid_t pid; 00141 00142 xx = close(fdno); 00143 xx = pipe(pipes); 00144 pid = fork(); 00145 switch (pid) { 00146 case 0: 00147 { const char ** av = NULL; 00148 int ac = 0; 00149 xx = close(pipes[0]); 00150 xx = dup2(pipes[1], STDOUT_FILENO); 00151 xx = close(pipes[1]); 00152 if (!poptDupArgv(cmd_ac, cmd_av, &ac, &av)) { 00153 av[ac-1] = path; 00154 av[ac] = NULL; 00155 unsetenv("MALLOC_CHECK_"); 00156 xx = execve(av[0], (char *const *)av+1, environ); 00157 } 00158 _exit(127); 00159 /*@notreached@*/ 00160 } break; 00161 default: 00162 fdno = pipes[0]; 00163 xx = close(pipes[1]); 00164 *pidp = pid; 00165 break; 00166 } 00167 } 00168 } 00169 #endif 00170 00171 exit: 00172 return fdno; 00173 } 00174 /*@=compdef =moduncon =noeffectuncon @*/ 00175 00176 static const char hmackey[] = "orboDeJITITejsirpADONivirpUkvarP"; 00177 00178 int dodigest(int dalgo, const char * fn, unsigned char * digest, 00179 unsigned dflags, size_t *fsizep) 00180 { 00181 int asAscii = dflags & 0x01; 00182 int doHmac = dflags & 0x02; 00183 const char * path; 00184 urltype ut = urlPath(fn, &path); 00185 unsigned char * dsum = NULL; 00186 size_t dlen; 00187 unsigned char buf[32*BUFSIZ]; 00188 FD_t fd; 00189 size_t fsize = 0; 00190 pid_t pid = 0; 00191 int use_mmap; 00192 int rc = 0; 00193 int fdno; 00194 #if defined(HAVE_MMAP) 00195 int xx; 00196 #endif 00197 00198 /*@-globs -internalglobs -mods @*/ 00199 fdno = open_dso(path, &pid, &fsize); 00200 /*@=globs =internalglobs =mods @*/ 00201 if (fdno < 0) { 00202 rc = 1; 00203 goto exit; 00204 } 00205 00206 /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */ 00207 use_mmap = (pid == 0 && fsize <= 0x07ffffff); 00208 00209 switch(ut) { 00210 case URL_IS_PATH: 00211 case URL_IS_UNKNOWN: 00212 #if defined(HAVE_MMAP) 00213 if (use_mmap) { 00214 DIGEST_CTX ctx; 00215 void * mapped = NULL; 00216 00217 if (fsize) { 00218 mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0); 00219 if (mapped == (void *)-1) { 00220 xx = close(fdno); 00221 rc = 1; 00222 break; 00223 } 00224 00225 #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL) 00226 xx = madvise(mapped, fsize, MADV_SEQUENTIAL); 00227 #endif 00228 } 00229 00230 ctx = rpmDigestInit(dalgo, RPMDIGEST_NONE); 00231 if (doHmac) 00232 xx = rpmHmacInit(ctx, hmackey, 0); 00233 if (fsize) 00234 xx = rpmDigestUpdate(ctx, mapped, fsize); 00235 xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii); 00236 if (fsize) 00237 xx = munmap(mapped, fsize); 00238 xx = close(fdno); 00239 break; 00240 } /*@fallthrough@*/ 00241 #endif 00242 case URL_IS_HTTPS: 00243 case URL_IS_HTTP: 00244 case URL_IS_FTP: 00245 case URL_IS_HKP: 00246 case URL_IS_DASH: 00247 default: 00248 /* Either use the pipe to prelink -y or open the URL. */ 00249 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.fdio"); 00250 (void) close(fdno); 00251 if (fd == NULL || Ferror(fd)) { 00252 rc = 1; 00253 if (fd != NULL) 00254 (void) Fclose(fd); 00255 break; 00256 } 00257 00258 fdInitDigest(fd, dalgo, 0); 00259 if (doHmac) 00260 fdInitHmac(fd, hmackey, 0); 00261 fsize = 0; 00262 while ((rc = (int) Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) 00263 fsize += rc; 00264 fdFiniDigest(fd, dalgo, &dsum, &dlen, asAscii); 00265 if (Ferror(fd)) 00266 rc = 1; 00267 00268 (void) Fclose(fd); 00269 break; 00270 } 00271 00272 /* Reap the prelink -y helper. */ 00273 if (pid) { 00274 int status; 00275 /*@+longunsignedintegral@*/ 00276 (void) waitpid(pid, &status, 0); 00277 /*@=longunsignedintegral@*/ 00278 if (!WIFEXITED(status) || WEXITSTATUS(status)) 00279 rc = 1; 00280 } 00281 00282 exit: 00283 if (fsizep) 00284 *fsizep = fsize; 00285 if (!rc) 00286 memcpy(digest, dsum, dlen); 00287 dsum = _free(dsum); 00288 00289 return rc; 00290 }
1.7.5.1