rpm  4.5
legacy.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #if 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 #include <gelf.h>
18 
19 #if !defined(DT_GNU_PRELINKED)
20 #define DT_GNU_PRELINKED 0x6ffffdf5
21 #endif
22 #if !defined(DT_GNU_LIBLIST)
23 #define DT_GNU_LIBLIST 0x6ffffef9
24 #endif
25 
26 #endif
27 
28 #include "rpmio_internal.h"
29 #include <rpmlib.h>
30 #include <rpmmacro.h>
31 #include "misc.h"
32 #include "legacy.h"
33 #include "debug.h"
34 
35 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
36 
44 static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep)
45  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
46  /*@modifies *pidp, *fsizep, rpmGlobalMacroContext,
47  fileSystem, internalState @*/
48 {
49 /*@only@*/
50  static const char * cmd = NULL;
51  static int initted = 0;
52  int fdno;
53 
54  if (!initted) {
55  cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
56  initted++;
57  }
58 
59 /*@-boundswrite@*/
60  if (pidp) *pidp = 0;
61 
62  if (fsizep) {
63  struct stat sb, * st = &sb;
64  if (stat(path, st) < 0)
65  return -1;
66  *fsizep = st->st_size;
67  }
68 /*@=boundswrite@*/
69 
70  fdno = open(path, O_RDONLY);
71  if (fdno < 0)
72  return fdno;
73 
74 /*@-boundsread@*/
75  if (!(cmd && *cmd))
76  return fdno;
77 /*@=boundsread@*/
78 
79 #if HAVE_GELF_H && HAVE_LIBELF
80  { Elf *elf = NULL;
81  Elf_Scn *scn = NULL;
82  Elf_Data *data = NULL;
83  GElf_Ehdr ehdr;
84  GElf_Shdr shdr;
85  GElf_Dyn dyn;
86  int bingo;
87 
88  (void) elf_version(EV_CURRENT);
89 
90 /*@-evalorder@*/
91  if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
92  || elf_kind(elf) != ELF_K_ELF
93  || gelf_getehdr(elf, &ehdr) == NULL
94  || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
95  goto exit;
96 /*@=evalorder@*/
97 
98  bingo = 0;
99  /*@-branchstate -uniondef @*/
100  while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
101  (void) gelf_getshdr(scn, &shdr);
102  if (shdr.sh_type != SHT_DYNAMIC)
103  continue;
104  while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
105  int maxndx = data->d_size / shdr.sh_entsize;
106  int ndx;
107 
108  for (ndx = 0; ndx < maxndx; ++ndx) {
109  (void) gelf_getdyn (data, ndx, &dyn);
110  if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
111  /*@innercontinue@*/ continue;
112  bingo = 1;
113  /*@innerbreak@*/ break;
114  }
115  }
116  }
117  /*@=branchstate =uniondef @*/
118 
119 /*@-boundswrite@*/
120  if (pidp != NULL && bingo) {
121  int pipes[2];
122  pid_t pid;
123  int xx;
124 
125  xx = close(fdno);
126  pipes[0] = pipes[1] = -1;
127  xx = pipe(pipes);
128  if (!(pid = fork())) {
129  const char ** av;
130  int ac;
131  xx = close(pipes[0]);
132  xx = dup2(pipes[1], STDOUT_FILENO);
133  xx = close(pipes[1]);
134  if (!poptParseArgvString(cmd, &ac, &av)) {
135  av[ac-1] = path;
136  av[ac] = NULL;
137  unsetenv("MALLOC_CHECK_");
138  xx = execve(av[0], (char *const *)av+1, environ);
139  }
140  _exit(127);
141  }
142  *pidp = pid;
143  fdno = pipes[0];
144  xx = close(pipes[1]);
145  }
146 /*@=boundswrite@*/
147 
148 exit:
149  if (elf) (void) elf_end(elf);
150  }
151 #endif
152 
153  return fdno;
154 }
155 
156 int dodigest(int digestalgo, const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
157 {
158  const char * path;
159  urltype ut = urlPath(fn, &path);
160  unsigned char * dsum = NULL;
161  size_t dlen;
162  unsigned char buf[32*BUFSIZ];
163  FD_t fd;
164  size_t fsize = 0;
165  pid_t pid = 0;
166  int use_mmap;
167  int rc = 0;
168  int fdno;
169  int xx;
170 
171 /*@-globs -internalglobs -mods @*/
172  fdno = open_dso(path, &pid, &fsize);
173 /*@=globs =internalglobs =mods @*/
174  if (fdno < 0) {
175  rc = 1;
176  goto exit;
177  }
178 
179  /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */
180  use_mmap = (pid == 0 && fsize <= 0x07ffffff);
181 
182  switch(ut) {
183  case URL_IS_PATH:
184  case URL_IS_UNKNOWN:
185 #if HAVE_MMAP
186  if (use_mmap) {
187  DIGEST_CTX ctx;
188  void * mapped = NULL;
189 
190  if (fsize) {
191  mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
192  if (mapped == (void *)-1) {
193  xx = close(fdno);
194  rc = 1;
195  break;
196  }
197 
198 #ifdef MADV_SEQUENTIAL
199  xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
200 #endif
201  }
202 
203  ctx = rpmDigestInit(digestalgo, RPMDIGEST_NONE);
204  if (fsize)
205  xx = rpmDigestUpdate(ctx, mapped, fsize);
206  xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii);
207  if (fsize)
208  xx = munmap(mapped, fsize);
209  xx = close(fdno);
210  break;
211  } /*@fallthrough@*/
212 #endif
213  case URL_IS_HTTPS:
214  case URL_IS_HTTP:
215  case URL_IS_FTP:
216  case URL_IS_HKP:
217  case URL_IS_DASH:
218  default:
219  /* Either use the pipe to prelink -y or open the URL. */
220  fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r");
221  (void) close(fdno);
222  if (fd == NULL || Ferror(fd)) {
223  rc = 1;
224  if (fd != NULL)
225  (void) Fclose(fd);
226  break;
227  }
228 
229  fdInitDigest(fd, digestalgo, 0);
230  fsize = 0;
231  while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
232  fsize += rc;
233  fdFiniDigest(fd, digestalgo, &dsum, &dlen, asAscii);
234  if (Ferror(fd))
235  rc = 1;
236 
237  (void) Fclose(fd);
238  break;
239  }
240 
241  /* Reap the prelink -y helper. */
242  if (pid) {
243  int status;
244  (void) waitpid(pid, &status, 0);
245  if (!WIFEXITED(status) || WEXITSTATUS(status))
246  rc = 1;
247  }
248 
249 exit:
250 /*@-boundswrite@*/
251  if (fsizep)
252  *fsizep = fsize;
253  if (!rc)
254  memcpy(digest, dsum, dlen);
255 /*@=boundswrite@*/
256  dsum = _free(dsum);
257 
258  return rc;
259 }
260 
261 int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
262 {
263  return dodigest(PGPHASHALGO_MD5, fn, digest, asAscii, fsizep);
264 }
265 
267  /*@out@*/ const char *** fnp, /*@out@*/ int * fcp)
268 {
270  HFD_t hfd = headerFreeData;
271  const char ** baseNames;
272  const char ** dirNames;
273  int * dirIndexes;
274  int count;
275  const char ** fileNames;
276  int size;
277  rpmTag dirNameTag = 0;
278  rpmTag dirIndexesTag = 0;
279  rpmTagType bnt, dnt;
280  char * t;
281  int i, xx;
282 
283  if (tagN == RPMTAG_BASENAMES) {
284  dirNameTag = RPMTAG_DIRNAMES;
285  dirIndexesTag = RPMTAG_DIRINDEXES;
286  } else if (tagN == RPMTAG_ORIGBASENAMES) {
287  dirNameTag = RPMTAG_ORIGDIRNAMES;
288  dirIndexesTag = RPMTAG_ORIGDIRINDEXES;
289  }
290 
291  if (!hge(h, tagN, &bnt, &baseNames, &count)) {
292  if (fnp) *fnp = NULL;
293  if (fcp) *fcp = 0;
294  return; /* no file list */
295  }
296 
297  xx = hge(h, dirNameTag, &dnt, &dirNames, NULL);
298  xx = hge(h, dirIndexesTag, NULL, &dirIndexes, &count);
299 
300  size = sizeof(*fileNames) * count;
301  for (i = 0; i < count; i++) {
302  const char * dn = NULL;
303  (void) urlPath(dirNames[dirIndexes[i]], &dn);
304  size += strlen(baseNames[i]) + strlen(dn) + 1;
305  }
306 
307  fileNames = xmalloc(size);
308  t = ((char *) fileNames) + (sizeof(*fileNames) * count);
309  /*@-branchstate@*/
310  for (i = 0; i < count; i++) {
311  const char * dn = NULL;
312  fileNames[i] = t;
313  (void) urlPath(dirNames[dirIndexes[i]], &dn);
314  t = stpcpy( stpcpy(t, dn), baseNames[i]);
315  *t++ = '\0';
316  }
317  /*@=branchstate@*/
318  baseNames = hfd(baseNames, bnt);
319  dirNames = hfd(dirNames, dnt);
320 
321  /*@-branchstate@*/
322  if (fnp)
323  *fnp = fileNames;
324  else
325  fileNames = _free(fileNames);
326  /*@=branchstate@*/
327  if (fcp) *fcp = count;
328 }