throw away result, we don't care.
[trinity.git] / generic-sanitise.c
blob827b363d06a94a64cd3d8364a62f1b47b023ceec
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
6 #include "trinity.h" // page_size
7 #include "files.h"
8 #include "arch.h"
9 #include "random.h"
10 #include "sanitise.h"
11 #include "syscall.h"
12 #include "net.h"
13 #include "log.h"
14 #include "maps.h"
15 #include "shm.h"
16 #include "tables.h"
18 static unsigned int get_cpu(void)
20 int i;
21 i = rand() % 100;
23 switch (i) {
24 case 0: return -1;
25 case 1: return rand() % 4095;
26 case 2: return rand() % 15;
28 case 3 ... 99:
29 return rand() % num_online_cpus;
31 default:
32 BUG("unreachable!\n");
33 break;
35 return 0;
38 static unsigned long handle_arg_address(int childno, int call, int argnum)
40 unsigned long addr = 0;
42 if (rand_bool())
43 return (unsigned long) get_address();
45 /* Half the time, we look to see if earlier args were also ARG_ADDRESS,
46 * and munge that instead of returning a new one from get_address() */
48 addr = find_previous_arg_address(argnum, call, childno);
50 switch (rand() % 4) {
51 case 0: break; /* return unmodified */
52 case 1: addr++;
53 break;
54 case 2: addr+= sizeof(int);
55 break;
56 case 3: addr+= sizeof(long);
57 break;
58 default: BUG("unreachable!\n");
59 break;
62 return addr;
65 static unsigned long handle_arg_range(unsigned int call, unsigned int argnum)
67 unsigned long i;
68 unsigned long low = 0, high = 0;
70 switch (argnum) {
71 case 1: low = syscalls[call].entry->low1range;
72 high = syscalls[call].entry->hi1range;
73 break;
74 case 2: low = syscalls[call].entry->low2range;
75 high = syscalls[call].entry->hi2range;
76 break;
77 case 3: low = syscalls[call].entry->low3range;
78 high = syscalls[call].entry->hi3range;
79 break;
80 case 4: low = syscalls[call].entry->low4range;
81 high = syscalls[call].entry->hi4range;
82 break;
83 case 5: low = syscalls[call].entry->low5range;
84 high = syscalls[call].entry->hi5range;
85 break;
86 case 6: low = syscalls[call].entry->low6range;
87 high = syscalls[call].entry->hi6range;
88 break;
89 default:
90 BUG("Should never happen.\n");
91 break;
94 if (high == 0) {
95 outputerr("%s forgets to set hirange!\n", syscalls[call].entry->name);
96 BUG("Fix syscall definition!\n");
97 return 0;
100 i = (unsigned long) rand64() % high;
101 if (i < low) {
102 i += low;
103 i &= high;
105 return i;
108 static unsigned long handle_arg_op(unsigned long call, unsigned long argnum)
110 const unsigned int *values = NULL;
111 unsigned int num = 0;
112 unsigned long mask = 0;
114 switch (argnum) {
115 case 1: num = syscalls[call].entry->arg1list.num;
116 values = syscalls[call].entry->arg1list.values;
117 break;
118 case 2: num = syscalls[call].entry->arg2list.num;
119 values = syscalls[call].entry->arg2list.values;
120 break;
121 case 3: num = syscalls[call].entry->arg3list.num;
122 values = syscalls[call].entry->arg3list.values;
123 break;
124 case 4: num = syscalls[call].entry->arg4list.num;
125 values = syscalls[call].entry->arg4list.values;
126 break;
127 case 5: num = syscalls[call].entry->arg5list.num;
128 values = syscalls[call].entry->arg5list.values;
129 break;
130 case 6: num = syscalls[call].entry->arg6list.num;
131 values = syscalls[call].entry->arg6list.values;
132 break;
133 default: break;
136 if (num == 0)
137 BUG("ARG_OP with 0 args. What?\n");
139 if (values == NULL)
140 BUG("ARG_OP with no values.\n");
142 mask |= values[rand() % num];
143 return mask;
146 static unsigned long handle_arg_list(unsigned long call, unsigned long argnum)
148 unsigned long i;
149 unsigned long mask = 0;
150 unsigned int bits;
151 unsigned int num = 0;
152 const unsigned int *values = NULL;
154 switch (argnum) {
155 case 1: num = syscalls[call].entry->arg1list.num;
156 values = syscalls[call].entry->arg1list.values;
157 break;
158 case 2: num = syscalls[call].entry->arg2list.num;
159 values = syscalls[call].entry->arg2list.values;
160 break;
161 case 3: num = syscalls[call].entry->arg3list.num;
162 values = syscalls[call].entry->arg3list.values;
163 break;
164 case 4: num = syscalls[call].entry->arg4list.num;
165 values = syscalls[call].entry->arg4list.values;
166 break;
167 case 5: num = syscalls[call].entry->arg5list.num;
168 values = syscalls[call].entry->arg5list.values;
169 break;
170 case 6: num = syscalls[call].entry->arg6list.num;
171 values = syscalls[call].entry->arg6list.values;
172 break;
173 default: break;
176 if (num == 0)
177 BUG("ARG_LIST with 0 args. What?\n");
179 if (values == NULL)
180 BUG("ARG_LIST with no values.\n");
182 bits = rand() % (num + 1); /* num of bits to OR */
183 for (i = 0; i < bits; i++)
184 mask |= values[rand() % num];
185 return mask;
188 static unsigned long handle_arg_randpage(void)
190 /* Because we pass this to something that might overwrite it,
191 * and we want page_allocs to remain unmodified, we copy it to page rand instead.
193 if (rand_bool())
194 memcpy(page_rand, page_allocs, page_size);
196 return (unsigned long) page_rand;
199 static unsigned long handle_arg_iovec(int childno, unsigned long call, unsigned long argnum)
201 unsigned long i;
203 i = (rand() % 5) + 1;
205 switch (argnum) {
206 case 1: if (syscalls[call].entry->arg2type == ARG_IOVECLEN)
207 shm->a2[childno] = i;
208 break;
209 case 2: if (syscalls[call].entry->arg3type == ARG_IOVECLEN)
210 shm->a3[childno] = i;
211 break;
212 case 3: if (syscalls[call].entry->arg4type == ARG_IOVECLEN)
213 shm->a4[childno] = i;
214 break;
215 case 4: if (syscalls[call].entry->arg5type == ARG_IOVECLEN)
216 shm->a5[childno] = i;
217 break;
218 case 5: if (syscalls[call].entry->arg6type == ARG_IOVECLEN)
219 shm->a6[childno] = i;
220 break;
221 default: BUG("impossible\n");
223 return (unsigned long) alloc_iovec(i);
226 static unsigned long handle_arg_len_already_set(int childno, unsigned long argnum)
228 unsigned long r = 0;
231 * We already set the len in the ARG_IOVEC/ARG_SOCKADDR case
232 * So here we just return what we had set there.
234 switch (argnum) {
235 case 1: r = shm->a1[childno]; break;
236 case 2: r = shm->a2[childno]; break;
237 case 3: r = shm->a3[childno]; break;
238 case 4: r = shm->a4[childno]; break;
239 case 5: r = shm->a5[childno]; break;
240 case 6: r = shm->a6[childno]; break;
241 default: break;
243 return r;
246 static unsigned long handle_arg_sockaddr(int childno, unsigned long call, unsigned long argnum)
248 unsigned long sockaddr = 0, sockaddrlen = 0;
250 generate_sockaddr((unsigned long **)&sockaddr, &sockaddrlen, PF_NOHINT);
252 switch (argnum) {
253 case 1: if (syscalls[call].entry->arg2type == ARG_SOCKADDRLEN)
254 shm->a2[childno] = sockaddrlen;
255 break;
256 case 2: if (syscalls[call].entry->arg3type == ARG_SOCKADDRLEN)
257 shm->a3[childno] = sockaddrlen;
258 break;
259 case 3: if (syscalls[call].entry->arg4type == ARG_SOCKADDRLEN)
260 shm->a4[childno] = sockaddrlen;
261 break;
262 case 4: if (syscalls[call].entry->arg5type == ARG_SOCKADDRLEN)
263 shm->a5[childno] = sockaddrlen;
264 break;
265 case 5: if (syscalls[call].entry->arg6type == ARG_SOCKADDRLEN)
266 shm->a6[childno] = sockaddrlen;
267 break;
268 case 6:
269 default: BUG("impossible\n");
271 return (unsigned long) sockaddr;
274 static unsigned long handle_arg_mode_t(void)
276 unsigned int i, j, count, bit;
277 mode_t mode = 0;
279 count = rand() % 9;
281 for (i = 0; i < count; i++) {
282 bit = rand() % 3;
283 mode |= 1 << bit;
284 j = rand() % 12;
285 switch (j) {
286 case 0: mode |= S_IRUSR; break;
287 case 1: mode |= S_IWUSR; break;
288 case 2: mode |= S_IXUSR; break;
289 case 3: mode |= S_IRGRP; break;
290 case 4: mode |= S_IWGRP; break;
291 case 5: mode |= S_IXGRP; break;
292 case 6: mode |= S_IROTH; break;
293 case 7: mode |= S_IWOTH; break;
294 case 8: mode |= S_IXOTH; break;
295 case 9: mode |= S_ISUID; break;
296 case 10: mode|= S_ISGID; break;
297 case 11: mode|= S_ISVTX; break;
298 default: break;
301 return mode;
305 static unsigned long fill_arg(int childno, int call, unsigned int argnum)
307 enum argtype argtype = 0;
309 if (argnum > syscalls[call].entry->num_args)
310 return 0;
312 switch (argnum) {
313 case 1: argtype = syscalls[call].entry->arg1type;
314 break;
315 case 2: argtype = syscalls[call].entry->arg2type;
316 break;
317 case 3: argtype = syscalls[call].entry->arg3type;
318 break;
319 case 4: argtype = syscalls[call].entry->arg4type;
320 break;
321 case 5: argtype = syscalls[call].entry->arg5type;
322 break;
323 case 6: argtype = syscalls[call].entry->arg6type;
324 break;
325 default:
326 BUG("unreachable!\n");
327 return 0;
330 switch (argtype) {
331 case ARG_UNDEFINED:
332 case ARG_RANDOM_LONG:
333 return (unsigned long) rand64();
335 case ARG_FD:
336 return get_random_fd();
338 case ARG_LEN:
339 return (unsigned long) get_len();
341 case ARG_ADDRESS:
342 return handle_arg_address(childno, call, argnum);
344 case ARG_NON_NULL_ADDRESS:
345 return (unsigned long) get_non_null_address();
347 case ARG_MMAP:
348 return (unsigned long) get_map();
350 case ARG_PID:
351 return (unsigned long) get_pid();
353 case ARG_RANGE:
354 return handle_arg_range(call, argnum);
356 case ARG_OP: /* Like ARG_LIST, but just a single value. */
357 return handle_arg_op(call, argnum);
359 case ARG_LIST:
360 return handle_arg_list(call, argnum);
362 case ARG_RANDPAGE:
363 return handle_arg_randpage();
365 case ARG_CPU:
366 return (unsigned long) get_cpu();
368 case ARG_PATHNAME:
369 return (unsigned long) generate_pathname();
371 case ARG_IOVEC:
372 return handle_arg_iovec(childno, call, argnum);
374 case ARG_IOVECLEN:
375 case ARG_SOCKADDRLEN:
376 return handle_arg_len_already_set(childno, argnum);
378 case ARG_SOCKADDR:
379 return handle_arg_sockaddr(childno, call, argnum);
381 case ARG_MODE_T:
382 return handle_arg_mode_t();
384 default:
385 BUG("unreachable!\n");
386 return 0;
389 BUG("unreachable!\n");
390 return 0x5a5a5a5a; /* Should never happen */
393 void generic_sanitise(int childno)
395 unsigned int call = shm->syscallno[childno];
397 if (syscalls[call].entry->arg1type != 0)
398 shm->a1[childno] = fill_arg(childno, call, 1);
399 if (syscalls[call].entry->arg2type != 0)
400 shm->a2[childno] = fill_arg(childno, call, 2);
401 if (syscalls[call].entry->arg3type != 0)
402 shm->a3[childno] = fill_arg(childno, call, 3);
403 if (syscalls[call].entry->arg4type != 0)
404 shm->a4[childno] = fill_arg(childno, call, 4);
405 if (syscalls[call].entry->arg5type != 0)
406 shm->a5[childno] = fill_arg(childno, call, 5);
407 if (syscalls[call].entry->arg6type != 0)
408 shm->a6[childno] = fill_arg(childno, call, 6);