plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 1 | /* |
| 2 | * crash02.c - Test OS robustness by executing syscalls with random args. |
| 3 | * |
| 4 | * Copyright (C) 2001 Stephane Fillod <f4cfe@free.fr> |
| 5 | * |
| 6 | * This test program was inspired from crashme, by GEORGE J. CARRETT. |
| 7 | * |
| 8 | * This program is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU General Public License |
| 10 | * as published by the Free Software Foundation; either version 2 |
| 11 | * of the License, or (at your option) any later version. |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 12 | * |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 13 | * This program is distributed in the hope that it will be useful, |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 16 | * GNU General Public License for more details. |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 17 | * |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 18 | * You should have received a copy of the GNU General Public License |
| 19 | * along with this program; if not, write to the Free Software |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 21 | */ |
| 22 | |
| 23 | /* |
| 24 | A signal handler is set up so that in most cases the machine exception |
| 25 | generated by the illegal syscall, bad operands, etc in the procedure |
| 26 | made up of random data are caught; and another round of randomness may |
| 27 | be tried. Eventually a random syscall may corrupt the program or |
| 28 | the machine state in such a way that the program must halt. This is |
| 29 | a test of the robustness of the hardware/software for instruction |
| 30 | fault handling. |
| 31 | |
| 32 | Note: Running this program just a few times, using total CPU time of |
| 33 | less than a few seconds SHOULD NOT GIVE YOU ANY CONFIDENCE in system |
| 34 | robustness. Having it run for hours, with tens of thousands of cases |
| 35 | would be a different thing. It would also make sense to run this |
| 36 | stress test at the same time you run other tests, like a multi-user |
| 37 | benchmark. |
| 38 | |
| 39 | CAUTION: running this program may crash your system, your disk and all |
| 40 | your data along! DO NOT RUN IT ON PRODUCTION SYSTEMS! |
| 41 | CONSIDER YOUR DISK FRIED. |
| 42 | REMEMBER THE DISCLAIMER PART OF THE LICENSE. |
| 43 | |
| 44 | Running as user nobody and with all your filesystems |
| 45 | remounted to readonly may be wise.. |
| 46 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 47 | TODO: |
| 48 | * in rand_long(), stuff in some real pointers to random data |
| 49 | * Does a syscall is supposed to send SIGSEGV? |
| 50 | */ |
| 51 | |
subrata_modak | 1b77909 | 2009-05-25 15:27:10 +0000 | [diff] [blame] | 52 | #define _GNU_SOURCE |
| 53 | #include <sys/syscall.h> |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 54 | #include <stdio.h> |
| 55 | #include <stdlib.h> |
| 56 | #include <string.h> |
| 57 | #include <signal.h> |
| 58 | #include <setjmp.h> |
| 59 | #include <time.h> |
| 60 | #include <unistd.h> |
| 61 | #include <errno.h> |
| 62 | #include <sys/types.h> |
| 63 | #include <sys/wait.h> |
| 64 | |
| 65 | #include "test.h" |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 66 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 67 | char *TCID = "crash02"; |
| 68 | int TST_TOTAL = 1; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 69 | |
| 70 | static int x_opt = 0; |
| 71 | static int v_opt = 0; |
| 72 | static char *v_copt; |
| 73 | static int s_opt = 0; |
| 74 | static char *s_copt; |
| 75 | static int l_opt = 0; |
| 76 | static char *l_copt; |
| 77 | static int n_opt = 0; |
| 78 | static char *n_copt; |
| 79 | |
| 80 | int verbose_level = 2; |
| 81 | |
| 82 | /* depends on architecture.. */ |
| 83 | unsigned int sysno_max = 127; |
| 84 | |
| 85 | int nseed; |
| 86 | int ntries = 100; |
| 87 | |
| 88 | /* max time allowed per try, in seconds */ |
| 89 | #define MAX_TRY_TIME 5 |
| 90 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 91 | void cleanup() |
| 92 | { |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 93 | |
| 94 | tst_rmdir(); |
| 95 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | void setup() |
| 99 | { |
| 100 | /* |
| 101 | * setup a default signal hander and a |
| 102 | * temporary working directory. |
| 103 | */ |
| 104 | tst_sig(FORK, DEF_HANDLER, cleanup); |
| 105 | |
| 106 | TEST_PAUSE; |
| 107 | |
| 108 | tst_tmpdir(); |
| 109 | } |
| 110 | |
| 111 | void help() |
| 112 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 113 | printf |
| 114 | (" -x dry run, hexdump random code instead\n"); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 115 | printf(" -l x max syscall no\n"); |
| 116 | printf(" -v x verbose level\n"); |
| 117 | printf(" -s x random seed\n"); |
| 118 | printf(" -n x ntries\n"); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | /* |
| 122 | */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 123 | option_t options[] = { |
| 124 | {"v:", &v_opt, &v_copt}, |
| 125 | {"l:", &l_opt, &l_copt}, |
| 126 | {"s:", &s_opt, &s_copt}, |
| 127 | {"n:", &n_opt, &n_copt}, |
| 128 | {"x", &x_opt, NULL}, |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 129 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 130 | {NULL, NULL, NULL} |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 131 | }; |
| 132 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 133 | void badboy_fork(); |
| 134 | void badboy_loop(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 135 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 136 | void summarize_errno(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 137 | void record_errno(unsigned int n); |
| 138 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 139 | int main(int argc, char *argv[]) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 140 | { |
Cyril Hrubis | 0b9589f | 2014-05-27 17:40:33 +0200 | [diff] [blame] | 141 | const char *msg; |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 142 | int lc; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 143 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 144 | if ((msg = parse_opts(argc, argv, options, help)) != NULL) |
| 145 | tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 146 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 147 | if (v_opt) |
| 148 | verbose_level = atoi(v_copt); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 149 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 150 | if (n_opt) |
| 151 | ntries = atoi(n_copt); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 152 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 153 | if (l_opt) |
| 154 | sysno_max = atoi(l_copt); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 155 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 156 | if (s_opt) |
| 157 | nseed = atoi(s_copt); |
| 158 | else |
| 159 | nseed = time(NULL); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 160 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 161 | setup(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 162 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 163 | for (lc = 0; TEST_LOOPING(lc); lc++) { |
Caspar Zhang | d59a659 | 2013-03-07 14:59:12 +0800 | [diff] [blame] | 164 | tst_count = 0; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 165 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 166 | tst_resm(TINFO, "crashme02 %d %d %d", sysno_max, nseed, ntries); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 167 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 168 | srand(nseed); |
| 169 | badboy_fork(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 170 | |
| 171 | /* still there? */ |
| 172 | tst_resm(TPASS, "we're still here, OS seems to be robust"); |
| 173 | |
| 174 | nseed++; |
| 175 | } |
| 176 | cleanup(); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 177 | tst_exit(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 178 | } |
| 179 | |
| 180 | /* ************************* */ |
| 181 | int badboy_pid; |
| 182 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 183 | void my_signal(int sig, void (*func) ()); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 184 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 185 | void monitor_fcn(int sig) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 186 | { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 187 | int status; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 188 | |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 189 | if (verbose_level >= 3) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 190 | printf("time limit reached on pid. using kill.\n"); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 191 | |
| 192 | status = kill(badboy_pid, SIGKILL); |
| 193 | if (status < 0) { |
| 194 | if (verbose_level >= 3) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 195 | printf("failed to kill process\n"); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 196 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 197 | } |
| 198 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 199 | void badboy_fork() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 200 | { |
| 201 | int status, pid; |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 202 | pid_t child; |
| 203 | child = fork(); |
| 204 | badboy_pid = status; |
| 205 | switch (child) { |
| 206 | case -1: |
| 207 | perror("fork"); |
| 208 | case 0: |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 209 | #ifdef DEBUG_LATE_BADBOY |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 210 | sleep(ntries * MAX_TRY_TIME + 10); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 211 | #else |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 212 | badboy_loop(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 213 | #endif |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 214 | exit(0); |
| 215 | default: |
| 216 | if (verbose_level > 3) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 217 | printf("badboy pid = %d\n", badboy_pid); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 218 | |
| 219 | /* don't trust the child to return at night */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 220 | my_signal(SIGALRM, monitor_fcn); |
| 221 | alarm(ntries * MAX_TRY_TIME); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 222 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 223 | pid = waitpid(-1, &status, WUNTRACED); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 224 | if (pid <= 0) |
| 225 | perror("wait"); |
| 226 | else { |
| 227 | if (verbose_level > 3) |
| 228 | printf("pid %d exited with status %d\n", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 229 | pid, status); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 230 | #if 0 |
| 231 | record_status(status); |
| 232 | #endif |
| 233 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 234 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 235 | alarm(0); |
| 236 | } |
| 237 | |
| 238 | /* *************** status recording ************************* */ |
| 239 | |
| 240 | /* errno status table (max is actually around 127) */ |
| 241 | #define STATUS_MAX 256 |
| 242 | static int errno_table[STATUS_MAX]; |
| 243 | |
| 244 | void record_errno(unsigned int n) |
| 245 | { |
| 246 | if (n >= STATUS_MAX) |
| 247 | return; |
| 248 | |
| 249 | errno_table[n]++; |
| 250 | } |
| 251 | |
| 252 | /* may not work with -c option */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 253 | void summarize_errno() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 254 | { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 255 | int i; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 256 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 257 | if (x_opt || verbose_level < 2) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 258 | return; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 259 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 260 | printf("errno status ... number of cases\n"); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 261 | for (i = 0; i < STATUS_MAX; i++) { |
| 262 | if (errno_table[i]) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 263 | printf("%12d ... %5d\n", i, errno_table[i]); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 264 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 265 | } |
| 266 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 267 | /* ************* badboy ******************************************* */ |
| 268 | |
| 269 | jmp_buf again_buff; |
| 270 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 271 | unsigned char *bad_malloc(int n); |
| 272 | void my_signal(int sig, void (*func) ()); |
| 273 | void again_handler(int sig); |
| 274 | void try_one_crash(int try_num); |
| 275 | void set_up_signals(); |
| 276 | int in_blacklist(int sysno); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 277 | |
| 278 | /* badboy "entry" point */ |
| 279 | |
| 280 | /* |
| 281 | * Unlike crashme, faulty syscalls are not supposed to barf |
| 282 | */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 283 | void badboy_loop() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 284 | { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 285 | int i; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 286 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 287 | for (i = 0; i < ntries; ++i) { |
| 288 | /* level 5 */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 289 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 290 | if (!x_opt && verbose_level >= 5) { |
| 291 | printf("try %d\n", i); |
| 292 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 293 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 294 | if (setjmp(again_buff) == 3) { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 295 | if (verbose_level >= 5) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 296 | printf("Barfed\n"); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 297 | } else { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 298 | set_up_signals(); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 299 | alarm(MAX_TRY_TIME); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 300 | try_one_crash(i); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 301 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 302 | } |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 303 | summarize_errno(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 304 | } |
| 305 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 306 | void again_handler(int sig) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 307 | { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 308 | char *ss; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 309 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 310 | switch (sig) { |
| 311 | case SIGILL: |
| 312 | ss = " illegal instruction"; |
| 313 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 314 | #ifdef SIGTRAP |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 315 | case SIGTRAP: |
| 316 | ss = " trace trap"; |
| 317 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 318 | #endif |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 319 | case SIGFPE: |
| 320 | ss = " arithmetic exception"; |
| 321 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 322 | #ifdef SIGBUS |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 323 | case SIGBUS: |
| 324 | ss = " bus error"; |
| 325 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 326 | #endif |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 327 | case SIGSEGV: |
| 328 | ss = " segmentation violation"; |
| 329 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 330 | #ifdef SIGIOT |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 331 | case SIGIOT: |
| 332 | ss = " IOT instruction"; |
| 333 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 334 | #endif |
| 335 | #ifdef SIGEMT |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 336 | case SIGEMT: |
| 337 | ss = " EMT instruction"; |
| 338 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 339 | #endif |
| 340 | #ifdef SIGALRM |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 341 | case SIGALRM: |
| 342 | ss = " alarm clock"; |
| 343 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 344 | #endif |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 345 | case SIGINT: |
| 346 | ss = " interrupt"; |
| 347 | break; |
| 348 | default: |
| 349 | ss = ""; |
| 350 | } |
| 351 | if (verbose_level >= 5) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 352 | printf("Got signal %d%s\n", sig, ss); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 353 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 354 | longjmp(again_buff, 3); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 355 | } |
| 356 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 357 | void my_signal(int sig, void (*func) ()) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 358 | { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 359 | struct sigaction act; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 360 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 361 | act.sa_handler = func; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 362 | memset(&act.sa_mask, 0x00, sizeof(sigset_t)); |
| 363 | act.sa_flags = SA_NOMASK | SA_RESTART; |
| 364 | sigaction(sig, &act, 0); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 365 | } |
| 366 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 367 | void set_up_signals() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 368 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 369 | my_signal(SIGILL, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 370 | #ifdef SIGTRAP |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 371 | my_signal(SIGTRAP, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 372 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 373 | my_signal(SIGFPE, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 374 | #ifdef SIGBUS |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 375 | my_signal(SIGBUS, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 376 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 377 | my_signal(SIGSEGV, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 378 | #ifdef SIGIOT |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 379 | my_signal(SIGIOT, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 380 | #endif |
| 381 | #ifdef SIGEMT |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 382 | my_signal(SIGEMT, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 383 | #endif |
| 384 | #ifdef SIGALRM |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 385 | my_signal(SIGALRM, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 386 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 387 | my_signal(SIGINT, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 388 | } |
| 389 | |
| 390 | /* |
| 391 | * NB: rand() (ie. RAND_MAX) might be on 31bits only! |
| 392 | * |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 393 | * FIXME: 64-bit systems |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 394 | * |
| 395 | * TODO: improve arg mixing (16bits and 8bits values, NULLs, etc.). |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 396 | * big values as returned by rand() are no so interresting |
| 397 | * (except when used as pointers) because they may fall too |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 398 | * quickly in the invalid parameter sieve. Smaller values, |
| 399 | * will be more insidious because they may refer to existing |
| 400 | * objects (pids, fd, etc.). |
| 401 | */ |
| 402 | long int rand_long() |
| 403 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 404 | int r1, r2; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 405 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 406 | r1 = rand(); |
| 407 | r2 = rand(); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 408 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 409 | if (r1 & 0x10000L) |
| 410 | r1 = 0; |
| 411 | if (!r1 && (r2 & 0x50000L)) |
| 412 | r2 = 0; |
| 413 | else if (!r1 && (r2 & 0x20000L)) |
| 414 | r2 &= 0x00ffL; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 415 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 416 | return (long int)((r1 & 0xffffL) << 16) | (r2 & 0xffffL); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 417 | } |
| 418 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 419 | void try_one_crash(int try_num) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 420 | { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 421 | long int sysno, arg1, arg2, arg3, arg4, arg5, arg6, arg7; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 422 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 423 | do { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 424 | sysno = rand() % sysno_max; |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 425 | } while (in_blacklist(sysno)); |
subrata_modak | 1b77909 | 2009-05-25 15:27:10 +0000 | [diff] [blame] | 426 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 427 | arg1 = rand_long(); |
| 428 | arg2 = rand_long(); |
| 429 | arg3 = rand_long(); |
| 430 | arg4 = rand_long(); |
| 431 | arg5 = rand_long(); |
| 432 | arg6 = rand_long(); |
| 433 | arg7 = rand_long(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 434 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 435 | if (x_opt) { |
| 436 | if (verbose_level >= 1) |
| 437 | printf("%04d: syscall(%ld, %#lx, %#lx, %#lx, %#lx, " |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 438 | "%#lx, %#lx, %#lx)\n", |
| 439 | try_num, sysno, arg1, arg2, arg3, arg4, arg5, |
| 440 | arg6, arg7); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 441 | } else { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 442 | syscall(sysno, arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 443 | record_errno(errno); |
| 444 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 445 | } |
| 446 | |
subrata_modak | 1b77909 | 2009-05-25 15:27:10 +0000 | [diff] [blame] | 447 | /* The following syscalls create new processes which may cause the test |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 448 | unable to finish. */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 449 | int in_blacklist(int sysno) |
subrata_modak | 1b77909 | 2009-05-25 15:27:10 +0000 | [diff] [blame] | 450 | { |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 451 | int i; |
| 452 | const int list[] = { |
yaberauneya | ef77253 | 2009-10-09 17:55:43 +0000 | [diff] [blame] | 453 | #if defined(__ia64__) |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 454 | SYS_clone2, |
subrata_modak | 1b77909 | 2009-05-25 15:27:10 +0000 | [diff] [blame] | 455 | #else |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 456 | /* |
| 457 | * No SYS_fork(vfork) on IA-64. Instead, it uses, |
| 458 | * clone(child_stack=0, flags=CLONE_VM|CLONE_VFORK|SIGCHLD) |
| 459 | * clone2() |
| 460 | */ |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 461 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 462 | /* |
| 463 | * NOTE (garrcoop): |
| 464 | * Could not find reference to SYS_fork(vfork) on mips32 |
| 465 | * with the Montavista / Octeon toolchain. Need to develop an |
| 466 | * autoconf check for this item. |
| 467 | */ |
yaberauneya | ef77253 | 2009-10-09 17:55:43 +0000 | [diff] [blame] | 468 | #if defined(__NR_vfork) && __NR_vfork |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 469 | SYS_vfork, |
| 470 | #elif defined(__NR_fork) && __NR_fork |
| 471 | SYS_fork, |
yaberauneya | ef77253 | 2009-10-09 17:55:43 +0000 | [diff] [blame] | 472 | #endif |
subrata_modak | 1b77909 | 2009-05-25 15:27:10 +0000 | [diff] [blame] | 473 | #endif /* __ia64__ */ |
yaberauneya | ef77253 | 2009-10-09 17:55:43 +0000 | [diff] [blame] | 474 | #if defined(__NR_clone) && __NR_clone |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 475 | SYS_clone, |
yaberauneya | ef77253 | 2009-10-09 17:55:43 +0000 | [diff] [blame] | 476 | #endif |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 477 | -1 |
| 478 | }; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 479 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 480 | for (i = 0; list[i] != -1; i++) { |
| 481 | if (sysno == list[i]) |
| 482 | return 1; |
| 483 | } |
subrata_modak | 1b77909 | 2009-05-25 15:27:10 +0000 | [diff] [blame] | 484 | |
Garrett Cooper | 1ffecc9 | 2010-12-18 00:03:44 -0800 | [diff] [blame] | 485 | return 0; |
Chris Dearman | ec6edca | 2012-10-17 19:54:01 -0700 | [diff] [blame] | 486 | } |