17 #include "trinity.h" // num_online_cpus
19 static unsigned int get_cpu(void)
26 case 1: return rand() % 4095;
27 case 2: return rand() % 15;
30 return rand() % num_online_cpus
;
35 static unsigned long handle_arg_address(int childno
, int call
, int argnum
)
37 unsigned long addr
= 0;
40 return (unsigned long) get_address();
42 /* Half the time, we look to see if earlier args were also ARG_ADDRESS,
43 * and munge that instead of returning a new one from get_address() */
45 addr
= find_previous_arg_address(argnum
, call
, childno
);
48 case 0: break; /* return unmodified */
51 case 2: addr
+= sizeof(int);
53 case 3: addr
+= sizeof(long);
60 static unsigned long handle_arg_range(unsigned int call
, unsigned int argnum
)
62 struct syscallentry
*entry
;
64 unsigned long low
= 0, high
= 0;
66 entry
= syscalls
[call
].entry
;
69 case 1: low
= entry
->low1range
;
70 high
= entry
->hi1range
;
72 case 2: low
= entry
->low2range
;
73 high
= entry
->hi2range
;
75 case 3: low
= entry
->low3range
;
76 high
= entry
->hi3range
;
78 case 4: low
= entry
->low4range
;
79 high
= entry
->hi4range
;
81 case 5: low
= entry
->low5range
;
82 high
= entry
->hi5range
;
84 case 6: low
= entry
->low6range
;
85 high
= entry
->hi6range
;
90 outputerr("%s forgets to set hirange!\n", entry
->name
);
91 BUG("Fix syscall definition!\n");
94 i
= (unsigned long) rand64() % high
;
102 static unsigned long handle_arg_op(unsigned long call
, unsigned long argnum
)
104 struct syscallentry
*entry
;
105 const unsigned long *values
= NULL
;
106 unsigned int num
= 0;
107 unsigned long mask
= 0;
109 entry
= syscalls
[call
].entry
;
112 case 1: num
= entry
->arg1list
.num
;
113 values
= entry
->arg1list
.values
;
115 case 2: num
= entry
->arg2list
.num
;
116 values
= entry
->arg2list
.values
;
118 case 3: num
= entry
->arg3list
.num
;
119 values
= entry
->arg3list
.values
;
121 case 4: num
= entry
->arg4list
.num
;
122 values
= entry
->arg4list
.values
;
124 case 5: num
= entry
->arg5list
.num
;
125 values
= entry
->arg5list
.values
;
127 case 6: num
= entry
->arg6list
.num
;
128 values
= entry
->arg6list
.values
;
133 BUG("ARG_OP with 0 args. What?\n");
136 BUG("ARG_OP with no values.\n");
138 mask
|= values
[rand() % num
];
142 unsigned long set_rand_bitmask(unsigned int num
, const unsigned long *values
)
145 unsigned long mask
= 0;
148 bits
= (rand() % num
) + 1; /* num of bits to OR */
149 for (i
= 0; i
< bits
; i
++)
150 mask
|= values
[rand() % num
];
155 static unsigned long handle_arg_list(unsigned long call
, unsigned long argnum
)
157 struct syscallentry
*entry
;
158 unsigned long mask
= 0;
159 unsigned int num
= 0;
160 const unsigned long *values
= NULL
;
162 entry
= syscalls
[call
].entry
;
165 case 1: num
= entry
->arg1list
.num
;
166 values
= entry
->arg1list
.values
;
168 case 2: num
= entry
->arg2list
.num
;
169 values
= entry
->arg2list
.values
;
171 case 3: num
= entry
->arg3list
.num
;
172 values
= entry
->arg3list
.values
;
174 case 4: num
= entry
->arg4list
.num
;
175 values
= entry
->arg4list
.values
;
177 case 5: num
= entry
->arg5list
.num
;
178 values
= entry
->arg5list
.values
;
180 case 6: num
= entry
->arg6list
.num
;
181 values
= entry
->arg6list
.values
;
186 BUG("ARG_LIST with 0 args. What?\n");
189 BUG("ARG_LIST with no values.\n");
191 mask
= set_rand_bitmask(num
, values
);
195 static unsigned long handle_arg_randpage(void)
197 /* Because we pass this to something that might overwrite it,
198 * and we want page_allocs to remain unmodified, we copy it to page rand instead.
201 memcpy(page_rand
, page_allocs
, page_size
);
203 return (unsigned long) page_rand
;
206 static unsigned long handle_arg_iovec(int childno
, unsigned long call
, unsigned long argnum
)
208 struct syscallentry
*entry
;
209 unsigned long num_entries
;
211 entry
= syscalls
[call
].entry
;
213 num_entries
= (rand() % 256) +1;
216 case 1: if (entry
->arg2type
== ARG_IOVECLEN
)
217 shm
->syscall
[childno
].a2
= num_entries
;
219 case 2: if (entry
->arg3type
== ARG_IOVECLEN
)
220 shm
->syscall
[childno
].a3
= num_entries
;
222 case 3: if (entry
->arg4type
== ARG_IOVECLEN
)
223 shm
->syscall
[childno
].a4
= num_entries
;
225 case 4: if (entry
->arg5type
== ARG_IOVECLEN
)
226 shm
->syscall
[childno
].a5
= num_entries
;
228 case 5: if (entry
->arg6type
== ARG_IOVECLEN
)
229 shm
->syscall
[childno
].a6
= num_entries
;
232 return (unsigned long) alloc_iovec(num_entries
);
235 static unsigned long get_argval(int childno
, unsigned int argnum
)
237 unsigned long val
= 0;
240 case 1: val
= shm
->syscall
[childno
].a1
;
242 case 2: val
= shm
->syscall
[childno
].a2
;
244 case 3: val
= shm
->syscall
[childno
].a3
;
246 case 4: val
= shm
->syscall
[childno
].a4
;
248 case 5: val
= shm
->syscall
[childno
].a5
;
250 case 6: val
= shm
->syscall
[childno
].a6
;
257 static unsigned long handle_arg_sockaddr(int childno
, unsigned long call
, unsigned long argnum
)
259 struct syscallentry
*entry
;
260 struct sockaddr
*sockaddr
= NULL
;
261 socklen_t sockaddrlen
= 0;
263 entry
= syscalls
[call
].entry
;
265 generate_sockaddr((struct sockaddr
**)&sockaddr
, &sockaddrlen
, PF_NOHINT
);
268 case 1: if (entry
->arg2type
== ARG_SOCKADDRLEN
)
269 shm
->syscall
[childno
].a2
= sockaddrlen
;
271 case 2: if (entry
->arg3type
== ARG_SOCKADDRLEN
)
272 shm
->syscall
[childno
].a3
= sockaddrlen
;
274 case 3: if (entry
->arg4type
== ARG_SOCKADDRLEN
)
275 shm
->syscall
[childno
].a4
= sockaddrlen
;
277 case 4: if (entry
->arg5type
== ARG_SOCKADDRLEN
)
278 shm
->syscall
[childno
].a5
= sockaddrlen
;
280 case 5: if (entry
->arg6type
== ARG_SOCKADDRLEN
)
281 shm
->syscall
[childno
].a6
= sockaddrlen
;
286 return (unsigned long) sockaddr
;
289 static unsigned long handle_arg_mode_t(void)
291 unsigned int i
, count
;
296 for (i
= 0; i
< count
; i
++) {
303 case 0: mode
|= S_IRUSR
; break;
304 case 1: mode
|= S_IWUSR
; break;
305 case 2: mode
|= S_IXUSR
; break;
306 case 3: mode
|= S_IRGRP
; break;
307 case 4: mode
|= S_IWGRP
; break;
308 case 5: mode
|= S_IXGRP
; break;
309 case 6: mode
|= S_IROTH
; break;
310 case 7: mode
|= S_IWOTH
; break;
311 case 8: mode
|= S_IXOTH
; break;
312 case 9: mode
|= S_ISUID
; break;
313 case 10: mode
|= S_ISGID
; break;
314 case 11: mode
|= S_ISVTX
; break;
320 static enum argtype
get_argtype(struct syscallentry
*entry
, unsigned int argnum
)
322 enum argtype argtype
= 0;
325 case 1: argtype
= entry
->arg1type
;
327 case 2: argtype
= entry
->arg2type
;
329 case 3: argtype
= entry
->arg3type
;
331 case 4: argtype
= entry
->arg4type
;
333 case 5: argtype
= entry
->arg5type
;
335 case 6: argtype
= entry
->arg6type
;
342 static unsigned long fill_arg(int childno
, int call
, unsigned int argnum
)
344 struct syscallentry
*entry
;
345 enum argtype argtype
;
347 entry
= syscalls
[call
].entry
;
349 if (argnum
> entry
->num_args
)
352 argtype
= get_argtype(entry
, argnum
);
356 case ARG_RANDOM_LONG
:
357 return (unsigned long) rand64();
360 return get_random_fd();
363 return (unsigned long) get_len();
366 return handle_arg_address(childno
, call
, argnum
);
368 case ARG_NON_NULL_ADDRESS
:
369 return (unsigned long) get_non_null_address();
372 return (unsigned long) get_map();
375 return (unsigned long) get_pid();
378 return handle_arg_range(call
, argnum
);
380 case ARG_OP
: /* Like ARG_LIST, but just a single value. */
381 return handle_arg_op(call
, argnum
);
384 return handle_arg_list(call
, argnum
);
387 return handle_arg_randpage();
390 return (unsigned long) get_cpu();
393 return (unsigned long) generate_pathname();
396 return handle_arg_iovec(childno
, call
, argnum
);
399 case ARG_SOCKADDRLEN
:
400 /* We already set the len in the ARG_IOVEC/ARG_SOCKADDR case
401 * So here we just return what we had set there. */
402 return get_argval(childno
, argnum
);
405 return handle_arg_sockaddr(childno
, call
, argnum
);
408 return handle_arg_mode_t();
411 BUG("unreachable!\n");
414 void generic_sanitise(int childno
)
416 struct syscallentry
*entry
;
417 unsigned int call
= shm
->syscall
[childno
].nr
;
419 entry
= syscalls
[call
].entry
;
421 if (entry
->arg1type
!= 0)
422 shm
->syscall
[childno
].a1
= fill_arg(childno
, call
, 1);
423 if (entry
->arg2type
!= 0)
424 shm
->syscall
[childno
].a2
= fill_arg(childno
, call
, 2);
425 if (entry
->arg3type
!= 0)
426 shm
->syscall
[childno
].a3
= fill_arg(childno
, call
, 3);
427 if (entry
->arg4type
!= 0)
428 shm
->syscall
[childno
].a4
= fill_arg(childno
, call
, 4);
429 if (entry
->arg5type
!= 0)
430 shm
->syscall
[childno
].a5
= fill_arg(childno
, call
, 5);
431 if (entry
->arg6type
!= 0)
432 shm
->syscall
[childno
].a6
= fill_arg(childno
, call
, 6);
435 void generic_free_arg(int childno
)
437 struct syscallentry
*entry
;
438 unsigned int call
= shm
->syscall
[childno
].nr
;
439 enum argtype argtype
;
442 entry
= syscalls
[call
].entry
;
444 for (i
= 1; i
<= entry
->num_args
; i
++) {
445 argtype
= get_argtype(entry
, i
);
447 if (argtype
== ARG_IOVEC
)
448 free((void *) get_argval(childno
, i
));