blob: 080e725770a923553ad026e281d64daa2214bb63 [file] [log] [blame]
fitzhardinge7e343cd2003-12-16 02:14:00 +00001/*
2 User-mode exec
3
4 This bootstraps Valgrind. This code decides on the layout of the
5 client and Valgrind address spaces, loads valgrind.so and the
6 skin.so into the valgrind part, loads the client executable (and the
7 dynamic linker, if necessary) into the client part, and calls into
8 Valgrind proper.
9
10 The code is careful not to allow spurious mappings to appear in the
11 wrong parts of the address space. In particular, to make sure
12 dlopen puts things in the right place, it will pad out the forbidden
13 chunks of address space so that dlopen is forced to put things where
14 we want them.
15
16 The memory map it creates is:
17
18 CLIENT_BASE +-------------------------+
19 | client address space |
20 : :
21 : :
22 | client stack |
23 client_end +-------------------------+
24 | redzone |
25 shadow_base +-------------------------+
26 | |
27 : shadow memory for skins :
28 | (may be 0 sized) |
29 shadow_end +-------------------------+
30 : gap (may be 0 sized) :
31 valgrind_base +-------------------------+
32 | valgrind .so files |
33 | and mappings |
34 valgrind_mmap_end -
35 | kickstart executable |
36 - -
37 | valgrind heap vvvvvvvvv|
38 valgrind_end - -
39 | valgrind stack ^^^^^^^^^|
40 +-------------------------+
41 : kernel :
42 */
43
44#define _GNU_SOURCE
45#define _FILE_OFFSET_BITS 64
46
47#include "vg_include.h"
48
49#include <stddef.h>
50#include <sys/mman.h>
51#include <fcntl.h>
52#include <errno.h>
53#include <elf.h>
54#include <stdio.h>
55#include <string.h>
56#include <stdlib.h>
57#include <unistd.h>
58#include <asm/unistd.h>
59#include <sys/stat.h>
60#include <sys/sysmacros.h>
61#include <dlfcn.h>
62#include <assert.h>
63
64#include "ume.h"
65
66static int padfile = -1;
67static struct stat padstat;
68
69extern int kickstart_base; /* linker created */
70
71void foreach_map(int (*fn)(void *start, void *end,
72 const char *perm, off_t offset,
73 int maj, int min, int ino))
74{
75 static char buf[10240];
76 char *bufptr = buf;
77 int ret, fd;
78
79 fd = open("/proc/self/maps", O_RDONLY);
80
81 if (fd == -1) {
82 perror("open /proc/self/maps");
83 return;
84 }
85
86 ret = read(fd, buf, sizeof(buf));
87
88 if (ret == -1) {
89 perror("read /proc/self/maps");
90 close(fd);
91 return;
92 }
93 close(fd);
94
95 if (ret == sizeof(buf)) {
96 fprintf(stderr, "buf too small\n");
97 return;
98 }
99
100 while(bufptr && bufptr < buf+ret) {
101 char perm[5];
102 off_t offset;
103 int maj, min;
104 int ino;
105 void *segstart, *segend;
106
107 sscanf(bufptr, "%p-%p %s %Lx %x:%x %d",
108 &segstart, &segend, perm, &offset, &maj, &min, &ino);
109 bufptr = strchr(bufptr, '\n');
110 if (bufptr != NULL)
111 bufptr++; /* skip \n */
112
113 if (!(*fn)(segstart, segend, perm, offset, maj, min, ino))
114 break;
115 }
116}
117
118/* pad all the empty spaces in a range of address space to stop
119 interlopers */
120void as_pad(void *start, void *end)
121{
122 char buf[1024];
123 char *addr;
124
125 int fillgap(void *segstart, void *segend, const char *perm, off_t off,
126 int maj, int min, int ino) {
127 if (segstart >= end)
128 return 0;
129
130 if ((char *)segstart > addr)
131 mmap(addr, (char *)segstart-addr, PROT_NONE, MAP_FIXED|MAP_PRIVATE,
132 padfile, 0);
133 addr = segend;
134
135 return 1;
136 }
137
138 if (padfile == -1) {
139 int seq = 1;
140 do {
141 sprintf(buf, "/tmp/.pad.%d.%d", getpid(), seq++);
142 padfile = open(buf, O_RDWR|O_CREAT|O_EXCL, 0);
143 unlink(buf);
144 if (padfile == -1 && errno != EEXIST)
145 exit(44);
146 } while(padfile == -1);
147 fstat(padfile, &padstat);
148 }
149
150 addr = start;
151
152 foreach_map(fillgap);
153
154 if (addr < (char *)end)
155 mmap(addr, (char *)end-addr, PROT_NONE, MAP_FIXED|MAP_PRIVATE,
156 padfile, 0);
157}
158
159/* remove padding from a range of address space - padding is always a
160 mapping of padfile*/
161void as_unpad(void *start, void *end)
162{
163 int killpad(void *segstart, void *segend, const char *perm, off_t off,
164 int maj, int min, int ino) {
165 void *b, *e;
166
167 if (padstat.st_dev != makedev(maj, min) || padstat.st_ino != ino)
168 return 1;
169
170 if (segend <= start || segstart >= end)
171 return 1;
172
173 if (segstart <= start)
174 b = start;
175 else
176 b = segstart;
177
178 if (segend >= end)
179 e = end;
180 else
181 e = segend;
182
183 munmap(b, (char *)e-(char *)b);
184
185 return 1;
186 }
187
188 if (padfile == -1) /* no padfile, no padding */
189 return;
190
191 foreach_map(killpad);
192}
193
194void as_closepadfile(void)
195{
196 /* don't unpad */
197 close(padfile);
198 padfile = -1;
199}
200
201int as_getpadfd(void)
202{
203 return padfile;
204}
205
206void as_setpadfd(int fd)
207{
208 as_closepadfile();
209 padfile = fd;
210 fstat(padfile, &padstat);
211}
212
213struct ume_auxv *find_auxv(int *esp)
214{
215 esp++; /* skip argc */
216
217 while(*esp != 0) /* skip argv */
218 esp++;
219 esp++;
220
221 while(*esp != 0) /* skip env */
222 esp++;
223 esp++;
224
225 return (struct ume_auxv *)esp;
226}
227
228
229struct elfinfo *readelf(int fd, const char *filename)
230{
231 struct elfinfo *e = malloc(sizeof(*e));
232 int phsz;
233
234 e->fd = fd;
235
236 if (pread(fd, &e->e, sizeof(e->e), 0) != sizeof(e->e)) {
237 fprintf(stderr, "%s: can't read elf header: %s\n",
238 filename, strerror(errno));
239 return NULL;
240 }
241
242 if (memcmp(&e->e.e_ident[0], ELFMAG, SELFMAG) != 0) {
243 fprintf(stderr, "%s: bad ELF magic\n",
244 filename);
245 return NULL;
246 }
247 if (e->e.e_ident[EI_CLASS] != ELFCLASS32) {
248 fprintf(stderr, "Can only handle 32-bit executables\n");
249 return NULL;
250 }
251 if (e->e.e_ident[EI_DATA] != ELFDATA2LSB) {
252 fprintf(stderr, "Expecting little-endian\n");
253 return NULL;
254 }
255 if (!(e->e.e_type == ET_EXEC || e->e.e_type == ET_DYN)) {
256 fprintf(stderr, "need executable\n");
257 return NULL;
258 }
259
260 if (e->e.e_machine != EM_386) {
261 fprintf(stderr, "need x86\n");
262 return NULL;
263 }
264
265 if (e->e.e_phentsize != sizeof(ESZ(Phdr))) {
266 fprintf(stderr, "sizeof Phdr wrong\n");
267 return NULL;
268 }
269
270 phsz = sizeof(ESZ(Phdr)) * e->e.e_phnum;
271 e->p = malloc(phsz);
272
273 if (pread(fd, e->p, phsz, e->e.e_phoff) != phsz) {
274 fprintf(stderr, "can't read phdr: %s\n", strerror(errno));
275 return NULL;
276 }
277
278 return e;
279}
280
281#define REMAINS(x, a) ((x) & ((a)-1))
282
283/* Map an ELF file. Returns the brk address. */
284ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base, int setbrk)
285{
286 int i;
287 ESZ(Addr) elfbrk = 0;
288
289 for(i = 0; i < e->e.e_phnum; i++) {
290 ESZ(Phdr) *ph = &e->p[i];
291 ESZ(Addr) addr, brkaddr;
292 ESZ(Word) memsz;
293
294 if (ph->p_type != PT_LOAD)
295 continue;
296
297 addr = ph->p_vaddr+base;
298 memsz = ph->p_memsz;
299 brkaddr = addr+memsz;
300
301 if (brkaddr > elfbrk)
302 elfbrk = brkaddr;
303 }
304
305 if (setbrk) {
306 /* sneaking up on the brk limit works better than actually
307 jumping directly there. Unfortunately, setting the brk is
308 tested against the datasize rlimit, even though we're not
309 actually using any memory. */
310 char *b = sbrk(0);
311 char *initb = (char *)PGROUNDUP(b);
312
313 while(b < (char *)elfbrk) {
314 unsigned delta = (char *)elfbrk - b;
315 static const unsigned limit = 256*1024*1024;
316 char *bb;
317
318 if (delta > limit)
319 delta = limit;
320 //printf("elfbrk=%p b=%p delta=%u\n", elfbrk, b, delta);
321 bb = sbrk(delta);
322 if (bb != b) {
323 fprintf(stderr, "sbrk failed while adjusting brk base: "
324 "perhaps we hit the datasize ulimit?\n");
fitzhardinge92360792003-12-24 10:11:11 +0000325 return 0;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000326 }
327 b += delta;
328 }
329 munmap(initb, (char *)PGROUNDDN(elfbrk)-initb);
330 }
331
332 for(i = 0; i < e->e.e_phnum; i++) {
333 ESZ(Phdr) *ph = &e->p[i];
334 ESZ(Addr) addr, bss, brkaddr;
335 ESZ(Off) off;
336 ESZ(Word) filesz;
337 ESZ(Word) memsz;
338 ESZ(Word) align;
339 unsigned prot = 0;
340
341 if (ph->p_type != PT_LOAD)
342 continue;
343
344 if (ph->p_flags & PF_X)
345 prot |= PROT_EXEC;
346 if (ph->p_flags & PF_W)
347 prot |= PROT_WRITE;
348 if (ph->p_flags & PF_R)
349 prot |= PROT_READ;
350
351 align = ph->p_align;
352
353 addr = ph->p_vaddr+base;
354 off = ph->p_offset;
355 filesz = ph->p_filesz;
356 bss = addr+filesz;
357 memsz = ph->p_memsz;
358 brkaddr = addr+memsz;
359
360 mmap((char *)ROUNDDN(addr, align), ROUNDUP(bss, align)-ROUNDDN(addr, align),
361 prot, MAP_FIXED|MAP_PRIVATE, e->fd, ROUNDDN(off, align));
362
363 /* if memsz > filesz, then we need to fill the remainder with zeroed pages */
364 if (memsz > filesz) {
365 UInt bytes;
366
367 bytes = ROUNDUP(brkaddr, align)-ROUNDUP(bss, align);
368 if (bytes > 0)
369 mmap((char *)ROUNDUP(bss, align), bytes,
370 prot, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
371
372 bytes = bss & (VKI_BYTES_PER_PAGE - 1);
373 if (bytes > 0) {
374 bytes = VKI_BYTES_PER_PAGE - bytes;
375 memset((char *)bss, 0, bytes);
376 }
377 }
378 }
379
380 return elfbrk;
381}
382
383
384static int do_exec_inner(const char *exe, struct exeinfo *info);
385
386
387static int match_ELF(const char *hdr, int len)
388{
389 ESZ(Ehdr) *e = (ESZ(Ehdr) *)hdr;
390 return (len > sizeof(*e)) && memcmp(&e->e_ident[0], ELFMAG, SELFMAG) == 0;
391}
392
393static int load_ELF(char *hdr, int len, int fd, const char *name, struct exeinfo *info)
394{
395 struct elfinfo *e;
396 struct elfinfo *interp = NULL;
397 ESZ(Addr) minaddr = ~0;
398 ESZ(Addr) maxaddr = 0;
399 ESZ(Addr) interp_addr = 0;
400 ESZ(Word) interp_size = 0;
401 int i;
402 void *entry;
403
404 e = readelf(fd, name);
405
406 if (e == NULL)
407 return ENOEXEC;
408
409 info->phnum = e->e.e_phnum;
410 info->entry = e->e.e_entry;
411
412 for(i = 0; i < e->e.e_phnum; i++) {
413 ESZ(Phdr) *ph = &e->p[i];
414
415 switch(ph->p_type) {
416 case PT_PHDR:
417 info->phdr = ph->p_vaddr;
418 break;
419
420 case PT_LOAD:
421 if (ph->p_vaddr < minaddr)
422 minaddr = ph->p_vaddr;
423 if (ph->p_vaddr+ph->p_memsz > maxaddr)
424 maxaddr = ph->p_vaddr+ph->p_memsz;
425 break;
426
427 case PT_INTERP: {
428 char *buf = malloc(ph->p_filesz+1);
429 int j;
430 int intfd;
431 int baseaddr_set;
432
433 pread(fd, buf, ph->p_filesz, ph->p_offset);
434 buf[ph->p_filesz] = '\0';
435
436 intfd = open(buf, O_RDONLY);
437 if (intfd == -1) {
438 perror("open interp");
439 exit(1);
440 }
441
442 interp = readelf(intfd, buf);
443 if (interp == NULL) {
444 fprintf(stderr, "Can't read interpreter\n");
445 return 1;
446 }
447 free(buf);
448
449 baseaddr_set = 0;
450 for(j = 0; j < interp->e.e_phnum; j++) {
451 ESZ(Phdr) *iph = &interp->p[j];
452 ESZ(Addr) end;
453
454 if (iph->p_type != PT_LOAD)
455 continue;
456
457 if (!baseaddr_set) {
458 interp_addr = iph->p_vaddr;
459 baseaddr_set = 1;
460 }
461
462 /* assumes that all segments in the interp are close */
463 end = (iph->p_vaddr - interp_addr) + iph->p_memsz;
464
465 if (end > interp_size)
466 interp_size = end;
467 }
468 break;
469 }
470 }
471 }
472
473 if (info->exe_base != info->exe_end) {
474 if (minaddr >= maxaddr ||
475 (minaddr < info->exe_base ||
476 maxaddr > info->exe_end)) {
477 fprintf(stderr, "Executable is mapped outside of range %p-%p\n",
478 (void *)info->exe_base, (void *)info->exe_end);
479 return ENOMEM;
480 }
481 }
482
483 info->brkbase = mapelf(e, 0, info->setbrk); /* map the executable */
484
fitzhardinge92360792003-12-24 10:11:11 +0000485 if (info->brkbase == 0)
486 return ENOMEM;
487
fitzhardinge7e343cd2003-12-16 02:14:00 +0000488 if (interp != NULL) {
489 /* reserve a chunk of address space for interpreter */
490 char *base = (char *)info->exe_base;
491 char *baseoff;
492 int flags = MAP_PRIVATE|MAP_ANONYMOUS;
493
494 if (info->map_base != 0) {
495 base = (char *)info->map_base;
496 flags |= MAP_FIXED;
497 }
498
499 base = mmap(base, interp_size, PROT_NONE, flags, -1, 0);
500
501 baseoff = base - interp_addr;
502
503 mapelf(interp, (ESZ(Addr))baseoff, 0);
504
505 close(interp->fd);
506 free(interp);
507
508 entry = baseoff + interp->e.e_entry;
509 info->interp_base = (ESZ(Addr))base;
510 } else
511 entry = (void *)e->e.e_entry;
512
513 info->exe_base = minaddr;
514 info->exe_end = maxaddr;
515
516 info->init_eip = (addr_t)entry;
517
518 free(e);
519
520 return 0;
521}
522
523
524static int match_script(const char *hdr, Int len)
525{
526 return (len > 2) && memcmp(hdr, "#!", 2) == 0;
527}
528
529static int load_script(char *hdr, int len, int fd, const char *name, struct exeinfo *info)
530{
531 char *interp;
532 char *const end = hdr+len;
533 char *cp;
534 char *arg = NULL;
535 int eol;
536
537 interp = hdr + 2;
538 while(interp < end && (*interp == ' ' || *interp == '\t'))
539 interp++;
540
541 if (*interp != '/')
542 return ENOEXEC; /* absolute path only for interpreter */
543
544 /* skip over interpreter name */
545 for(cp = interp; cp < end && *cp != ' ' && *cp != '\t' && *cp != '\n'; cp++)
546 ;
547
548 eol = (*cp == '\n');
549
550 *cp++ = '\0';
551
552 if (!eol && cp < end) {
553 /* skip space before arg */
554 while (cp < end && (*cp == '\t' || *cp == ' '))
555 cp++;
556
557 /* arg is from here to eol */
558 arg = cp;
559 while (cp < end && *cp != '\n')
560 cp++;
561 *cp = '\0';
562 }
563
564 info->argv0 = strdup(interp);
565 if (arg != NULL && *arg != '\0')
566 info->argv1 = strdup(arg);
567
568 if (info->argv && info->argv[0] != NULL)
569 info->argv[0] = (char *)name;
570
571 if (0)
572 printf("#! script: argv0=\"%s\" argv1=\"%s\"\n",
573 info->argv0, info->argv1);
574
575 return do_exec_inner(interp, info);
576}
577
578struct binfmt {
579 int (*match)(const char *hdr, int len);
580 int (*load) ( char *hdr, int len, int fd, const char *name, struct exeinfo *);
581};
582
583static const struct binfmt formats[] = {
584 { match_ELF, load_ELF },
585 { match_script, load_script },
586};
587
588
589static int do_exec_inner(const char *exe, struct exeinfo *info)
590{
591 int fd;
592 char buf[VKI_BYTES_PER_PAGE];
593 int bufsz;
594 int i;
595 int ret;
596 struct stat st;
597
598 fd = open(exe, O_RDONLY);
599 if (fd == -1) {
600 if (0)
601 fprintf(stderr, "Can't open executable %s: %s\n",
602 exe, strerror(errno));
603 return errno;
604 }
605
606 if (fstat(fd, &st) == -1)
607 return errno;
608 else {
609 uid_t uid = geteuid();
610 gid_t gid = getegid();
611 gid_t groups[32];
612 int ngrp = getgroups(32, groups);
613
fitzhardingea49f9b52003-12-16 22:26:45 +0000614 if (st.st_mode & (S_ISUID | S_ISGID)) {
615 fprintf(stderr, "Can't execute suid/sgid executable %s\n", exe);
616 return EACCES;
617 }
618
fitzhardinge7e343cd2003-12-16 02:14:00 +0000619 if (uid == st.st_uid && !(st.st_mode & S_IXUSR))
620 return EACCES;
621
622 if (gid == st.st_gid && !(st.st_mode & S_IXGRP))
623 return EACCES;
624
625 for(i = 0; i < ngrp; i++)
626 if (groups[i] == st.st_gid && !(st.st_mode & S_IXGRP))
627 return EACCES;
628
629 if (!(st.st_mode & S_IXOTH))
630 return EACCES;
631 }
632
633 bufsz = pread(fd, buf, sizeof(buf), 0);
634 if (bufsz < 0) {
635 fprintf(stderr, "Can't read executable header: %s\n",
636 strerror(errno));
637 close(fd);
638 return errno;
639 }
640
641 ret = ENOEXEC;
642 for(i = 0; i < sizeof(formats)/sizeof(*formats); i++) {
643 if ((formats[i].match)(buf, bufsz)) {
644 ret = (formats[i].load)(buf, bufsz, fd, exe, info);
645 break;
646 }
647 }
648
649 close(fd);
650
651 return ret;
652}
653
654int do_exec(const char *exe, struct exeinfo *info)
655{
656 info->argv0 = NULL;
657 info->argv1 = NULL;
658
659 return do_exec_inner(exe, info);
660}