6 #include "trinity.h" // page_size
18 static unsigned int get_cpu(void)
25 case 1: return rand() % 4095;
26 case 2: return rand() % 15;
29 return rand() % num_online_cpus
;
32 BUG("unreachable!\n");
38 static unsigned long handle_arg_address(int childno
, int call
, int argnum
)
40 unsigned long addr
= 0;
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
);
51 case 0: break; /* return unmodified */
54 case 2: addr
+= sizeof(int);
56 case 3: addr
+= sizeof(long);
58 default: BUG("unreachable!\n");
65 static unsigned long handle_arg_range(unsigned int call
, unsigned int argnum
)
68 unsigned long low
= 0, high
= 0;
71 case 1: low
= syscalls
[call
].entry
->low1range
;
72 high
= syscalls
[call
].entry
->hi1range
;
74 case 2: low
= syscalls
[call
].entry
->low2range
;
75 high
= syscalls
[call
].entry
->hi2range
;
77 case 3: low
= syscalls
[call
].entry
->low3range
;
78 high
= syscalls
[call
].entry
->hi3range
;
80 case 4: low
= syscalls
[call
].entry
->low4range
;
81 high
= syscalls
[call
].entry
->hi4range
;
83 case 5: low
= syscalls
[call
].entry
->low5range
;
84 high
= syscalls
[call
].entry
->hi5range
;
86 case 6: low
= syscalls
[call
].entry
->low6range
;
87 high
= syscalls
[call
].entry
->hi6range
;
90 BUG("Should never happen.\n");
95 outputerr("%s forgets to set hirange!\n", syscalls
[call
].entry
->name
);
96 BUG("Fix syscall definition!\n");
100 i
= (unsigned long) rand64() % high
;
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;
115 case 1: num
= syscalls
[call
].entry
->arg1list
.num
;
116 values
= syscalls
[call
].entry
->arg1list
.values
;
118 case 2: num
= syscalls
[call
].entry
->arg2list
.num
;
119 values
= syscalls
[call
].entry
->arg2list
.values
;
121 case 3: num
= syscalls
[call
].entry
->arg3list
.num
;
122 values
= syscalls
[call
].entry
->arg3list
.values
;
124 case 4: num
= syscalls
[call
].entry
->arg4list
.num
;
125 values
= syscalls
[call
].entry
->arg4list
.values
;
127 case 5: num
= syscalls
[call
].entry
->arg5list
.num
;
128 values
= syscalls
[call
].entry
->arg5list
.values
;
130 case 6: num
= syscalls
[call
].entry
->arg6list
.num
;
131 values
= syscalls
[call
].entry
->arg6list
.values
;
137 BUG("ARG_OP with 0 args. What?\n");
140 BUG("ARG_OP with no values.\n");
142 mask
|= values
[rand() % num
];
146 static unsigned long handle_arg_list(unsigned long call
, unsigned long argnum
)
149 unsigned long mask
= 0;
151 unsigned int num
= 0;
152 const unsigned int *values
= NULL
;
155 case 1: num
= syscalls
[call
].entry
->arg1list
.num
;
156 values
= syscalls
[call
].entry
->arg1list
.values
;
158 case 2: num
= syscalls
[call
].entry
->arg2list
.num
;
159 values
= syscalls
[call
].entry
->arg2list
.values
;
161 case 3: num
= syscalls
[call
].entry
->arg3list
.num
;
162 values
= syscalls
[call
].entry
->arg3list
.values
;
164 case 4: num
= syscalls
[call
].entry
->arg4list
.num
;
165 values
= syscalls
[call
].entry
->arg4list
.values
;
167 case 5: num
= syscalls
[call
].entry
->arg5list
.num
;
168 values
= syscalls
[call
].entry
->arg5list
.values
;
170 case 6: num
= syscalls
[call
].entry
->arg6list
.num
;
171 values
= syscalls
[call
].entry
->arg6list
.values
;
177 BUG("ARG_LIST with 0 args. What?\n");
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
];
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.
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
)
203 i
= (rand() % 5) + 1;
206 case 1: if (syscalls
[call
].entry
->arg2type
== ARG_IOVECLEN
)
207 shm
->a2
[childno
] = i
;
209 case 2: if (syscalls
[call
].entry
->arg3type
== ARG_IOVECLEN
)
210 shm
->a3
[childno
] = i
;
212 case 3: if (syscalls
[call
].entry
->arg4type
== ARG_IOVECLEN
)
213 shm
->a4
[childno
] = i
;
215 case 4: if (syscalls
[call
].entry
->arg5type
== ARG_IOVECLEN
)
216 shm
->a5
[childno
] = i
;
218 case 5: if (syscalls
[call
].entry
->arg6type
== ARG_IOVECLEN
)
219 shm
->a6
[childno
] = i
;
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
)
231 * We already set the len in the ARG_IOVEC/ARG_SOCKADDR case
232 * So here we just return what we had set there.
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;
246 static unsigned long handle_arg_sockaddr(int childno
, unsigned long call
, unsigned long argnum
)
248 struct sockaddr
*sockaddr
= NULL
;
249 socklen_t sockaddrlen
= 0;
251 generate_sockaddr((struct sockaddr
**)&sockaddr
, &sockaddrlen
, PF_NOHINT
);
254 case 1: if (syscalls
[call
].entry
->arg2type
== ARG_SOCKADDRLEN
)
255 shm
->a2
[childno
] = sockaddrlen
;
257 case 2: if (syscalls
[call
].entry
->arg3type
== ARG_SOCKADDRLEN
)
258 shm
->a3
[childno
] = sockaddrlen
;
260 case 3: if (syscalls
[call
].entry
->arg4type
== ARG_SOCKADDRLEN
)
261 shm
->a4
[childno
] = sockaddrlen
;
263 case 4: if (syscalls
[call
].entry
->arg5type
== ARG_SOCKADDRLEN
)
264 shm
->a5
[childno
] = sockaddrlen
;
266 case 5: if (syscalls
[call
].entry
->arg6type
== ARG_SOCKADDRLEN
)
267 shm
->a6
[childno
] = sockaddrlen
;
270 default: BUG("impossible\n");
272 return (unsigned long) sockaddr
;
275 static unsigned long handle_arg_mode_t(void)
277 unsigned int i
, j
, count
, bit
;
282 for (i
= 0; i
< count
; i
++) {
287 case 0: mode
|= S_IRUSR
; break;
288 case 1: mode
|= S_IWUSR
; break;
289 case 2: mode
|= S_IXUSR
; break;
290 case 3: mode
|= S_IRGRP
; break;
291 case 4: mode
|= S_IWGRP
; break;
292 case 5: mode
|= S_IXGRP
; break;
293 case 6: mode
|= S_IROTH
; break;
294 case 7: mode
|= S_IWOTH
; break;
295 case 8: mode
|= S_IXOTH
; break;
296 case 9: mode
|= S_ISUID
; break;
297 case 10: mode
|= S_ISGID
; break;
298 case 11: mode
|= S_ISVTX
; break;
306 static unsigned long fill_arg(int childno
, int call
, unsigned int argnum
)
308 enum argtype argtype
= 0;
310 if (argnum
> syscalls
[call
].entry
->num_args
)
314 case 1: argtype
= syscalls
[call
].entry
->arg1type
;
316 case 2: argtype
= syscalls
[call
].entry
->arg2type
;
318 case 3: argtype
= syscalls
[call
].entry
->arg3type
;
320 case 4: argtype
= syscalls
[call
].entry
->arg4type
;
322 case 5: argtype
= syscalls
[call
].entry
->arg5type
;
324 case 6: argtype
= syscalls
[call
].entry
->arg6type
;
327 BUG("unreachable!\n");
333 case ARG_RANDOM_LONG
:
334 return (unsigned long) rand64();
337 return get_random_fd();
340 return (unsigned long) get_len();
343 return handle_arg_address(childno
, call
, argnum
);
345 case ARG_NON_NULL_ADDRESS
:
346 return (unsigned long) get_non_null_address();
349 return (unsigned long) get_map();
352 return (unsigned long) get_pid();
355 return handle_arg_range(call
, argnum
);
357 case ARG_OP
: /* Like ARG_LIST, but just a single value. */
358 return handle_arg_op(call
, argnum
);
361 return handle_arg_list(call
, argnum
);
364 return handle_arg_randpage();
367 return (unsigned long) get_cpu();
370 return (unsigned long) generate_pathname();
373 return handle_arg_iovec(childno
, call
, argnum
);
376 case ARG_SOCKADDRLEN
:
377 return handle_arg_len_already_set(childno
, argnum
);
380 return handle_arg_sockaddr(childno
, call
, argnum
);
383 return handle_arg_mode_t();
386 BUG("unreachable!\n");
390 BUG("unreachable!\n");
391 return 0x5a5a5a5a; /* Should never happen */
394 void generic_sanitise(int childno
)
396 unsigned int call
= shm
->syscallno
[childno
];
398 if (syscalls
[call
].entry
->arg1type
!= 0)
399 shm
->a1
[childno
] = fill_arg(childno
, call
, 1);
400 if (syscalls
[call
].entry
->arg2type
!= 0)
401 shm
->a2
[childno
] = fill_arg(childno
, call
, 2);
402 if (syscalls
[call
].entry
->arg3type
!= 0)
403 shm
->a3
[childno
] = fill_arg(childno
, call
, 3);
404 if (syscalls
[call
].entry
->arg4type
!= 0)
405 shm
->a4
[childno
] = fill_arg(childno
, call
, 4);
406 if (syscalls
[call
].entry
->arg5type
!= 0)
407 shm
->a5
[childno
] = fill_arg(childno
, call
, 5);
408 if (syscalls
[call
].entry
->arg6type
!= 0)
409 shm
->a6
[childno
] = fill_arg(childno
, call
, 6);