Home | History | Annotate | Line # | Download | only in named
fuzz.c revision 1.2.2.3
      1 /*	$NetBSD: fuzz.c,v 1.2.2.3 2019/01/18 08:49:11 pgoyette Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 #include <config.h>
     15 
     16 #include <inttypes.h>
     17 #include <stdbool.h>
     18 
     19 #include <named/fuzz.h>
     20 
     21 #ifdef ENABLE_AFL
     22 #include <named/globals.h>
     23 #include <named/server.h>
     24 #include <sys/errno.h>
     25 
     26 #include <isc/app.h>
     27 #include <isc/condition.h>
     28 #include <isc/mutex.h>
     29 #include <isc/thread.h>
     30 #include <isc/util.h>
     31 #include <named/log.h>
     32 #include <dns/log.h>
     33 
     34 #include <stdlib.h>
     35 #include <string.h>
     36 #include <signal.h>
     37 #include <arpa/inet.h>
     38 #include <unistd.h>
     39 #include <pthread.h>
     40 
     41 /*
     42  * We are using pthreads directly because we might be using it with
     43  * unthreaded version of BIND, where all thread functions are
     44  * mocks. Since AFL for now only works on Linux it's not a problem.
     45  */
     46 static pthread_cond_t cond;
     47 static pthread_mutex_t mutex;
     48 static bool ready;
     49 
     50 /*
     51  * In "client:" mode, this thread reads fuzzed query messages from AFL
     52  * from standard input and sends it to named's listening port (DNS) that
     53  * is passed in the -A client:<address>:<port> option. It can be used to
     54  * test named from the client side.
     55  */
     56 static void *
     57 fuzz_thread_client(void *arg) {
     58 	char *host;
     59 	char *port;
     60 	struct sockaddr_in servaddr;
     61 	int sockfd;
     62 	void *buf;
     63 
     64 	UNUSED(arg);
     65 
     66 	/*
     67 	 * Parse named -A argument in the "address:port" syntax. Due to
     68 	 * the syntax used, this only supports IPv4 addresses.
     69 	 */
     70 	host = strdup(named_g_fuzz_addr);
     71 	RUNTIME_CHECK(host != NULL);
     72 
     73 	port = strchr(host, ':');
     74 	RUNTIME_CHECK(port != NULL);
     75 	*port = 0;
     76 	++port;
     77 
     78 	memset(&servaddr, 0, sizeof (servaddr));
     79 	servaddr.sin_family = AF_INET;
     80 	RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1);
     81 	servaddr.sin_port = htons(atoi(port));
     82 
     83 	free(host);
     84 
     85 	/*
     86 	 * Wait for named to start. This is set in run_server() in the
     87 	 * named thread.
     88 	 */
     89 	while (!named_g_run_done) {
     90 		usleep(10000);
     91 	}
     92 
     93 	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     94 	RUNTIME_CHECK(sockfd != -1);
     95 
     96 	buf = malloc(65536);
     97 	RUNTIME_CHECK(buf != NULL);
     98 
     99 	/*
    100 	 * Processing fuzzed packets 100,000 times before shutting down
    101 	 * the app.
    102 	 */
    103 #ifdef __AFL_LOOP
    104 	for (int loop = 0; loop < 100000; loop++) {
    105 #else
    106 	{
    107 #endif
    108 		ssize_t length;
    109 		ssize_t sent;
    110 
    111 		length = read(0, buf, 65536);
    112 		if (length <= 0) {
    113 			usleep(1000000);
    114 			goto next;
    115 		}
    116 
    117 		/*
    118 		 * Ignore packets that are larger than 4096 bytes.
    119 		 */
    120 		if (length > 4096) {
    121 			/*
    122 			 * AFL_CMIN doesn't support persistent mode, so
    123 			 * shutdown the server.
    124 			 */
    125 			if (getenv("AFL_CMIN")) {
    126 				free(buf);
    127 				close(sockfd);
    128 				named_server_flushonshutdown(named_g_server,
    129 							     false);
    130 				isc_app_shutdown();
    131 				return (NULL);
    132 			}
    133 			raise(SIGSTOP);
    134 			goto next;
    135 		}
    136 
    137 		RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    138 
    139 		ready = false;
    140 
    141 		sent = sendto(sockfd, buf, length, 0,
    142 			      (struct sockaddr *) &servaddr, sizeof(servaddr));
    143 		RUNTIME_CHECK(sent == length);
    144 
    145 		/*
    146 		 * Read the reply message from named to unclog it. Don't
    147 		 * bother if there isn't a reply.
    148 		 */
    149 		recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL);
    150 
    151 		while (!ready)
    152 			pthread_cond_wait(&cond, &mutex);
    153 
    154 		RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    155 	next: ;
    156 	}
    157 
    158 	free(buf);
    159 	close(sockfd);
    160 
    161 	named_server_flushonshutdown(named_g_server, false);
    162 	isc_app_shutdown();
    163 
    164 	return (NULL);
    165 }
    166 
    167 /*
    168  * In "resolver:" mode, this thread reads fuzzed reply messages from AFL
    169  * from standard input. It also sets up a listener as a remote
    170  * authoritative server and sends a driver query to the client side of
    171  * named(resolver).  When named(resolver) connects to this authoritative
    172  * server, this thread writes the fuzzed reply message from AFL to it.
    173  *
    174  * -A resolver:<saddress>:<sport>:<raddress>:<rport>
    175  *
    176  * Here, <saddress>:<sport> is where named(resolver) is listening on.
    177  * <raddress>:<rport> is where the thread is supposed to setup the
    178  * authoritative server. This address should be configured via the root
    179  * zone to be the authoritiative server for aaaaaaaaaa.example.
    180  *
    181  * named(resolver) when being fuzzed will not cache answers.
    182  */
    183 static void *
    184 fuzz_thread_resolver(void *arg) {
    185 	char *sqtype, *shost, *sport, *rhost, *rport;
    186 	struct sockaddr_in servaddr, recaddr, recvaddr;
    187 	/*
    188 	 * Query for aaaaaaaaaa.example./A in wire format with RD=1,
    189 	 * EDNS and DO=1. 0x88, 0x0c at the start is the ID field which
    190 	 * will be updated for each query.
    191 	 */
    192 	char respacket[] = {
    193 		 0x88, 0x0c, 0x01, 0x20, 0x00, 0x01, 0x00, 0x00,
    194 		 0x00, 0x00, 0x00, 0x01, 0x0a, 0x61, 0x61, 0x61,
    195 		 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x07,
    196 		 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00,
    197 		 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10,
    198 		 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00
    199 	};
    200 	/*
    201 	 * Response for example./DNSKEY in wire format. Note that RRSIGs
    202 	 * were generated with this DNSKEY that are used as seeds for
    203 	 * AFL in the DNSSEC fuzzing job. So the DNSKEY content of this
    204 	 * message must not change, or the corresponding RRSIGs will
    205 	 * have to be updated. 0x8d, 0xf6 at the start is the ID field
    206 	 * which will be made to match the query.
    207 	 */
    208 	const uint8_t dnskey_wf[] = {
    209 		0x8d, 0xf6, 0x84, 0x00, 0x00, 0x01, 0x00, 0x02,
    210 		0x00, 0x00, 0x00, 0x01, 0x07, 0x65, 0x78, 0x61,
    211 		0x6d, 0x70, 0x6c, 0x65, 0x00, 0x00, 0x30, 0x00,
    212 		0x01, 0xc0, 0x0c, 0x00, 0x30, 0x00, 0x01, 0x00,
    213 		0x00, 0x01, 0x2c, 0x01, 0x08, 0x01, 0x00, 0x03,
    214 		0x08, 0x03, 0x01, 0x00, 0x01, 0xbd, 0x81, 0xdc,
    215 		0x7f, 0x16, 0xd4, 0x81, 0x7c, 0x1f, 0x9f, 0x6a,
    216 		0x68, 0xdd, 0xd4, 0xda, 0x48, 0xd9, 0x1c, 0xbd,
    217 		0xa6, 0x46, 0x1a, 0xf0, 0xb4, 0xb9, 0xec, 0x3d,
    218 		0x6c, 0x0b, 0x57, 0xc7, 0xd6, 0x54, 0x66, 0xe6,
    219 		0x6c, 0xd5, 0x90, 0x3a, 0x78, 0x7d, 0x7f, 0x78,
    220 		0x80, 0xa2, 0x89, 0x61, 0x6d, 0x8a, 0x2b, 0xcd,
    221 		0x0a, 0x77, 0x7a, 0xad, 0xc9, 0x61, 0x53, 0x53,
    222 		0x8c, 0x99, 0x72, 0x86, 0x14, 0x74, 0x9c, 0x49,
    223 		0x2a, 0x47, 0x23, 0xf7, 0x02, 0x07, 0x73, 0x1c,
    224 		0x5c, 0x2e, 0xb4, 0x9a, 0xa4, 0xd7, 0x98, 0x42,
    225 		0xc3, 0xd2, 0xfe, 0xbf, 0xf3, 0xb3, 0x6a, 0x52,
    226 		0x92, 0xd5, 0xfa, 0x47, 0x00, 0xe3, 0xd9, 0x59,
    227 		0x31, 0x95, 0x48, 0x40, 0xfc, 0x06, 0x73, 0x90,
    228 		0xc6, 0x73, 0x96, 0xba, 0x29, 0x91, 0xe2, 0xac,
    229 		0xa3, 0xa5, 0x6d, 0x91, 0x6d, 0x52, 0xb9, 0x34,
    230 		0xba, 0x68, 0x4f, 0xad, 0xf0, 0xc3, 0xf3, 0x1d,
    231 		0x6d, 0x61, 0x76, 0xe5, 0x3d, 0xa3, 0x9b, 0x2a,
    232 		0x0c, 0x92, 0xb3, 0x78, 0x6b, 0xf1, 0x20, 0xd6,
    233 		0x90, 0xb7, 0xac, 0xe2, 0xf8, 0x2b, 0x94, 0x10,
    234 		0x79, 0xce, 0xa8, 0x60, 0x42, 0xea, 0x6a, 0x18,
    235 		0x2f, 0xc0, 0xd8, 0x05, 0x0a, 0x3b, 0x06, 0x0f,
    236 		0x02, 0x7e, 0xff, 0x33, 0x46, 0xee, 0xb6, 0x21,
    237 		0x25, 0x90, 0x63, 0x4b, 0x3b, 0x5e, 0xb2, 0x72,
    238 		0x3a, 0xcb, 0x91, 0x41, 0xf4, 0x20, 0x50, 0x78,
    239 		0x1c, 0x93, 0x95, 0xda, 0xfa, 0xae, 0x85, 0xc5,
    240 		0xd7, 0x6b, 0x92, 0x0c, 0x70, 0x6b, 0xe4, 0xb7,
    241 		0x29, 0x3a, 0x2e, 0x18, 0x88, 0x82, 0x33, 0x7c,
    242 		0xa8, 0xea, 0xb8, 0x31, 0x8f, 0xaf, 0x50, 0xc5,
    243 		0x9c, 0x08, 0x56, 0x8f, 0x09, 0x76, 0x4e, 0xdf,
    244 		0x97, 0x75, 0x9d, 0x00, 0x52, 0x7f, 0xdb, 0xec,
    245 		0x30, 0xcb, 0x1c, 0x4c, 0x2a, 0x21, 0x93, 0xc4,
    246 		0x6d, 0x85, 0xa9, 0x40, 0x3b, 0xc0, 0x0c, 0x00,
    247 		0x2e, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x01,
    248 		0x1b, 0x00, 0x30, 0x08, 0x01, 0x00, 0x00, 0x01,
    249 		0x2c, 0x67, 0x74, 0x85, 0x80, 0x58, 0xb3, 0xc5,
    250 		0x17, 0x36, 0x90, 0x07, 0x65, 0x78, 0x61, 0x6d,
    251 		0x70, 0x6c, 0x65, 0x00, 0x45, 0xac, 0xd3, 0x82,
    252 		0x69, 0xf3, 0x10, 0x3a, 0x97, 0x2c, 0x6a, 0xa9,
    253 		0x78, 0x99, 0xea, 0xb0, 0xcc, 0xf7, 0xaf, 0x33,
    254 		0x51, 0x5b, 0xdf, 0x77, 0x04, 0x18, 0x14, 0x99,
    255 		0x61, 0xeb, 0x8d, 0x76, 0x3f, 0xd1, 0x71, 0x14,
    256 		0x43, 0x80, 0x53, 0xc2, 0x3b, 0x9f, 0x09, 0x4f,
    257 		0xb3, 0x51, 0x04, 0x89, 0x0e, 0xc8, 0x54, 0x12,
    258 		0xcd, 0x07, 0x20, 0xbe, 0x94, 0xc2, 0xda, 0x99,
    259 		0xdd, 0x1e, 0xf8, 0xb0, 0x84, 0x2e, 0xf9, 0x19,
    260 		0x35, 0x36, 0xf5, 0xd0, 0x5d, 0x82, 0x18, 0x74,
    261 		0xa0, 0x00, 0xb6, 0x15, 0x57, 0x40, 0x5f, 0x78,
    262 		0x2d, 0x27, 0xac, 0xc7, 0x8a, 0x29, 0x55, 0xa9,
    263 		0xcd, 0xbc, 0xf7, 0x3e, 0xff, 0xae, 0x1a, 0x5a,
    264 		0x1d, 0xac, 0x0d, 0x78, 0x0e, 0x08, 0x33, 0x6c,
    265 		0x59, 0x70, 0x40, 0xb9, 0x65, 0xbd, 0x35, 0xbb,
    266 		0x9a, 0x70, 0xdc, 0x93, 0x66, 0xb0, 0xef, 0xfe,
    267 		0xf0, 0x32, 0xa6, 0xee, 0xb7, 0x03, 0x89, 0xa2,
    268 		0x4d, 0xe0, 0xf1, 0x20, 0xdf, 0x39, 0xe8, 0xe3,
    269 		0xcc, 0x95, 0xe9, 0x9a, 0xad, 0xbf, 0xbd, 0x7c,
    270 		0xf7, 0xd7, 0xde, 0x47, 0x9e, 0xf6, 0x17, 0xbb,
    271 		0x84, 0xa9, 0xed, 0xf2, 0x45, 0x61, 0x6d, 0x13,
    272 		0x0b, 0x06, 0x29, 0x50, 0xde, 0xfd, 0x42, 0xb0,
    273 		0x66, 0x2c, 0x1c, 0x2b, 0x63, 0xcb, 0x4e, 0xb9,
    274 		0x31, 0xc4, 0xea, 0xd2, 0x07, 0x3a, 0x08, 0x79,
    275 		0x19, 0x4b, 0x4c, 0x50, 0x97, 0x02, 0xd7, 0x26,
    276 		0x41, 0x2f, 0xdd, 0x57, 0xaa, 0xb0, 0xa0, 0x21,
    277 		0x4e, 0x74, 0xb6, 0x97, 0x4b, 0x8b, 0x09, 0x9c,
    278 		0x3d, 0x29, 0xfb, 0x12, 0x27, 0x47, 0x8f, 0xb8,
    279 		0xc5, 0x8e, 0x65, 0xcd, 0xca, 0x2f, 0xba, 0xf5,
    280 		0x3e, 0xec, 0x56, 0xc3, 0xc9, 0xa1, 0x62, 0x7d,
    281 		0xf2, 0x9f, 0x90, 0x16, 0x1d, 0xbf, 0x97, 0x28,
    282 		0xe1, 0x92, 0xb1, 0x53, 0xab, 0xc4, 0xe0, 0x99,
    283 		0xbb, 0x19, 0x90, 0x7c, 0x00, 0x00, 0x29, 0x10,
    284 		0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00
    285 	};
    286 
    287 	int sockfd;
    288 	int listenfd;
    289 	int loop;
    290 	uint16_t qtype;
    291 	char *buf, *rbuf;
    292 	char *nameptr;
    293 	unsigned int i;
    294 	uint8_t llen;
    295 	uint64_t seed;
    296 
    297 	UNUSED(arg);
    298 
    299 	/*
    300 	 * Parse named -A argument in the "qtype:saddress:sport:raddress:rport"
    301 	 * syntax.  Due to the syntax used, this only supports IPv4 addresses.
    302 	 */
    303 	sqtype = strdup(named_g_fuzz_addr);
    304 	RUNTIME_CHECK(sqtype != NULL);
    305 
    306 	shost = strchr(sqtype, ':');
    307 	RUNTIME_CHECK(shost != NULL);
    308 	*shost = 0;
    309 	shost++;
    310 
    311 	sport = strchr(shost, ':');
    312 	RUNTIME_CHECK(sport != NULL);
    313 	*sport = 0;
    314 	sport++;
    315 
    316 	rhost = strchr(sport, ':');
    317 	RUNTIME_CHECK(rhost != NULL);
    318 	*rhost = 0;
    319 	rhost++;
    320 
    321 	rport = strchr(rhost, ':');
    322 	RUNTIME_CHECK(rport != NULL);
    323 	*rport = 0;
    324 	rport++;
    325 
    326 	/*
    327 	 * Patch in the qtype into the question section of respacket.
    328 	 */
    329 	qtype = atoi(sqtype);
    330 	respacket[32] = (qtype >> 8) & 0xff;
    331 	respacket[33] = qtype & 0xff;
    332 
    333 	memset(&servaddr, 0, sizeof (servaddr));
    334 	servaddr.sin_family = AF_INET;
    335 	RUNTIME_CHECK(inet_pton(AF_INET, shost, &servaddr.sin_addr) == 1);
    336 	servaddr.sin_port = htons(atoi(sport));
    337 
    338 	memset(&recaddr, 0, sizeof (recaddr));
    339 	recaddr.sin_family = AF_INET;
    340 	RUNTIME_CHECK(inet_pton(AF_INET, rhost, &recaddr.sin_addr) == 1);
    341 	recaddr.sin_port = htons(atoi(rport));
    342 
    343 	free(sqtype);
    344 
    345 	/*
    346 	 * Wait for named to start. This is set in run_server() in the
    347 	 * named thread.
    348 	 */
    349 	while (!named_g_run_done) {
    350 		usleep(10000);
    351 	}
    352 
    353 	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    354 	RUNTIME_CHECK(sockfd != -1);
    355 
    356 	listenfd = socket(AF_INET, SOCK_DGRAM, 0);
    357 	RUNTIME_CHECK(listenfd != -1);
    358 
    359 	RUNTIME_CHECK(bind(listenfd, (struct sockaddr *)&recaddr,
    360 			   sizeof(struct sockaddr_in)) == 0);
    361 
    362 	buf = malloc(65536);
    363 	rbuf = malloc(65536);
    364 	RUNTIME_CHECK(buf != NULL);
    365 	RUNTIME_CHECK(rbuf != NULL);
    366 
    367 	seed = 42;
    368 
    369 	/*
    370 	 * Processing fuzzed packets 100,000 times before shutting down
    371 	 * the app.
    372 	 */
    373 	for (loop = 0; loop < 100000; loop++) {
    374 		ssize_t length;
    375 		ssize_t sent;
    376 		unsigned short id;
    377 		socklen_t socklen;
    378 
    379 		memset(buf, 0, 12);
    380 		length = read(0, buf, 65536);
    381 		if (length <= 0) {
    382 			usleep(1000000);
    383 			continue;
    384 		}
    385 
    386 		if (length > 4096) {
    387 			if (getenv("AFL_CMIN")) {
    388 				free(buf);
    389 				free(rbuf);
    390 				close(sockfd);
    391 				close(listenfd);
    392 				named_server_flushonshutdown(named_g_server,
    393 							     false);
    394 				isc_app_shutdown();
    395 				return (NULL);
    396 			}
    397 			raise(SIGSTOP);
    398 			continue;
    399 		}
    400 
    401 		if (length < 12) {
    402 		    length = 12;
    403 		}
    404 
    405 		RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    406 
    407 		ready = false;
    408 
    409 		/* Use a unique query ID. */
    410 		seed = 1664525 * seed + 1013904223;
    411 		id = seed & 0xffff;
    412 		respacket[0] = (id >> 8) & 0xff;
    413 		respacket[1] = id & 0xff;
    414 
    415 		/*
    416 		 * Flush any pending data on the authoritative server.
    417 		 */
    418 		socklen = sizeof(recvaddr);
    419 		sent = recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT,
    420 			(struct sockaddr *) &recvaddr, &socklen);
    421 
    422 		/*
    423 		 * Send a fixed client query to named(resolver) of
    424 		 * aaaaaaaaaa.example./A. This is the starting query
    425 		 * driver.
    426 		 */
    427 		sent = sendto(sockfd, respacket, sizeof(respacket), 0,
    428 		       (struct sockaddr *) &servaddr, sizeof(servaddr));
    429 		RUNTIME_CHECK(sent == sizeof(respacket));
    430 
    431 		/*
    432 		 * named(resolver) will process the query above and send
    433 		 * an upstream query to the authoritative server. We
    434 		 * handle that here as the upstream authoritative server
    435 		 * on listenfd.
    436 		 */
    437 		socklen = sizeof(recvaddr);
    438 		sent = recvfrom(listenfd, rbuf, 65536, 0,
    439 				(struct sockaddr *) &recvaddr, &socklen);
    440 		RUNTIME_CHECK(sent > 0);
    441 
    442 		/*
    443 		 * Copy QID and set QR so that response is always
    444 		 * accepted by named(resolver).
    445 		 */
    446 		buf[0] = rbuf[0];
    447 		buf[1] = rbuf[1];
    448 		buf[2] |= 0x80;
    449 
    450 		/*
    451 		 * NOTE: We are not copying the QNAME or setting
    452 		 * rcode=NOERROR each time. So the resolver may fail the
    453 		 * client query (driver) / wander due to this. AA flag
    454 		 * may also not be set based on the contents of the AFL
    455 		 * fuzzed packet.
    456 		 */
    457 
    458 		/*
    459 		 * A hack - set QTYPE to the one from query so that we
    460 		 * can easily share packets between instances. If we
    461 		 * write over something else we'll get FORMERR anyway.
    462 		 */
    463 
    464 		/* Skip DNS header to get to the name */
    465 		nameptr = buf + 12;
    466 
    467 		/* Skip the name to get to the qtype */
    468 		i = 0;
    469 		while (((llen = nameptr[i]) != 0) &&
    470 		       (i < 255) &&
    471 		       (((nameptr + i + 1 + llen) - buf) < length))
    472 			i += 1 + llen;
    473 
    474 		if (i <= 255) {
    475 			nameptr += 1 + i;
    476 			/* Patch the qtype */
    477 			if ((nameptr - buf) < (length - 2)) {
    478 				*nameptr++ = (qtype >> 8) & 0xff;
    479 				*nameptr++ = qtype & 0xff;
    480 			}
    481 			/* Patch the qclass */
    482 			if ((nameptr - buf) < (length - 2)) {
    483 				*nameptr++ = 0;
    484 				*nameptr++ = 1;
    485 			}
    486 		}
    487 
    488 		/*
    489 		 * Send the reply to named(resolver).
    490 		 */
    491 		sent = sendto(listenfd, buf, length, 0,
    492 			      (struct sockaddr *) &recvaddr, sizeof(recvaddr));
    493 		RUNTIME_CHECK(sent == length);
    494 
    495 		/* We might get additional questions here (e.g. for CNAME). */
    496 		for (;;) {
    497 			fd_set fds;
    498 			struct timeval tv;
    499 			int rv;
    500 			int max;
    501 
    502 			FD_ZERO(&fds);
    503 			FD_SET(listenfd, &fds);
    504 			FD_SET(sockfd, &fds);
    505 			tv.tv_sec = 10;
    506 			tv.tv_usec = 0;
    507 			max = (listenfd > sockfd ? listenfd : sockfd)+1;
    508 
    509 			rv = select(max, &fds, NULL, NULL, &tv);
    510 			RUNTIME_CHECK(rv > 0);
    511 
    512 			if (FD_ISSET(sockfd, &fds)) {
    513 				/*
    514 				 * It's the reply from named(resolver)
    515 				 * to the client(query driver), so we're
    516 				 * done.
    517 				 */
    518 				recvfrom(sockfd, buf, 65536, 0, NULL, NULL);
    519 				break;
    520 			}
    521 
    522 			/*
    523 			 * We've got additional question (eg. due to
    524 			 * CNAME). Bounce it - setting QR flag and
    525 			 * NOERROR rcode and sending it back.
    526 			 */
    527 			length = recvfrom(listenfd, buf, 65536, 0,
    528 				   (struct sockaddr *) &recvaddr, &socklen);
    529 
    530 			/*
    531 			 * If this is a DNSKEY query, send the DNSKEY,
    532 			 * otherwise, bounce the query.
    533 			 */
    534 
    535 			/* Skip DNS header to get to the name */
    536 			nameptr = buf + 12;
    537 
    538 			/* Skip the name to get to the qtype */
    539 			i = 0;
    540 			while (((llen = nameptr[i]) != 0) &&
    541 			       (i < 255) &&
    542 			       (((nameptr + i + 1 + llen) - buf) < length))
    543 				i += 1 + llen;
    544 
    545 			if (i <= 255) {
    546 				nameptr += 1 + i;
    547 				/*
    548 				 * Patch in the DNSKEY reply without
    549 				 * touching the ID field. Note that we
    550 				 * don't compare the name in the
    551 				 * question section in the query, but we
    552 				 * don't expect to receive any query for
    553 				 * type DNSKEY but for the name
    554 				 * "example."
    555 				 */
    556 				if ((nameptr - buf) < (length - 2)) {
    557 					uint8_t hb, lb;
    558 					hb = *nameptr++;
    559 					lb = *nameptr++;
    560 					qtype = (hb << 8) | lb;
    561 
    562 					if (qtype == 48) {
    563 						memmove(buf + 2, dnskey_wf + 2,
    564 							sizeof (dnskey_wf) - 2);
    565 						length = sizeof (dnskey_wf);
    566 					}
    567 				}
    568 			}
    569 
    570 			buf[2] |= 0x80;
    571 			buf[3] &= 0xF0;
    572 			sent = sendto(listenfd, buf, length, 0,
    573 				      (struct sockaddr *) &recvaddr,
    574 				      sizeof(recvaddr));
    575 			RUNTIME_CHECK(sent == length);
    576 		}
    577 
    578 		while (!ready)
    579 			pthread_cond_wait(&cond, &mutex);
    580 
    581 		RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    582 	}
    583 
    584 	free(buf);
    585 	free(rbuf);
    586 	close(sockfd);
    587 	close(listenfd);
    588 	named_server_flushonshutdown(named_g_server, false);
    589 	isc_app_shutdown();
    590 
    591 #ifdef __AFL_LOOP
    592 	/*
    593 	 * This is here just for the signature, that's how AFL detects
    594 	 * if it's a 'persistent mode' binary. It has to occur somewhere
    595 	 * in the file, that's all. < wpk_> AFL checks the binary for
    596 	 * this signature ("##SIG_AFL_PERSISTENT##") and runs the binary
    597 	 * in persistent mode if it's present.
    598 	 */
    599 	__AFL_LOOP(0);
    600 #endif
    601 
    602 	return (NULL);
    603 }
    604 
    605 /*
    606  * In "tcp:", "http:" and "rndc:" modes, this thread reads fuzzed query
    607  * blobs from AFL from standard input and sends it to the corresponding
    608  * TCP listening port of named (port 53 DNS, or the HTTP statistics
    609  * channels listener or the rndc port) that is passed in the -A
    610  * <mode>:<address>:<port> option. It can be used to test named from the
    611  * client side.
    612  */
    613 static void *
    614 fuzz_thread_tcp(void *arg) {
    615 	char *host;
    616 	char *port;
    617 	struct sockaddr_in servaddr;
    618 	int sockfd;
    619 	char *buf;
    620 	int loop;
    621 
    622 	UNUSED(arg);
    623 
    624 	/*
    625 	 * Parse named -A argument in the "address:port" syntax. Due to
    626 	 * the syntax used, this only supports IPv4 addresses.
    627 	 */
    628 	host = strdup(named_g_fuzz_addr);
    629 	RUNTIME_CHECK(host != NULL);
    630 
    631 	port = strchr(host, ':');
    632 	RUNTIME_CHECK(port != NULL);
    633 	*port = 0;
    634 	++port;
    635 
    636 	memset(&servaddr, 0, sizeof (servaddr));
    637 	servaddr.sin_family = AF_INET;
    638 	RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1);
    639 	servaddr.sin_port = htons(atoi(port));
    640 
    641 	free(host);
    642 
    643 	/*
    644 	 * Wait for named to start. This is set in run_server() in the
    645 	 * named thread.
    646 	 */
    647 	while (!named_g_run_done) {
    648 		usleep(10000);
    649 	}
    650 
    651 	buf = malloc(65539);
    652 	RUNTIME_CHECK(buf != NULL);
    653 
    654 	/*
    655 	 * Processing fuzzed packets 100,000 times before shutting down
    656 	 * the app.
    657 	 */
    658 	for (loop = 0; loop < 100000; loop++) {
    659 		ssize_t length;
    660 		ssize_t sent;
    661 		int yes;
    662 		int r;
    663 
    664 		if (named_g_fuzz_type == isc_fuzz_tcpclient) {
    665 			/*
    666 			 * To fuzz DNS TCP client we have to put 16-bit
    667 			 * message length preceding the start of packet.
    668 			 */
    669 			length = read(0, buf+2, 65535);
    670 			buf[0] = (length >> 8) & 0xff;
    671 			buf[1] = length & 0xff;
    672 			length += 2;
    673 		} else {
    674 			/*
    675 			 * Other types of TCP clients such as HTTP, etc.
    676 			 */
    677 			length = read(0, buf, 65535);
    678 		}
    679 		if (length <= 0) {
    680 			usleep(1000000);
    681 			continue;
    682 		}
    683 		if (named_g_fuzz_type == isc_fuzz_http) {
    684 			/*
    685 			 * This guarantees that the request will be
    686 			 * processed.
    687 			 */
    688 			INSIST(length <= 65535);
    689 			buf[length++]='\r';
    690 			buf[length++]='\n';
    691 			buf[length++]='\r';
    692 			buf[length++]='\n';
    693 		}
    694 
    695 		RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    696 
    697 		ready = false;
    698 		yes = 1;
    699 		sockfd = socket(AF_INET, SOCK_STREAM, 0);
    700 
    701 		RUNTIME_CHECK(sockfd != -1);
    702 		RUNTIME_CHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
    703 					 &yes, sizeof(int)) == 0);
    704 
    705 		do {
    706 			r = connect(sockfd, (struct sockaddr*)&servaddr,
    707 				    sizeof(servaddr));
    708 			if (r != 0)
    709 				usleep(10000);
    710 		} while (r != 0);
    711 
    712 		/*
    713 		 * Send the fuzzed query blob to the target server.
    714 		 */
    715 		sent = write(sockfd, buf, length);
    716 		RUNTIME_CHECK(sent == length);
    717 
    718 		close(sockfd);
    719 
    720 		while (!ready)
    721 			pthread_cond_wait(&cond, &mutex);
    722 
    723 		RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    724 	}
    725 
    726 	free(buf);
    727 	close(sockfd);
    728 	named_server_flushonshutdown(named_g_server, false);
    729 	isc_app_shutdown();
    730 
    731 	return (NULL);
    732 }
    733 
    734 #endif /* ENABLE_AFL */
    735 
    736 /*
    737  * named has finished processing a message and has sent the
    738  * reply. Signal the fuzz thread using the condition variable, to read
    739  * and process the next item from AFL.
    740  */
    741 void
    742 named_fuzz_notify(void) {
    743 #ifdef ENABLE_AFL
    744 	if (getenv("AFL_CMIN")) {
    745 		named_server_flushonshutdown(named_g_server, false);
    746 		isc_app_shutdown();
    747 		return;
    748 	}
    749 
    750 	raise(SIGSTOP);
    751 
    752 	RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    753 
    754 	ready = true;
    755 
    756 	RUNTIME_CHECK(pthread_cond_signal(&cond) == 0);
    757 	RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    758 #endif /* ENABLE_AFL */
    759 }
    760 
    761 void
    762 named_fuzz_setup(void) {
    763 #ifdef ENABLE_AFL
    764 	if (getenv("__AFL_PERSISTENT") || getenv("AFL_CMIN")) {
    765 		pthread_t thread;
    766 		void *(fn) = NULL;
    767 
    768 		switch (named_g_fuzz_type) {
    769 		case isc_fuzz_client:
    770 			fn = fuzz_thread_client;
    771 			break;
    772 
    773 		case isc_fuzz_http:
    774 		case isc_fuzz_tcpclient:
    775 		case isc_fuzz_rndc:
    776 			fn = fuzz_thread_tcp;
    777 			break;
    778 
    779 		case isc_fuzz_resolver:
    780 			fn = fuzz_thread_resolver;
    781 			break;
    782 
    783 		default:
    784 			RUNTIME_CHECK(fn != NULL);
    785 		}
    786 
    787 		RUNTIME_CHECK(pthread_mutex_init(&mutex, NULL) == 0);
    788 		RUNTIME_CHECK(pthread_cond_init(&cond, NULL) == 0);
    789 		RUNTIME_CHECK(pthread_create(&thread, NULL, fn, NULL) == 0);
    790 	}
    791 #endif /* ENABLE_AFL */
    792 }
    793