rpm  5.4.4
rpmdb/legacy.c
Go to the documentation of this file.
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 }