1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
#define _GNU_SOURCE
#include <elf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
static int fails;
#define CHECK(cond, what) \
do { \
if (!(cond)) { \
fails++; \
printf("exechello: FAIL %s\n", what); \
} \
} while (0)
extern const Elf64_Ehdr __ehdr_start;
extern char _end[];
extern char _start[];
static int in_image(const void *p, unsigned long len)
{
unsigned long a = (unsigned long)p, lo = (unsigned long)&__ehdr_start;
return a < (unsigned long)_end && a + len > lo;
}
int main(void)
{
puts("hello from a plain static executable");
CHECK((unsigned long)&__ehdr_start == 0x400000, "image starts at 0x400000");
CHECK(__ehdr_start.e_type == ET_EXEC, "ET_EXEC file");
CHECK(getauxval(AT_ENTRY) == (unsigned long)_start, "AT_ENTRY is _start");
CHECK(getauxval(AT_PHDR) == 0x400000 + __ehdr_start.e_phoff, "AT_PHDR");
char *brk0 = sbrk(0);
CHECK(brk0 != (char *)-1 && brk0 >= _end, "brk starts after the image");
char *more = brk0;
CHECK((char *)syscall(SYS_brk, brk0 + 64 * 1024) == brk0 + 64 * 1024, "brk grows by 64 KiB");
{
memset(more, 0x5a, 64 * 1024);
CHECK(!in_image(more, 64 * 1024), "brk memory outside the image");
}
void *m = mmap(NULL, 1 << 20, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
CHECK(m != MAP_FAILED && !in_image(m, 1 << 20), "mmap outside the image");
CHECK(m == MAP_FAILED || (char *)m > brk0 + 64 * 1024, "mmap above the heap");
for (int i = 0; i < 64; i++) {
size_t n = i % 2 ? 40 : 300 * 1024;
char *p = malloc(n);
CHECK(p && !in_image(p, n), "malloc outside the image");
if (p)
memset(p, i, n);
free(p);
}
printf("image %p..%p, brk %p, mmap %p\n", (void *)&__ehdr_start, (void *)_end, (void *)brk0, m);
printf("exechello: %d failed\n", fails);
return fails;
}
|