github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/common.h (about)

     1  // Copyright 2016 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  // This file is shared between executor and csource package.
     5  // csource does a bunch of transformations with this file:
     6  // - unused parts are stripped using #if SYZ* defines
     7  // - includes are hoisted to the top and deduplicated
     8  // - comments and empty lines are stripped
     9  // - NORETURN/PRINTF/debug are removed
    10  // - exitf/fail are replaced with exit
    11  // - uintN types are replaced with uintN_t
    12  // - /*{{{FOO}}}*/ placeholders are replaced by actual values
    13  
    14  #ifndef _GNU_SOURCE
    15  #define _GNU_SOURCE
    16  #endif
    17  
    18  #if GOOS_freebsd || GOOS_test && HOSTGOOS_freebsd
    19  #include <sys/endian.h> // for htobe*.
    20  #elif GOOS_darwin
    21  #include <libkern/OSByteOrder.h>
    22  #define htobe16(x) OSSwapHostToBigInt16(x)
    23  #define htobe32(x) OSSwapHostToBigInt32(x)
    24  #define htobe64(x) OSSwapHostToBigInt64(x)
    25  #define le16toh(x) OSSwapLittleToHostInt16(x)
    26  #define htole16(x) OSSwapHostToLittleInt16(x)
    27  #elif GOOS_windows
    28  #define htobe16 _byteswap_ushort
    29  #define htobe32 _byteswap_ulong
    30  #define htobe64 _byteswap_uint64
    31  #define le16toh(x) x
    32  #define htole16(x) x
    33  typedef signed int ssize_t;
    34  #else
    35  #include <endian.h> // for htobe*.
    36  #endif
    37  #include <stdint.h>
    38  #include <stdio.h> // for fmt arguments
    39  #include <stdlib.h>
    40  #include <string.h>
    41  
    42  #if SYZ_TRACE
    43  #include <errno.h>
    44  #endif
    45  
    46  #if !SYZ_EXECUTOR
    47  /*{{{SYSCALL_DEFINES}}}*/
    48  #endif
    49  
    50  #if SYZ_EXECUTOR && !GOOS_linux
    51  #if !GOOS_windows
    52  #include <unistd.h>
    53  #endif
    54  NORETURN void doexit(int status)
    55  {
    56  	_exit(status);
    57  	for (;;) {
    58  	}
    59  }
    60  #if !GOOS_fuchsia
    61  NORETURN void doexit_thread(int status)
    62  {
    63  	// For BSD systems, _exit seems to do exactly what's needed.
    64  	doexit(status);
    65  }
    66  #endif
    67  #endif
    68  
    69  #if SYZ_EXECUTOR || SYZ_MULTI_PROC || SYZ_REPEAT && SYZ_CGROUPS ||                      \
    70      SYZ_NET_DEVICES || __NR_syz_mount_image || __NR_syz_read_part_table ||              \
    71      __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usbip_server_init || \
    72      (GOOS_freebsd || GOOS_darwin || GOOS_openbsd || GOOS_netbsd) && SYZ_NET_INJECTION
    73  static unsigned long long procid;
    74  #endif
    75  
    76  #if !GOOS_fuchsia && !GOOS_windows
    77  #if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
    78  #include <setjmp.h>
    79  #include <signal.h>
    80  #include <string.h>
    81  
    82  #if GOOS_linux
    83  #include <sys/syscall.h>
    84  #endif
    85  
    86  static __thread int clone_ongoing;
    87  static __thread int skip_segv;
    88  static __thread jmp_buf segv_env;
    89  
    90  static void segv_handler(int sig, siginfo_t* info, void* ctx)
    91  {
    92  	// Generated programs can contain bad (unmapped/protected) addresses,
    93  	// which cause SIGSEGVs during copyin/copyout.
    94  	// This handler ignores such crashes to allow the program to proceed.
    95  	// We additionally opportunistically check that the faulty address
    96  	// is not within executable data region, because such accesses can corrupt
    97  	// output region and then fuzzer will fail on corrupted data.
    98  
    99  	if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
   100  		// During clone, we always exit on a SEGV. If we do not, then
   101  		// it might prevent us from running child-specific code. E.g.
   102  		// if an invalid stack is passed to the clone() call, then it
   103  		// will trigger a seg fault, which in turn causes the child to
   104  		// jump over the NONFAILING macro and continue execution in
   105  		// parallel with the parent.
   106  		doexit_thread(sig);
   107  	}
   108  
   109  	uintptr_t addr = (uintptr_t)info->si_addr;
   110  	const uintptr_t prog_start = 1 << 20;
   111  	const uintptr_t prog_end = 100 << 20;
   112  	int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
   113  	int valid = addr < prog_start || addr > prog_end;
   114  #if GOOS_freebsd || (GOOS_test && HOSTGOOS_freebsd)
   115  	// FreeBSD delivers SIGBUS in response to any fault that isn't a page
   116  	// fault.  In this case it tries to be helpful and sets si_addr to the
   117  	// address of the faulting instruction rather than zero as other
   118  	// operating systems seem to do.  However, such faults should always be
   119  	// ignored.
   120  	if (sig == SIGBUS)
   121  		valid = 1;
   122  #endif
   123  	if (skip && valid) {
   124  		debug("SIGSEGV on %p, skipping\n", (void*)addr);
   125  		_longjmp(segv_env, 1);
   126  	}
   127  	debug("SIGSEGV on %p, exiting\n", (void*)addr);
   128  	doexit(sig);
   129  }
   130  
   131  static void install_segv_handler(void)
   132  {
   133  	struct sigaction sa;
   134  #if GOOS_linux
   135  	// Don't need that SIGCANCEL/SIGSETXID glibc stuff.
   136  	// SIGCANCEL sent to main thread causes it to exit
   137  	// without bringing down the whole group.
   138  	memset(&sa, 0, sizeof(sa));
   139  	sa.sa_handler = SIG_IGN;
   140  	syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8);
   141  	syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8);
   142  #endif
   143  	memset(&sa, 0, sizeof(sa));
   144  	sa.sa_sigaction = segv_handler;
   145  	sa.sa_flags = SA_NODEFER | SA_SIGINFO;
   146  	sigaction(SIGSEGV, &sa, NULL);
   147  	sigaction(SIGBUS, &sa, NULL);
   148  }
   149  
   150  #define NONFAILING(...)                                              \
   151  	({                                                           \
   152  		int ok = 1;                                          \
   153  		__atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \
   154  		if (_setjmp(segv_env) == 0) {                        \
   155  			__VA_ARGS__;                                 \
   156  		} else                                               \
   157  			ok = 0;                                      \
   158  		__atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
   159  		ok;                                                  \
   160  	})
   161  #endif
   162  #endif
   163  
   164  #if !GOOS_linux
   165  #if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
   166  #include <signal.h>
   167  #include <sys/types.h>
   168  #include <sys/wait.h>
   169  
   170  static void kill_and_wait(int pid, int* status)
   171  {
   172  	kill(pid, SIGKILL);
   173  	while (waitpid(-1, status, 0) != pid) {
   174  	}
   175  }
   176  #endif
   177  #endif
   178  
   179  #if !GOOS_windows
   180  #if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER || \
   181      __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_sleep_ms ||     \
   182      __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write ||    \
   183      __NR_syz_usb_disconnect
   184  static void sleep_ms(uint64 ms)
   185  {
   186  	usleep(ms * 1000);
   187  }
   188  #endif
   189  
   190  #if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER || \
   191      SYZ_LEAK
   192  #include <time.h>
   193  
   194  static uint64 current_time_ms(void)
   195  {
   196  	struct timespec ts;
   197  	if (clock_gettime(CLOCK_MONOTONIC, &ts))
   198  		fail("clock_gettime failed");
   199  	return (uint64)ts.tv_sec * 1000 + (uint64)ts.tv_nsec / 1000000;
   200  }
   201  #endif
   202  
   203  #if SYZ_EXECUTOR || SYZ_SANDBOX_ANDROID || SYZ_USE_TMP_DIR
   204  #include <stdlib.h>
   205  #include <sys/stat.h>
   206  #include <unistd.h>
   207  
   208  static void use_temporary_dir(void)
   209  {
   210  #if SYZ_SANDBOX_ANDROID
   211  	char tmpdir_template[] = "/data/local/tmp/syzkaller.XXXXXX";
   212  #elif GOOS_fuchsia
   213  	char tmpdir_template[] = "/tmp/syzkaller.XXXXXX";
   214  #else
   215  	char tmpdir_template[] = "./syzkaller.XXXXXX";
   216  #endif
   217  	char* tmpdir = mkdtemp(tmpdir_template);
   218  	if (!tmpdir)
   219  		fail("failed to mkdtemp");
   220  	if (chmod(tmpdir, 0777))
   221  		fail("failed to chmod");
   222  	if (chdir(tmpdir))
   223  		fail("failed to chdir");
   224  }
   225  #endif
   226  #endif
   227  
   228  #if GOOS_netbsd || GOOS_freebsd || GOOS_darwin || GOOS_openbsd || GOOS_test
   229  #if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER && (SYZ_EXECUTOR || SYZ_USE_TMP_DIR)
   230  #include <dirent.h>
   231  #include <errno.h>
   232  #include <stdio.h>
   233  #include <string.h>
   234  #include <sys/stat.h>
   235  #include <sys/types.h>
   236  
   237  #if GOOS_freebsd
   238  // Unset file flags which might inhibit unlinking.
   239  static void reset_flags(const char* filename)
   240  {
   241  	struct stat st;
   242  	if (lstat(filename, &st))
   243  		exitf("lstat(%s) failed", filename);
   244  	st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE | SF_APPEND | UF_APPEND);
   245  	if (lchflags(filename, st.st_flags))
   246  		exitf("lchflags(%s) failed", filename);
   247  }
   248  #endif
   249  
   250  // We need to prevent the compiler from unrolling the while loop by using the gcc's noinline attribute
   251  // because otherwise it could trigger the compiler warning about a potential format truncation
   252  // when a filename is constructed with help of snprintf. This warning occurs because by unrolling
   253  // the while loop, the snprintf call will try to concatenate 2 buffers of length FILENAME_MAX and put
   254  // the result into a buffer of length FILENAME_MAX which is apparently not possible. But this is no
   255  // problem in our case because file and directory names should be short enough and fit into a buffer
   256  // of length FILENAME_MAX.
   257  static void __attribute__((noinline)) remove_dir(const char* dir)
   258  {
   259  	DIR* dp = opendir(dir);
   260  	if (dp == NULL) {
   261  		if (errno == EACCES) {
   262  			// We could end up here in a recursive call to remove_dir() below.
   263  			// One of executed syscall could end up creating a directory rooted
   264  			// in the current working directory created by loop() with zero
   265  			// permissions. Try to perform a best effort removal of the
   266  			// directory.
   267  			if (rmdir(dir))
   268  				exitf("rmdir(%s) failed", dir);
   269  			return;
   270  		}
   271  		exitf("opendir(%s) failed", dir);
   272  	}
   273  	struct dirent* ep = 0;
   274  	while ((ep = readdir(dp))) {
   275  		if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
   276  			continue;
   277  		char filename[FILENAME_MAX];
   278  		snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
   279  		struct stat st;
   280  		if (lstat(filename, &st))
   281  			exitf("lstat(%s) failed", filename);
   282  		if (S_ISDIR(st.st_mode)) {
   283  			remove_dir(filename);
   284  			continue;
   285  		}
   286  		if (unlink(filename)) {
   287  #if GOOS_freebsd
   288  			if (errno == EPERM) {
   289  				reset_flags(filename);
   290  				reset_flags(dir);
   291  				if (unlink(filename) == 0)
   292  					continue;
   293  			}
   294  #endif
   295  			exitf("unlink(%s) failed", filename);
   296  		}
   297  	}
   298  	closedir(dp);
   299  	while (rmdir(dir)) {
   300  #if GOOS_freebsd
   301  		if (errno == EPERM) {
   302  			reset_flags(dir);
   303  			if (rmdir(dir) == 0)
   304  				break;
   305  		}
   306  #endif
   307  		exitf("rmdir(%s) failed", dir);
   308  	}
   309  }
   310  #endif
   311  #endif
   312  
   313  #if !GOOS_linux && !GOOS_netbsd
   314  #if SYZ_EXECUTOR || SYZ_FAULT
   315  static int inject_fault(int nth)
   316  {
   317  	return 0;
   318  }
   319  #endif
   320  
   321  #if SYZ_FAULT
   322  static void setup_fault()
   323  {
   324  }
   325  #endif
   326  
   327  #if SYZ_EXECUTOR
   328  static int fault_injected(int fail_fd)
   329  {
   330  	return 0;
   331  }
   332  #endif
   333  #endif
   334  
   335  #if !GOOS_windows
   336  #if SYZ_EXECUTOR || SYZ_THREADED
   337  #include <errno.h>
   338  #include <pthread.h>
   339  
   340  static void thread_start(void* (*fn)(void*), void* arg)
   341  {
   342  	pthread_t th;
   343  	pthread_attr_t attr;
   344  	pthread_attr_init(&attr);
   345  	pthread_attr_setstacksize(&attr, 128 << 10);
   346  	// Clone can fail spuriously with EAGAIN if there is a concurrent execve in progress.
   347  	// (see linux kernel commit 498052bba55ec). But it can also be a true limit imposed by cgroups.
   348  	// In one case we want to retry infinitely, in another -- fail immidiately...
   349  	int i = 0;
   350  	for (; i < 100; i++) {
   351  		if (pthread_create(&th, &attr, fn, arg) == 0) {
   352  			pthread_attr_destroy(&attr);
   353  			return;
   354  		}
   355  		if (errno == EAGAIN) {
   356  			usleep(50);
   357  			continue;
   358  		}
   359  		break;
   360  	}
   361  	exitf("pthread_create failed");
   362  }
   363  
   364  #endif
   365  #endif
   366  
   367  #if GOOS_freebsd || GOOS_darwin || GOOS_netbsd || GOOS_openbsd || GOOS_test
   368  #if SYZ_EXECUTOR || SYZ_THREADED
   369  
   370  #include <pthread.h>
   371  #include <time.h>
   372  
   373  typedef struct {
   374  	pthread_mutex_t mu;
   375  	pthread_cond_t cv;
   376  	int state;
   377  } event_t;
   378  
   379  static void event_init(event_t* ev)
   380  {
   381  	if (pthread_mutex_init(&ev->mu, 0))
   382  		exitf("pthread_mutex_init failed");
   383  	if (pthread_cond_init(&ev->cv, 0))
   384  		exitf("pthread_cond_init failed");
   385  	ev->state = 0;
   386  }
   387  
   388  static void event_reset(event_t* ev)
   389  {
   390  	ev->state = 0;
   391  }
   392  
   393  static void event_set(event_t* ev)
   394  {
   395  	pthread_mutex_lock(&ev->mu);
   396  	if (ev->state)
   397  		exitf("event already set");
   398  	ev->state = 1;
   399  	pthread_mutex_unlock(&ev->mu);
   400  	pthread_cond_broadcast(&ev->cv);
   401  }
   402  
   403  static void event_wait(event_t* ev)
   404  {
   405  	pthread_mutex_lock(&ev->mu);
   406  	while (!ev->state)
   407  		pthread_cond_wait(&ev->cv, &ev->mu);
   408  	pthread_mutex_unlock(&ev->mu);
   409  }
   410  
   411  static int event_isset(event_t* ev)
   412  {
   413  	pthread_mutex_lock(&ev->mu);
   414  	int res = ev->state;
   415  	pthread_mutex_unlock(&ev->mu);
   416  	return res;
   417  }
   418  
   419  static int event_timedwait(event_t* ev, uint64 timeout)
   420  {
   421  	uint64 start = current_time_ms();
   422  	uint64 now = start;
   423  	pthread_mutex_lock(&ev->mu);
   424  	for (;;) {
   425  		if (ev->state)
   426  			break;
   427  		uint64 remain = timeout - (now - start);
   428  		struct timespec ts;
   429  		ts.tv_sec = remain / 1000;
   430  		ts.tv_nsec = (remain % 1000) * 1000 * 1000;
   431  		pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
   432  		now = current_time_ms();
   433  		if (now - start > timeout)
   434  			break;
   435  	}
   436  	int res = ev->state;
   437  	pthread_mutex_unlock(&ev->mu);
   438  	return res;
   439  }
   440  #endif
   441  #endif
   442  
   443  #if SYZ_EXECUTOR || SYZ_USE_BITMASKS
   444  #define BITMASK(bf_off, bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
   445  #define STORE_BY_BITMASK(type, htobe, addr, val, bf_off, bf_len)                        \
   446  	*(type*)(addr) = htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off), (bf_len))) | \
   447  			       (((type)(val) << (bf_off)) & BITMASK((bf_off), (bf_len))))
   448  #endif
   449  
   450  #if SYZ_EXECUTOR || SYZ_USE_CHECKSUMS
   451  struct csum_inet {
   452  	uint32 acc;
   453  };
   454  
   455  static void csum_inet_init(struct csum_inet* csum)
   456  {
   457  	csum->acc = 0;
   458  }
   459  
   460  static void csum_inet_update(struct csum_inet* csum, const uint8* data, size_t length)
   461  {
   462  	if (length == 0)
   463  		return;
   464  
   465  	size_t i = 0;
   466  	for (; i < length - 1; i += 2)
   467  		csum->acc += *(uint16*)&data[i];
   468  
   469  	if (length & 1)
   470  		csum->acc += le16toh((uint16)data[length - 1]);
   471  
   472  	while (csum->acc > 0xffff)
   473  		csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16);
   474  }
   475  
   476  static uint16 csum_inet_digest(struct csum_inet* csum)
   477  {
   478  	return ~csum->acc;
   479  }
   480  #endif
   481  
   482  #if GOOS_freebsd || GOOS_darwin || GOOS_netbsd
   483  #include "common_bsd.h"
   484  #elif GOOS_openbsd
   485  #include "common_openbsd.h"
   486  #elif GOOS_fuchsia
   487  #include "common_fuchsia.h"
   488  #elif GOOS_linux
   489  #include "common_linux.h"
   490  #elif GOOS_test
   491  #include "common_test.h"
   492  #elif GOOS_windows
   493  #include "common_windows.h"
   494  #else
   495  #error "unknown OS"
   496  #endif
   497  
   498  #if SYZ_TEST_COMMON_EXT_EXAMPLE
   499  #include "common_ext_example.h"
   500  #else
   501  #include "common_ext.h"
   502  #endif
   503  
   504  #if SYZ_EXECUTOR || __NR_syz_execute_func
   505  // syz_execute_func(text ptr[in, text[taget]])
   506  static long syz_execute_func(volatile long text)
   507  {
   508  	// Here we just to random code which is inherently unsafe.
   509  	// But we only care about coverage in the output region.
   510  	// The following code tries to remove left-over pointers in registers
   511  	// from the reach of the random code, otherwise it's known to reach
   512  	// the output region somehow. The asm block is arch-independent except
   513  	// for the number of available registers.
   514  #if defined(__GNUC__)
   515  	volatile long p[8] = {0};
   516  	(void)p;
   517  #if GOARCH_amd64
   518  	asm volatile("" ::"r"(0l), "r"(1l), "r"(2l), "r"(3l), "r"(4l), "r"(5l), "r"(6l),
   519  		     "r"(7l), "r"(8l), "r"(9l), "r"(10l), "r"(11l), "r"(12l), "r"(13l));
   520  #endif
   521  #endif
   522  	((void (*)(void))(text))();
   523  	return 0;
   524  }
   525  #endif
   526  
   527  #if SYZ_THREADED
   528  struct thread_t {
   529  	int created, call;
   530  	event_t ready, done;
   531  };
   532  
   533  static struct thread_t threads[16];
   534  static void execute_call(int call);
   535  static int running;
   536  
   537  static void* thr(void* arg)
   538  {
   539  	struct thread_t* th = (struct thread_t*)arg;
   540  	for (;;) {
   541  		event_wait(&th->ready);
   542  		event_reset(&th->ready);
   543  		execute_call(th->call);
   544  		__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
   545  		event_set(&th->done);
   546  	}
   547  	return 0;
   548  }
   549  
   550  #if SYZ_REPEAT
   551  static void execute_one(void)
   552  #else
   553  static void loop(void)
   554  #endif
   555  {
   556  	if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
   557  	}
   558  #if SYZ_TRACE
   559  	fprintf(stderr, "### start\n");
   560  #endif
   561  	int i, call, thread;
   562  	for (call = 0; call < /*{{{NUM_CALLS}}}*/; call++) {
   563  		for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) {
   564  			struct thread_t* th = &threads[thread];
   565  			if (!th->created) {
   566  				th->created = 1;
   567  				event_init(&th->ready);
   568  				event_init(&th->done);
   569  				event_set(&th->done);
   570  				thread_start(thr, th);
   571  			}
   572  			if (!event_isset(&th->done))
   573  				continue;
   574  			event_reset(&th->done);
   575  			th->call = call;
   576  			__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
   577  			event_set(&th->ready);
   578  #if SYZ_ASYNC
   579  			if (/*{{{ASYNC_CONDITIONS}}}*/)
   580  				break;
   581  #endif
   582  			event_timedwait(&th->done, /*{{{CALL_TIMEOUT_MS}}}*/);
   583  			break;
   584  		}
   585  	}
   586  	for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
   587  		sleep_ms(1);
   588  #if SYZ_HAVE_CLOSE_FDS
   589  	close_fds();
   590  #endif
   591  }
   592  #endif
   593  
   594  #if SYZ_EXECUTOR || SYZ_REPEAT
   595  static void execute_one(void);
   596  #if SYZ_EXECUTOR_USES_FORK_SERVER
   597  #include <signal.h>
   598  #include <sys/types.h>
   599  #include <sys/wait.h>
   600  
   601  #if GOOS_linux
   602  #define WAIT_FLAGS __WALL
   603  #else
   604  #define WAIT_FLAGS 0
   605  #endif
   606  
   607  #if SYZ_EXECUTOR
   608  static void reply_handshake();
   609  #endif
   610  
   611  static void loop(void)
   612  {
   613  #if SYZ_HAVE_SETUP_LOOP
   614  	setup_loop();
   615  #endif
   616  #if SYZ_EXECUTOR
   617  	// Tell parent that we are ready to serve.
   618  	reply_handshake();
   619  #endif
   620  	int iter = 0;
   621  #if SYZ_REPEAT_TIMES
   622  	for (; iter < /*{{{REPEAT_TIMES}}}*/; iter++) {
   623  #else
   624  	for (;; iter++) {
   625  #endif
   626  #if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
   627  		// Create a new private work dir for this test (removed at the end of the loop).
   628  		char cwdbuf[32];
   629  		sprintf(cwdbuf, "./%d", iter);
   630  		if (mkdir(cwdbuf, 0777))
   631  			fail("failed to mkdir");
   632  #endif
   633  #if SYZ_HAVE_RESET_LOOP
   634  		reset_loop();
   635  #endif
   636  #if SYZ_EXECUTOR
   637  		receive_execute();
   638  #endif
   639  		int pid = fork();
   640  		if (pid < 0)
   641  			fail("clone failed");
   642  		if (pid == 0) {
   643  #if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
   644  			if (chdir(cwdbuf))
   645  				fail("failed to chdir");
   646  #endif
   647  #if SYZ_HAVE_SETUP_TEST
   648  			setup_test();
   649  #endif
   650  #if SYZ_HAVE_SETUP_EXT_TEST
   651  			setup_ext_test();
   652  #endif
   653  #if SYZ_EXECUTOR
   654  			close(kInPipeFd);
   655  #endif
   656  #if SYZ_EXECUTOR && SYZ_EXECUTOR_USES_SHMEM
   657  			close(kOutPipeFd);
   658  #endif
   659  			execute_one();
   660  #if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED
   661  			close_fds();
   662  #endif
   663  			doexit(0);
   664  		}
   665  		debug("spawned worker pid %d\n", pid);
   666  
   667  		// We used to use sigtimedwait(SIGCHLD) to wait for the subprocess.
   668  		// But SIGCHLD is also delivered when a process stops/continues,
   669  		// so it would require a loop with status analysis and timeout recalculation.
   670  		// SIGCHLD should also unblock the usleep below, so the spin loop
   671  		// should be as efficient as sigtimedwait.
   672  		int status = 0;
   673  		uint64 start = current_time_ms();
   674  #if SYZ_EXECUTOR && SYZ_EXECUTOR_USES_SHMEM
   675  		uint64 last_executed = start;
   676  		uint32 executed_calls = __atomic_load_n(output_data, __ATOMIC_RELAXED);
   677  #endif
   678  		for (;;) {
   679  			if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
   680  				break;
   681  			sleep_ms(1);
   682  #if SYZ_EXECUTOR
   683  #if SYZ_EXECUTOR_USES_SHMEM
   684  			// Even though the test process executes exit at the end
   685  			// and execution time of each syscall is bounded by syscall_timeout_ms (~50ms),
   686  			// this backup watchdog is necessary and its performance is important.
   687  			// The problem is that exit in the test processes can fail (sic).
   688  			// One observed scenario is that the test processes prohibits
   689  			// exit_group syscall using seccomp. Another observed scenario
   690  			// is that the test processes setups a userfaultfd for itself,
   691  			// then the main thread hangs when it wants to page in a page.
   692  			// Below we check if the test process still executes syscalls
   693  			// and kill it after ~1s of inactivity.
   694  			uint64 min_timeout_ms = program_timeout_ms * 3 / 5;
   695  			uint64 inactive_timeout_ms = syscall_timeout_ms * 20;
   696  			uint64 now = current_time_ms();
   697  			uint32 now_executed = __atomic_load_n(output_data, __ATOMIC_RELAXED);
   698  			if (executed_calls != now_executed) {
   699  				executed_calls = now_executed;
   700  				last_executed = now;
   701  			}
   702  			// TODO: adjust timeout for progs with syz_usb_connect call.
   703  			if ((now - start < program_timeout_ms) &&
   704  			    (now - start < min_timeout_ms || now - last_executed < inactive_timeout_ms))
   705  				continue;
   706  #else
   707  			if (current_time_ms() - start < program_timeout_ms)
   708  				continue;
   709  #endif
   710  #else
   711  			if (current_time_ms() - start < /*{{{PROGRAM_TIMEOUT_MS}}}*/)
   712  				continue;
   713  #endif
   714  			debug("killing hanging pid %d\n", pid);
   715  			kill_and_wait(pid, &status);
   716  			break;
   717  		}
   718  #if SYZ_EXECUTOR
   719  		if (WEXITSTATUS(status) == kFailStatus) {
   720  			errno = 0;
   721  			fail("child failed");
   722  		}
   723  		reply_execute(0);
   724  #endif
   725  #if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
   726  		remove_dir(cwdbuf);
   727  #endif
   728  #if SYZ_LEAK
   729  		// Note: this will fail under setuid sandbox because we don't have
   730  		// write permissions for the kmemleak file.
   731  		check_leaks();
   732  #endif
   733  	}
   734  }
   735  #else
   736  static void loop(void)
   737  {
   738  	execute_one();
   739  }
   740  #endif
   741  #endif
   742  
   743  #if !SYZ_EXECUTOR
   744  
   745  /*{{{RESULTS}}}*/
   746  
   747  #if SYZ_THREADED || SYZ_REPEAT || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID
   748  #if SYZ_THREADED
   749  void execute_call(int call)
   750  #elif SYZ_REPEAT
   751  void execute_one(void)
   752  #else
   753  void loop(void)
   754  #endif
   755  {
   756  	/*{{{SYSCALLS}}}*/
   757  #if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT
   758  	close_fds();
   759  #endif
   760  }
   761  #endif
   762  
   763  // This is the main function for csource.
   764  int main(void)
   765  {
   766  	/*{{{MMAP_DATA}}}*/
   767  
   768  #if SYZ_SYSCTL
   769  	setup_sysctl();
   770  #endif
   771  #if SYZ_CGROUPS
   772  	setup_cgroups();
   773  #endif
   774  #if SYZ_BINFMT_MISC
   775  	setup_binfmt_misc();
   776  #endif
   777  #if SYZ_LEAK
   778  	setup_leak();
   779  #endif
   780  #if SYZ_FAULT
   781  	setup_fault();
   782  #endif
   783  #if SYZ_KCSAN
   784  	setup_kcsan();
   785  #endif
   786  #if SYZ_USB
   787  	setup_usb();
   788  #endif
   789  #if SYZ_802154
   790  	setup_802154();
   791  #endif
   792  #if SYZ_SWAP
   793  	setup_swap();
   794  #endif
   795  #if SYZ_HANDLE_SEGV
   796  	install_segv_handler();
   797  #endif
   798  #if SYZ_HAVE_SETUP_EXT
   799  	setup_ext();
   800  #endif
   801  #if SYZ_MULTI_PROC
   802  	for (procid = 0; procid < /*{{{PROCS}}}*/; procid++) {
   803  		if (fork() == 0) {
   804  #endif
   805  #if SYZ_USE_TMP_DIR || SYZ_SANDBOX_ANDROID
   806  			use_temporary_dir();
   807  #endif
   808  			/*{{{SANDBOX_FUNC}}}*/
   809  #if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT && !SYZ_SANDBOX_NONE && \
   810      !SYZ_SANDBOX_SETUID && !SYZ_SANDBOX_NAMESPACE && !SYZ_SANDBOX_ANDROID
   811  			close_fds();
   812  #endif
   813  #if SYZ_MULTI_PROC
   814  		}
   815  	}
   816  	sleep(1000000);
   817  #endif
   818  #if !SYZ_MULTI_PROC && !SYZ_REPEAT && SYZ_LEAK
   819  	check_leaks();
   820  #endif
   821  	return 0;
   822  }
   823  #endif