rpm  5.4.10
legacy.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #if defined(HAVE_GELF_H)
8 #if LIBELF_H_LFS_CONFLICT
9 /* some gelf.h/libelf.h implementations (Solaris) are
10  * incompatible with the Large File API
11  */
12 # undef _LARGEFILE64_SOURCE
13 # undef _LARGEFILE_SOURCE
14 # undef _FILE_OFFSET_BITS
15 # define _FILE_OFFSET_BITS 32
16 #endif
17 #if defined(__LCLINT__)
18 /*@-incondefs@*/
19 typedef long long loff_t;
20 /*@=incondefs@*/
21 #endif
22 #include <gelf.h>
23 
24 #if !defined(DT_GNU_PRELINKED)
25 #define DT_GNU_PRELINKED 0x6ffffdf5
26 #endif
27 #if !defined(DT_GNU_LIBLIST)
28 #define DT_GNU_LIBLIST 0x6ffffef9
29 #endif
30 
31 #endif
32 
33 #include "rpmio_internal.h"
34 #include <rpmmacro.h>
35 #include "misc.h"
36 #include "legacy.h"
37 #include "debug.h"
38 
39 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
40 
48 /*@-compdef -moduncon -noeffectuncon @*/
49 static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep)
50  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
51  /*@modifies *pidp, *fsizep, rpmGlobalMacroContext,
52  fileSystem, internalState @*/
53 {
54  int fdno;
55 
56  if (pidp) *pidp = 0;
57 
58  if (fsizep) {
59  struct stat sb, * st = &sb;
60  if (stat(path, st) < 0)
61  return -1;
62  *fsizep = (size_t)st->st_size;
63  }
64 
65  fdno = open(path, O_RDONLY);
66  if (fdno < 0)
67  goto exit;
68 
69 #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF)
70  { Elf *elf = NULL;
71  Elf_Scn *scn = NULL;
72  Elf_Data *data = NULL;
73  GElf_Ehdr ehdr;
74  GElf_Shdr shdr;
75  GElf_Dyn dyn;
76  int bingo;
77  static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
78  static yarnLock oneshot = NULL; /* XXX memleak */
79  static const char ** cmd_av = NULL; /* XXX memleak */
80  static int cmd_ac = 0;
81  int xx;
82 
83  xx = pthread_mutex_lock(&_mutex);
84  if (oneshot == NULL)
85  oneshot = yarnNewLock(0);
86  if (cmd_av == NULL) {
87  const char * cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
88  (void) poptParseArgvString(cmd, &cmd_ac, &cmd_av);
89  cmd = _free(cmd);
90  }
91  xx = pthread_mutex_unlock(&_mutex);
92 
93  if (cmd_ac == 0)
94  goto exit;
95 
96  yarnPossess(oneshot); /* XXX thread-safe iff compiled w USE_LOCKS */
98  (void) elf_version(EV_CURRENT);
99 
100 /*@-evalorder@*/
101  if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
102  || elf_kind(elf) != ELF_K_ELF
103  || gelf_getehdr(elf, &ehdr) == NULL
104  || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
105  {
106  if (elf) (void) elf_end(elf);
108  yarnRelease(oneshot);
109  goto exit;
110  }
111 /*@=evalorder@*/
112 
113  bingo = 0;
114  while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
115  (void) gelf_getshdr(scn, &shdr);
116  if (shdr.sh_type != SHT_DYNAMIC)
117  continue;
118  while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
119  unsigned maxndx = (unsigned) (data->d_size / shdr.sh_entsize);
120  unsigned ndx;
121 
122  for (ndx = 0; ndx < maxndx; ++ndx) {
123 /*@-uniondef@*/
124  (void) gelf_getdyn (data, ndx, &dyn);
125 /*@=uniondef@*/
126  if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
127  /*@innercontinue@*/ continue;
128  bingo = 1;
129  /*@innerbreak@*/ break;
130  }
131  }
132  }
133 
134  (void) elf_end(elf);
136  yarnRelease(oneshot);
137 
138  if (pidp != NULL && bingo) {
139  int pipes[2] = { -1, -1 };
140  pid_t pid;
141 
142  xx = close(fdno);
143  xx = pipe(pipes);
144  pid = fork();
145  switch (pid) {
146  case 0:
147  { const char ** av = NULL;
148  int ac = 0;
149  xx = close(pipes[0]);
150  xx = dup2(pipes[1], STDOUT_FILENO);
151  xx = close(pipes[1]);
152  if (!poptDupArgv(cmd_ac, cmd_av, &ac, &av)) {
153  av[ac-1] = path;
154  av[ac] = NULL;
155  unsetenv("MALLOC_CHECK_");
156  xx = execve(av[0], (char *const *)av+1, environ);
157  }
158  _exit(127);
159  /*@notreached@*/
160  } break;
161  default:
162  fdno = pipes[0];
163  xx = close(pipes[1]);
164  *pidp = pid;
165  break;
166  }
167  }
168  }
169 #endif
170 
171 exit:
172  return fdno;
173 }
174 /*@=compdef =moduncon =noeffectuncon @*/
175 
176 static const char hmackey[] = "orboDeJITITejsirpADONivirpUkvarP";
177 
178 int dodigest(int dalgo, const char * fn, unsigned char * digest,
179  unsigned dflags, size_t *fsizep)
180 {
181  int asAscii = dflags & 0x01;
182  int doHmac = dflags & 0x02;
183  const char * path;
184  urltype ut = urlPath(fn, &path);
185  unsigned char * dsum = NULL;
186  size_t dlen;
187  unsigned char buf[32*BUFSIZ];
188  FD_t fd;
189  size_t fsize = 0;
190  pid_t pid = 0;
191  int use_mmap;
192  int rc = 0;
193  int fdno;
194 #if defined(HAVE_MMAP)
195  int xx;
196 #endif
197 
198 /*@-globs -internalglobs -mods @*/
199  fdno = open_dso(path, &pid, &fsize);
200 /*@=globs =internalglobs =mods @*/
201  if (fdno < 0) {
202  rc = 1;
203  goto exit;
204  }
205 
206  /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */
207  use_mmap = (pid == 0 && fsize <= 0x07ffffff);
208 
209  switch(ut) {
210  case URL_IS_PATH:
211  case URL_IS_UNKNOWN:
212 #if defined(HAVE_MMAP)
213  if (use_mmap) {
214  DIGEST_CTX ctx;
215  void * mapped = NULL;
216 
217  if (fsize) {
218  mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
219  if (mapped == (void *)-1) {
220  xx = close(fdno);
221  rc = 1;
222  break;
223  }
224 
225 #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL)
226  xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
227 #endif
228  }
229 
231  if (doHmac)
232  xx = rpmHmacInit(ctx, hmackey, 0);
233  if (fsize)
234  xx = rpmDigestUpdate(ctx, mapped, fsize);
235  xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii);
236  if (fsize)
237  xx = munmap(mapped, fsize);
238  xx = close(fdno);
239  break;
240  } /*@fallthrough@*/
241 #endif
242  case URL_IS_HTTPS:
243  case URL_IS_HTTP:
244  case URL_IS_FTP:
245  case URL_IS_HKP:
246  case URL_IS_DASH:
247  default:
248  /* Either use the pipe to prelink -y or open the URL. */
249  fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.fdio");
250  (void) close(fdno);
251  if (fd == NULL || Ferror(fd)) {
252  rc = 1;
253  if (fd != NULL)
254  (void) Fclose(fd);
255  break;
256  }
257 
258  fdInitDigest(fd, (pgpHashAlgo)dalgo, 0);
259  if (doHmac)
260  fdInitHmac(fd, hmackey, 0);
261  fsize = 0;
262  while ((rc = (int) Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
263  fsize += rc;
264  fdFiniDigest(fd, (pgpHashAlgo)dalgo, &dsum, &dlen, asAscii);
265  if (Ferror(fd))
266  rc = 1;
267 
268  (void) Fclose(fd);
269  break;
270  }
271 
272  /* Reap the prelink -y helper. */
273  if (pid) {
274  int status;
275 /*@+longunsignedintegral@*/
276  (void) waitpid(pid, &status, 0);
277 /*@=longunsignedintegral@*/
278  if (!WIFEXITED(status) || WEXITSTATUS(status))
279  rc = 1;
280  }
281 
282 exit:
283  if (fsizep)
284  *fsizep = fsize;
285  if (!rc)
286  memcpy(digest, dsum, dlen);
287  dsum = _free(dsum);
288 
289  return rc;
290 }
enum urltype_e urltype
Supported URL types.
#define ANNOTATE_IGNORE_READS_AND_WRITES_END()
Definition: debug.h:167
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2833
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest.
Definition: digest.c:244
enum pgpHashAlgo_e pgpHashAlgo
9.4.
char ** environ
static int open_dso(const char *path, pid_t *pidp, size_t *fsizep)
Open a file descriptor to verify file MD5 and size.
Definition: legacy.c:49
static void fdInitHmac(FD_t fd, const void *key, size_t keylen)
Attach digest to fd.
int dodigest(int dalgo, const char *fn, unsigned char *digest, unsigned dflags, size_t *fsizep)
Return digest and size of a file.
Definition: legacy.c:178
FD_t fdDup(int fdno)
Definition: rpmio.c:264
static void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int _flags)
Attach digest to fd.
int rpmHmacInit(DIGEST_CTX ctx, const void *key, size_t keylen)
Compute key material and add to digest context.
Definition: digest.c:983
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:907
Digest private data.
Definition: digest.c:127
The FD_t File Handle data structure.
static void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo, void *datap, size_t *lenp, int asAscii)
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3117
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2412
void unsetenv(const char *name)
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:429
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN()
Definition: debug.h:166
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
int rpmDigestFinal(DIGEST_CTX ctx, void *datap, size_t *lenp, int asAscii)
Return digest and destroy context.
Definition: digest.c:921
struct yarnLock_s * yarnLock
Definition: rpmiotypes.h:34
static const char hmackey[]
Definition: legacy.c:176