split up constants.h some
[trinity.git] / random-address.c
blobcbf15c8e426275c6913c7c55470356841e7f7a64
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <sys/uio.h>
7 #include "trinity.h" // page_size
8 #include "arch.h" // KERNEL_ADDR etc
9 #include "log.h"
10 #include "random.h"
11 #include "sanitise.h"
12 #include "maps.h"
13 #include "shm.h"
14 #include "tables.h"
17 static bool within_page(void *addr, void *check)
19 if (addr == check)
20 return TRUE;
21 if ((addr > check) && (addr < (check + page_size)))
22 return TRUE;
23 return FALSE;
26 bool validate_address(void *addr)
28 if (within_page(addr, shm) == TRUE)
29 return FALSE;
30 if (within_page(addr, page_rand) == TRUE)
31 return FALSE;
32 if (within_page(addr, page_zeros) == TRUE)
33 return FALSE;
34 if (within_page(addr, page_0xff) == TRUE)
35 return FALSE;
36 if (within_page(addr, page_allocs) == TRUE)
37 return FALSE;
39 return TRUE;
43 static void * _get_address(unsigned char null_allowed)
45 int i;
46 struct map *map;
47 size_t len = page_size;
48 void *addr = NULL;
50 /* Because we get called during startup when we create fd's, we need
51 * to special case this, as we can't use get_non_null_address at that point */
52 if (getpid() == shm->mainpid)
53 return page_rand;
55 if (null_allowed == TRUE)
56 i = rand() % 10;
57 else
58 i = (rand() % 9) + 1;
61 switch (i) {
62 case 0: addr = NULL;
63 break;
64 case 1: addr = (void *) KERNEL_ADDR;
65 break;
66 case 2: addr = page_zeros;
67 break;
68 case 3: addr = page_0xff;
69 break;
70 case 4: addr = page_rand;
71 break;
72 case 5: addr = page_allocs;
73 break;
74 case 6: addr = (void *)(unsigned long)rand64();
75 break;
76 case 7: map = get_map();
77 addr = map->ptr;
78 len = map->size;
79 break;
80 case 8: addr = malloc(page_size * 2);
81 // FIXME: We leak this. This is the address we need to store for later
82 // freeing, not the potentially munged version below.
83 // tricky. We want to hand the munged version out too, so we might end up
84 // having to split this into alloc_address / get_address.
85 break;
86 case 9: addr = page_maps;
87 break;
91 * Most of the time, we just return the address we got above unmunged.
92 * But sometimes, we return an address just before the end of the page.
93 * The idea here is that we might see some bugs that are caused by page boundary failures.
95 i = rand() % 100;
96 switch (i) {
97 case 0: addr += (len - sizeof(char));
98 break;
99 case 1: addr += (len - sizeof(int));
100 break;
101 case 2: addr += (len - sizeof(long));
102 break;
103 case 3: addr += (len / 2);
104 break;
105 case 4 ... 99:
106 break;
109 return addr;
112 void * get_address(void)
114 return _get_address(TRUE);
117 void * get_non_null_address(void)
119 return _get_address(FALSE);
123 unsigned long find_previous_arg_address(unsigned int argnum, unsigned int call, int childno)
125 struct syscallentry *entry;
126 unsigned long addr = 0;
128 entry = syscalls[call].entry;
130 if (argnum > 1)
131 if ((entry->arg1type == ARG_ADDRESS) ||
132 (entry->arg1type == ARG_NON_NULL_ADDRESS))
133 addr = shm->syscall[childno].a1;
135 if (argnum > 2)
136 if ((entry->arg2type == ARG_ADDRESS) ||
137 (entry->arg2type == ARG_NON_NULL_ADDRESS))
138 addr = shm->syscall[childno].a2;
140 if (argnum > 3)
141 if ((entry->arg3type == ARG_ADDRESS) ||
142 (entry->arg3type == ARG_NON_NULL_ADDRESS))
143 addr = shm->syscall[childno].a3;
145 if (argnum > 4)
146 if ((entry->arg4type == ARG_ADDRESS) ||
147 (entry->arg4type == ARG_NON_NULL_ADDRESS))
148 addr = shm->syscall[childno].a4;
150 if (argnum > 5)
151 if ((entry->arg5type == ARG_ADDRESS) ||
152 (entry->arg5type == ARG_NON_NULL_ADDRESS))
153 addr = shm->syscall[childno].a5;
155 return addr;
159 struct iovec * alloc_iovec(unsigned int num)
161 struct iovec *iov;
163 iov = malloc(num * sizeof(struct iovec)); /* freed by generic_free_arg */
164 if (iov != NULL) {
165 unsigned int i;
167 for (i = 0; i < num; i++) {
168 struct map *map;
170 map = get_map();
171 iov[i].iov_base = map->ptr;
172 iov[i].iov_len = rand() % map->size;
175 return iov;