diff options
Diffstat (limited to 'contrib/unbound/testcode/testbound.c')
| -rw-r--r-- | contrib/unbound/testcode/testbound.c | 150 | 
1 files changed, 135 insertions, 15 deletions
| diff --git a/contrib/unbound/testcode/testbound.c b/contrib/unbound/testcode/testbound.c index 6da4ceaf2ebf..063037df4e80 100644 --- a/contrib/unbound/testcode/testbound.c +++ b/contrib/unbound/testcode/testbound.c @@ -293,6 +293,16 @@ setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])  			fclose(cfg);  			return;  		} +		if(strncmp(parse, "fake-sha1: yes", 14) == 0) { +			/* Allow the use of SHA1 signatures for the test, +			 * in case that OpenSSL disallows use of RSASHA1 +			 * with rh-allow-sha1-signatures disabled. */ +#ifndef UB_ON_WINDOWS +			setenv("OPENSSL_ENABLE_SHA1_SIGNATURES", "1", 0); +#else +			_putenv("OPENSSL_ENABLE_SHA1_SIGNATURES=1"); +#endif +		}  		fputs(line, cfg);  	}  	fatal_exit("No CONFIG_END in input file"); @@ -333,6 +343,35 @@ static void remove_configfile(void)  	cfgfiles = NULL;  } +/** perform the playback on the playback_file with the args. */ +static int +perform_playback(char* playback_file, int pass_argc, char** pass_argv) +{ +	struct replay_scenario* scen = NULL; +	int c, res; + +	/* setup test environment */ +	scen = setup_playback(playback_file, &pass_argc, pass_argv); +	/* init fake event backend */ +	fake_event_init(scen); + +	pass_argv[pass_argc] = NULL; +	echo_cmdline(pass_argc, pass_argv); + +	/* run the normal daemon */ +	res = daemon_main(pass_argc, pass_argv); + +	fake_event_cleanup(); +	for(c=1; c<pass_argc; c++) +		free(pass_argv[c]); +	return res; +} + +/* For fuzzing the main routine is replaced with + * LLVMFuzzerTestOneInput. */ +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#define main dummy_main +#endif  /**   * Main fake event test program. Setup, teardown and report errors.   * @param argc: arg count. @@ -348,7 +387,6 @@ main(int argc, char* argv[])  	char* playback_file = NULL;  	int init_optind = optind;  	char* init_optarg = optarg; -	struct replay_scenario* scen = NULL;  	/* we do not want the test to depend on the timezone */  	(void)putenv("TZ=UTC"); @@ -456,24 +494,11 @@ main(int argc, char* argv[])  	if(atexit(&remove_configfile) != 0)  		fatal_exit("atexit() failed: %s", strerror(errno)); -	/* setup test environment */ -	scen = setup_playback(playback_file, &pass_argc, pass_argv); -	/* init fake event backend */ -	fake_event_init(scen); - -	pass_argv[pass_argc] = NULL; -	echo_cmdline(pass_argc, pass_argv); -  	/* reset getopt processing */  	optind = init_optind;  	optarg = init_optarg; -	/* run the normal daemon */ -	res = daemon_main(pass_argc, pass_argv); - -	fake_event_cleanup(); -	for(c=1; c<pass_argc; c++) -		free(pass_argv[c]); +	res = perform_playback(playback_file, pass_argc, pass_argv);  	if(res == 0) {  		log_info("Testbound Exit Success\n");  		/* remove configfile from here, the atexit() is for when @@ -493,6 +518,101 @@ main(int argc, char* argv[])  	return res;  } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +static int delete_file(const char *pathname) { +  int ret = unlink(pathname); +  free((void *)pathname); +  return ret; +} + +static char *buf_to_file(const uint8_t *buf, size_t size) { +  int fd; +  size_t pos; +  char *pathname = strdup("/tmp/fuzz-XXXXXX"); +  if (pathname == NULL) +    return NULL; + +  fd = mkstemp(pathname); +  if (fd == -1) { +    log_err("mkstemp of file %s failed: %s", pathname, strerror(errno)); +    free(pathname); +    return NULL; +  } +  pos = 0; +  while (pos < size) { +    int nbytes = write(fd, &buf[pos], size - pos); +    if (nbytes <= 0) { +      if (nbytes == -1 && errno == EINTR) +             continue; +      log_err("write to file %s failed: %s", pathname, strerror(errno)); +      goto err; +    } +    pos += nbytes; +  } + +  if (close(fd) == -1) { +    log_err("close of file %s failed: %s", pathname, strerror(errno)); +    goto err; +  } + +  return pathname; +err: +  delete_file(pathname); +  return NULL; +} + +/* based on main() above, but with: hard-coded passed args, file created from fuzz input */ +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +       int c, res; +       int pass_argc = 0; +       char* pass_argv[MAXARG]; +       char* playback_file = NULL; + +       /* we do not want the test to depend on the timezone */ +       (void)putenv("TZ=UTC"); +       memset(pass_argv, 0, sizeof(pass_argv)); +#ifdef HAVE_SYSTEMD +       /* we do not want the test to use systemd daemon startup notification*/ +       (void)unsetenv("NOTIFY_SOCKET"); +#endif /* HAVE_SYSTEMD */ + +       checklock_start(); +       log_init(NULL, 0, NULL); +       /* determine commandline options for the daemon */ +       pass_argc = 1; +       pass_argv[0] = "unbound"; +       add_opts("-d", &pass_argc, pass_argv); + +       playback_file = buf_to_file(Data, Size); +       if (playback_file) { +               log_info("Start of %s testbound program.", PACKAGE_STRING); + +               res = perform_playback(playback_file, pass_argc, pass_argv); +               if(res == 0) { +                       log_info("Testbound Exit Success\n"); +                       /* remove configfile from here, the atexit() is for when +                        * there is a crash to remove the tmpdir file. +                        * This one removes the file while alloc and log locks are +                        * still valid, and can be logged (for memory calculation), +                        * it leaves the ptr NULL so the atexit does nothing. */ +                       remove_configfile(); +#ifdef HAVE_PTHREAD +                       /* dlopen frees its thread state (dlopen of gost engine) */ +                       pthread_exit(NULL); +#endif +               } + +               delete_file(playback_file); +       } + +       if(log_get_lock()) { +               lock_basic_destroy((lock_basic_type*)log_get_lock()); +       } +       return res; +} +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ +  /* fake remote control */  struct listen_port* daemon_remote_open_ports(struct config_file*   	ATTR_UNUSED(cfg)) | 
