public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Anshu Kumari <anskuma@redhat.com>
To: david@gibson.dropbear.id.au, sbrivio@redhat.com, passt-dev@passt.top
Cc: aerosound161@gmail.com, abdobngad@gmail.com, anskuma@redhat.com,
	lvivier@redhat.com
Subject: [PATCH 5/5] fuzz: Add test server for bidirectional protocol fuzzing
Date: Wed, 12 Aug 2026 12:56:28 +0530	[thread overview]
Message-ID: <20260812072630.3235261-6-anskuma@redhat.com> (raw)
In-Reply-To: <20260812072630.3235261-1-anskuma@redhat.com>

Add fuzz-server that acts as passt's network peer
during fuzzing. It connects to passt's UNIX socket
and listens on 127.0.0.1:9999 for TCP connections.

UNIX socket path: responds to ARP requests and TCP SYNs with
  stateless replies (swapped addresses, fixed ISN). Responses
  are XOR'd with AFL++ shared memory data so the fuzzer can
  mutate server behavior.

TCP loopback path: accepts connections on port 9999, reads
  data, XOR-mutates with AFL++ shared memory, and echoes it
  back. Uses SO_LINGER(0) for immediate RST on close to
  avoid TIME_WAIT port exhaustion.

Turn-based synchronization via mmap'd flag in /dev/shm
  coordinates frame exchange between passt and the server.

Also adds:
- fuzzing/testcase_dir/empty.bin
- fuzzing/README.fuzzing.md

Signed-off-by: Anshu Kumari <anskuma@redhat.com>
---
 Makefile                       |   8 +-
 fuzz-server.c                  | 490 +++++++++++++++++++++++++++++++++
 fuzzing/README.fuzzing.md      |  95 +++++++
 fuzzing/testcase_dir/empty.bin | Bin 0 -> 12 bytes
 4 files changed, 591 insertions(+), 2 deletions(-)
 create mode 100644 fuzz-server.c
 create mode 100644 fuzzing/README.fuzzing.md
 create mode 100644 fuzzing/testcase_dir/empty.bin

diff --git a/Makefile b/Makefile
index 8e4121e..4517bc7 100644
--- a/Makefile
+++ b/Makefile
@@ -125,17 +125,21 @@ valgrind: all
 
 FUZZ_CC ?= afl-clang-fast
 
-.PHONY: fuzz
+.PHONY: fuzz fuzz-server
 
 fuzz:
 	$(MAKE) clean
 	$(MAKE) CC="$(FUZZ_CC)" CPPFLAGS="-DFUZZING -DNDEBUG" CFLAGS="-g -fsanitize=address" passt
 
+fuzz-server:
+	$(CC) -D_GNU_SOURCE -O2 -o fuzz-server fuzz-server.c
+
 .PHONY: clean
 clean:
 	$(RM) $(BIN) *~ *.o seccomp.h seccomp_repair.h seccomp_pesto.h pasta.1 \
 		passt.tar passt.tar.gz *.deb *.rpm \
-		passt.pid README.plain.md
+		passt.pid README.plain.md \
+		fuzz-server
 
 install: $(BIN) $(MANPAGES) docs
 	mkdir -p $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir)
diff --git a/fuzz-server.c b/fuzz-server.c
new file mode 100644
index 0000000..c9b4101
--- /dev/null
+++ b/fuzz-server.c
@@ -0,0 +1,490 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/* fuzz-server.c - Test server for bidirectional fuzz testing of passt
+ *
+ * Connects to passt's UNIX socket as a client.
+ * Reads outbound frames, generates protocol responses, XORs them
+ * with AFL++ shared memory data, and writes them back.
+ *
+ * Build: make fuzz-server
+ * Run:   ./fuzz-server (after passt.fuzz is listening)
+ *
+ * Copyright Red Hat
+ * Author: Anshu Kumari <anskuma@redhat.com>
+ */
+
+#include <linux/if_ether.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/epoll.h>
+#include <sys/shm.h>
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#define FUZZ_SOCK_PATH		"/tmp/passt_fuzz_1.socket"
+#define FUZZ_TURN_PATH		"/dev/shm/passt_fuzz_turn"
+#define FUZZ_XOR_OFF		(12 + 64 * 1024)
+#define MAX_FRAME		1600
+#define TCP_LISTEN_PORT		9999
+#define TCP_MAX_EVENTS		16
+
+/**
+ * struct fuzz_turn - Turn-based synchronization flag (mmap'd shared memory)
+ * @turn:	0 = passt's turn, 1 = server's turn
+ */
+struct fuzz_turn {
+	uint32_t turn;
+};
+
+/**
+ * swap_eth_ip() - Swap Ethernet MACs and IPv4 addresses
+ * @pkt:	Pointer to start of Ethernet frame
+ */
+static void swap_eth_ip(uint8_t *pkt)
+{
+	struct ethhdr *eth = (void *)pkt;
+	struct iphdr *iph = (void *)(eth + 1);
+	uint8_t tmp_mac[ETH_ALEN];
+	uint8_t tmp_ip[4];
+
+	memcpy(tmp_mac, eth->h_source, ETH_ALEN);
+	memcpy(eth->h_source, eth->h_dest, ETH_ALEN);
+	memcpy(eth->h_dest, tmp_mac, ETH_ALEN);
+
+	memcpy(tmp_ip, &iph->saddr, 4);
+	memcpy(&iph->saddr, &iph->daddr, 4);
+	memcpy(&iph->daddr, tmp_ip, 4);
+}
+
+/**
+ * respond_arp() - Generate ARP reply for an ARP request
+ * @in:		Incoming frame
+ * @in_len:	Incoming frame length
+ * @out:	Output buffer for response
+ *
+ * Swaps sender hardware and protocol addresses to form a
+ * valid ARP reply. Only responds to ARP requests (op=1).
+ *
+ * Return: response length, or 0 if not an ARP request
+ */
+static int respond_arp(const uint8_t *in, uint32_t in_len, uint8_t *out)
+{
+	/* Min ARP Frame size: eth(14) + ARP Header(8) + Payload(20) */
+	if (in_len < 42)
+		return 0;
+
+	const struct ethhdr *eth = (const void *)in;
+	const struct arphdr *arp = (const void *)(eth + 1);
+
+	if (eth->h_proto != htons(ETH_P_ARP) ||
+	    arp->ar_op != htons(ARPOP_REQUEST))
+		return 0;
+
+	memcpy(out, in, in_len);
+
+	struct ethhdr *out_eth = (void *)out;
+	struct arphdr *out_arp = (void *)(out_eth + 1);
+
+	/* set MAC addresses for output buffer */
+	memcpy(out_eth->h_dest, eth->h_source, ETH_ALEN);
+	memcpy(out_eth->h_source, eth->h_dest, ETH_ALEN);
+
+	/* set ARP operation to REPLY */
+	out_arp->ar_op = htons(ARPOP_REPLY);
+
+	/* Swap ARP Sender and Target fields */
+	uint8_t *sender = (uint8_t *)(out_arp + 1);
+	uint8_t *target = sender + 10;
+	uint8_t tmp[10];
+
+	memcpy(tmp, sender, 10);
+	memcpy(sender, target, 10);
+	memcpy(target, tmp, 10);
+
+	return in_len;
+}
+
+/**
+ * respond_tcp_syn() - Generate SYN-ACK for a TCP SYN
+ * @in:         Incoming frame
+ * @in_len:     Incoming frame length
+ * @out:        Output buffer for response
+ *
+ * Swaps MAC/IP/port addresses and crafts a stateless SYN-ACK with
+ * a fixed ISN of 1000. Only responds to pure SYN (no ACK set).
+ *
+ * Return: response length, or 0 if not a TCP SYN
+ */
+static int respond_tcp_syn(const uint8_t *in, uint32_t in_len, uint8_t *out)
+{
+	const struct ethhdr *eth = (const void *)in;
+	const struct iphdr *iph;
+	const struct tcphdr *th;
+	struct tcphdr *out_th;
+	uint32_t ihl, hdr_len;
+
+	/* Combined minimum length check for Eth + IP + TCP */
+	if (in_len < sizeof(*eth) + sizeof(*iph) + sizeof(*th))
+		return 0;
+
+	if (eth->h_proto != htons(ETH_P_IP))
+		return 0;
+
+	iph = (const void *)(eth + 1);
+	ihl = iph->ihl * 4;
+
+	if (iph->protocol != IPPROTO_TCP ||
+	    in_len < sizeof(*eth) + ihl + sizeof(*th))
+		return 0;
+
+	th = (const void *)((const uint8_t *)iph + ihl);
+
+	/* Only respond to pure SYN packets (no ACK set) */
+	if (!th->syn || th->ack)
+		return 0;
+
+	hdr_len = sizeof(*eth) + ihl + sizeof(*th);
+	memcpy(out, in, hdr_len);
+	swap_eth_ip(out);
+
+	/* Craft SYN-ACK response header */
+	out_th = (struct tcphdr *)(out + sizeof(*eth) + ihl);
+	out_th->source  = th->dest;
+	out_th->dest    = th->source;
+	out_th->seq     = htonl(1000);
+	out_th->ack_seq = htonl(ntohl(th->seq) + 1);
+	out_th->syn     = 1;
+	out_th->ack     = 1;
+	out_th->doff    = 5;
+	out_th->check   = 0;
+
+	return hdr_len;
+}
+
+/**
+ * generate_response() - Try all protocol responders on a frame
+ * @in:		Incoming frame
+ * @in_len:	Incoming frame length
+ * @out:	Output buffer for response
+ *
+ * Tries ARP then TCP SYN responders in order. Returns the first
+ * successful response.
+ *
+ * Return: response length, or 0 if no responder matched
+ */
+static int generate_response(const uint8_t *in, uint32_t in_len, uint8_t *out)
+{
+	int len;
+
+	if (in_len < sizeof(struct ethhdr))
+		return 0;
+
+	if ((len = respond_arp(in, in_len, out)) > 0)
+		return len;
+	if ((len = respond_tcp_syn(in, in_len, out)) > 0)
+		return len;
+
+	return 0;
+}
+
+/**
+ * map_afl_shm() - Map AFL++ shared memory for XOR mutation
+ *
+ * Reads __AFL_SHM_FUZZ_ID from the AFL++ environment
+ * variable and attaches the corresponding shared memory
+ * segment read-only.
+ *
+ * Return: pointer to mapped SHM, or NULL if not available
+ */
+static uint8_t *map_afl_shm(void)
+{
+	const char *id_str = getenv("__AFL_SHM_FUZZ_ID");
+	int shm_id;
+	uint8_t *map;
+
+	if (!id_str)
+		return NULL;
+
+	shm_id = atoi(id_str);
+	map = shmat(shm_id, NULL, SHM_RDONLY);
+	if (map == (void *)-1)
+		return NULL;
+
+	return map;
+}
+
+/**
+ * apply_xor_mask() - XOR buffer with AFL++ shared memory data
+ * @buf:	Buffer to mutate in place
+ * @len:	Buffer length
+ * @afl_buf:	AFL++ shared memory
+ *
+ * XORs each byte of @buf with the corresponding byte from the
+ * AFL++ buffer starting at offset FUZZ_XOR_OFF (65548). This
+ * lets AFL++ mutate server responses.
+ */
+static void apply_xor_mask(uint8_t *buf, int len, const uint8_t *afl_buf)
+{
+	int i;
+
+	if (!afl_buf)
+		return;
+
+	for (i = 0; i < len; i++)
+		buf[i] ^= afl_buf[FUZZ_XOR_OFF + i];
+}
+
+/* ---- TCP Host Listener (Loopback) ---- */
+
+static int tcp_listen_fd = -1;
+static int tcp_epfd = -1;
+
+/**
+ * tcp_listener_init() - Set up TCP listener on loopback port 9999
+ *
+ * Creates an epoll instance and a non-blocking TCP listener on
+ * 127.0.0.1:9999 with SO_REUSEADDR.
+ *
+ * Return: 0 on success, -1 on failure
+ */
+static int tcp_listener_init(void)
+{
+	struct sockaddr_in sa = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+		.sin_port = htons(TCP_LISTEN_PORT),
+	};
+	struct epoll_event ev;
+	int opt = 1;
+
+	tcp_epfd = epoll_create1(EPOLL_CLOEXEC);
+	tcp_listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
+	if (tcp_epfd < 0 || tcp_listen_fd < 0)
+		return -1;
+
+	setsockopt(tcp_listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+	if (bind(tcp_listen_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0 ||
+	    listen(tcp_listen_fd, 128) < 0)
+		return -1;
+
+	ev.events = EPOLLIN;
+	ev.data.fd = tcp_listen_fd;
+	epoll_ctl(tcp_epfd, EPOLL_CTL_ADD, tcp_listen_fd, &ev);
+
+	return 0;
+}
+
+/**
+ * tcp_handle_accept() - Drain all pending TCP connections
+ *
+ * Sets SO_LINGER with l_linger=0 on every accepted connection,
+ * which does the immediate RST on connection close instead of
+ * waiting for connection to close on it's own.
+ */
+static void tcp_handle_accept(void)
+{
+	struct linger lg = { .l_onoff = 1, .l_linger = 0 };
+	struct epoll_event ev;
+	int fd;
+
+	/* Drain ALL pending connections in the backlog */
+	while ((fd = accept4(tcp_listen_fd, NULL, NULL,
+			     SOCK_NONBLOCK)) >= 0) {
+		setsockopt(fd, SOL_SOCKET, SO_LINGER, &lg, sizeof(lg));
+
+		ev.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR;
+		ev.data.fd = fd;
+		epoll_ctl(tcp_epfd, EPOLL_CTL_ADD, fd, &ev);
+	}
+}
+
+/**
+ * tcp_handle_data() - Read TCP data, XOR-mutate, echo back
+ * @fd:		Connected TCP socket
+ * @afl_buf:	AFL++ shared memory for XOR mask
+ */
+static void tcp_handle_data(int fd, const uint8_t *afl_buf)
+{
+	uint8_t buf[MAX_FRAME];
+	ssize_t n, written, ret;
+
+	n = read(fd, buf, sizeof(buf));
+	if (n <= 0) {
+		epoll_ctl(tcp_epfd, EPOLL_CTL_DEL, fd, NULL);
+		close(fd);
+		return;
+	}
+
+	apply_xor_mask(buf, (uint32_t)n, afl_buf);
+
+	/* Ensure all n bytes are written, handling short writes */
+	written = 0;
+	while (written < n) {
+		ret = write(fd, buf + written, (size_t)(n - written));
+		if (ret <= 0) {
+			if (ret < 0 && (errno == EAGAIN ||
+					errno == EWOULDBLOCK))
+				continue;
+
+			epoll_ctl(tcp_epfd, EPOLL_CTL_DEL, fd, NULL);
+			close(fd);
+			return;
+		}
+		written += ret;
+	}
+}
+
+/**
+ * tcp_process_events() - Non-blocking poll for TCP events
+ * @afl_buf:	AFL++ shared memory
+ */
+static void tcp_process_events(const uint8_t *afl_buf)
+{
+	struct epoll_event events[TCP_MAX_EVENTS];
+	int nfds, i;
+
+	nfds = epoll_wait(tcp_epfd, events, TCP_MAX_EVENTS, 0);
+
+	for (i = 0; i < nfds; i++) {
+		int fd = events[i].data.fd;
+
+		if (fd == tcp_listen_fd) {
+			tcp_handle_accept();
+		} else if (events[i].events & (EPOLLIN | EPOLLRDHUP)) {
+			tcp_handle_data(fd, afl_buf);
+		} else if (events[i].events & (EPOLLHUP | EPOLLERR)) {
+			epoll_ctl(tcp_epfd, EPOLL_CTL_DEL, fd, NULL);
+			close(fd);
+		}
+	}
+}
+
+/**
+ * create_turn_flag() - Create and mmap the turn synchronization flag
+ *
+ * Creates FUZZ_TURN_PATH in /dev/shm and maps it
+ * as shared memory. Both passt and fuzz-server map this file to
+ * coordinate turn-based frame exchange via atomic load/store.
+ *
+ * Return: pointer to mapped turn struct, or NULL on failure
+ */
+static struct fuzz_turn *create_turn_flag(void)
+{
+	struct fuzz_turn *t;
+	int fd;
+
+	fd = open(FUZZ_TURN_PATH, O_RDWR | O_CREAT | O_TRUNC, 0644);
+	if (fd < 0)
+		return NULL;
+
+	if (ftruncate(fd, sizeof(struct fuzz_turn)) < 0) {
+		close(fd);
+		return NULL;
+	}
+
+	t = mmap(NULL, sizeof(*t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	close(fd);
+
+	if (t == MAP_FAILED)
+		return NULL;
+
+	t->turn = 0;
+	return t;
+}
+
+/**
+ * main() - Server entry point
+ *
+ * Outer loop reconnects to passt's UNIX socket on each AFL++ fork
+ * server restart. Inner loop handles turn-based TAP frame exchange
+ * and TCP events concurrently.
+ *
+ * Return: 0 on success, 1 on initialization failure
+ */
+int main(void)
+{
+	struct sockaddr_un addr = { .sun_family = AF_UNIX };
+	uint8_t frame[MAX_FRAME], response[MAX_FRAME];
+	struct fuzz_turn *turn;
+	uint8_t *afl_buf;
+
+	strncpy(addr.sun_path, FUZZ_SOCK_PATH, sizeof(addr.sun_path) - 1);
+
+	turn = create_turn_flag();
+	if (!turn || tcp_listener_init() < 0) {
+		(void)fprintf(stderr,
+			      "fuzz-server: tcp initialization failed\n");
+		return 1;
+	}
+
+	afl_buf = map_afl_shm();
+	(void)fprintf(stderr,
+		      "fuzz-server: ready, TCP listening on 127.0.0.1:%d\n",
+		TCP_LISTEN_PORT);
+
+	/*
+	 * Reconnect UNIX socket on passt restart — AFL++'s fork server
+	 * restarts passt on each iteration.
+	 */
+	while (1) {
+		ssize_t n;
+		int sock;
+
+		sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+		if (sock < 0)
+			return 1;
+
+		while (connect(sock, (struct sockaddr *)&addr,
+			       sizeof(addr)) < 0)
+			usleep(10000);
+
+		while (1) {
+			tcp_process_events(afl_buf);
+
+			if (__atomic_load_n(&turn->turn,
+					    __ATOMIC_ACQUIRE) == 1) {
+				n = recv(sock, frame, MAX_FRAME,
+					 MSG_DONTWAIT);
+				if (n > 0) {
+					int resp_len;
+
+					resp_len = generate_response(
+							frame, n, response);
+					if (resp_len > 0) {
+						apply_xor_mask(response,
+							       resp_len,
+							       afl_buf);
+						send(sock, response,
+						     resp_len, MSG_NOSIGNAL);
+					}
+				} else if (n == 0 ||
+					   (n < 0 && errno != EAGAIN &&
+					    errno != EWOULDBLOCK)) {
+					__atomic_store_n(&turn->turn, 0,
+							 __ATOMIC_RELEASE);
+					break;
+				}
+
+				__atomic_store_n(&turn->turn, 0,
+						 __ATOMIC_RELEASE);
+			}
+		}
+
+		close(sock);
+	}
+
+	return 0;
+}
diff --git a/fuzzing/README.fuzzing.md b/fuzzing/README.fuzzing.md
new file mode 100644
index 0000000..f23e265
--- /dev/null
+++ b/fuzzing/README.fuzzing.md
@@ -0,0 +1,95 @@
+## Fuzzing passt with AFL++
+
+### Prerequisites
+
+- AFL++ (afl-clang-fast, afl-fuzz)
+
+### Build
+
+```
+make fuzz
+cp passt passt.fuzz
+make fuzz-server
+```
+
+This produces:
+- `passt.fuzz` -- instrumented with AFL++ and AddressSanitizer
+- `fuzz-server` -- test server for bidirectional protocol fuzzing
+
+To use a specific AFL++ installation:
+
+```
+make FUZZ_CC=/path/to/afl-clang-fast fuzz
+```
+
+### Run
+
+Start the test server first, then the fuzzer:
+
+```
+# Terminal 1 -- test server:
+./fuzz-server
+
+# Terminal 2 -- fuzzer:
+afl-fuzz -i fuzzing/testcase_dir -o fuzzing/sync_dir \
+  -- ./passt.fuzz --foreground
+```
+
+Multi-core (secondary instances share the corpus):
+
+```
+# Terminal 1 -- main instance:
+afl-fuzz -M main -i fuzzing/testcase_dir -o fuzzing/sync_dir \
+  -- ./passt.fuzz --foreground
+
+# Terminal 2 -- secondary with different power schedule:
+afl-fuzz -S variant1 -p rare -i fuzzing/testcase_dir \
+  -o fuzzing/sync_dir -- ./passt.fuzz --foreground
+```
+
+### Architecture
+
+The fuzzer uses AFL++ persistent mode with shared memory fuzzing.
+Each iteration:
+
+1. Resets deterministic state (clock, flow table, epoll)
+2. Reads an epoll event and packet data from AFL++ shared memory
+3. For TAP events: injects a packet with fixed L2/L3/L4 headers
+   into the tap pipeline via tap_add_packet() + tap_handler().
+   The TCP destination port is fixed to 9999 (the test server's
+   listening port).
+4. Exchanges a turn flag with fuzz-server for bidirectional flow.
+5. Calls passt_worker() to process the epoll event
+6. Polls for host-side TCP events (connect completion, server data)
+
+The test server connects to passt's UNIX socket (SOCK_SEQPACKET)
+and listens on 127.0.0.1:9999 for TCP connections. It responds to
+ARP requests and TCP SYNs on the UNIX socket, and echoes TCP data
+(XOR'd with AFL++ shared memory) on the loopback side.
+
+Deterministic wrappers in fuzz.c replace clock_gettime(),
+getrandom(), getsockopt(TCP_INFO), and recv/recvmsg/recvfrom/
+recvmmsg to eliminate non-determinism from kernel state. The recv
+wrappers return AFL++ buffer data for non-TAP file descriptors,
+giving the fuzzer control over what passt "receives" from host
+sockets.
+
+### Seed inputs
+
+`testcase_dir/empty.bin` is a 12-byte zero file
+(sizeof(struct epoll_event)). AFL++ discovers packet formats
+through mutation from this minimal seed.
+
+### Reproducing crashes
+
+```
+./passt.fuzz --foreground < \
+  fuzzing/sync_dir/default/crashes/id:000000,...
+```
+
+Minimize a crash input:
+
+```
+afl-tmin -i fuzzing/sync_dir/default/crashes/id:000000,... \
+  -o crash_minimized -- ./passt.fuzz --foreground
+```
diff --git a/fuzzing/testcase_dir/empty.bin b/fuzzing/testcase_dir/empty.bin
new file mode 100644
index 0000000000000000000000000000000000000000..ce58bc9f84b9623e708de4eb8427a57d9f9a160f
GIT binary patch
literal 12
KcmZQzKmY&$3;+QD

literal 0
HcmV?d00001

-- 
2.55.0


      parent reply	other threads:[~2026-08-12  7:27 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-12  7:26 [PATCH 0/5] Add AFL++ fuzzing support for passt Anshu Kumari
2026-08-12  7:26 ` [PATCH 1/5] fuzz: Add deterministic wrappers for system calls Anshu Kumari
2026-08-13  3:46   ` David Gibson
2026-08-12  7:26 ` [PATCH 2/5] fuzz: Add flow type guards for fuzzing stability Anshu Kumari
2026-08-13  4:45   ` David Gibson
2026-08-12  7:26 ` [PATCH 3/5] fuzz: Bypass isolation and adapt sockets for AFL++ Anshu Kumari
2026-08-13  5:04   ` David Gibson
2026-08-12  7:26 ` [PATCH 4/5] fuzz: Add AFL++ persistent mode fuzz loop Anshu Kumari
2026-08-12  7:26 ` Anshu Kumari [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260812072630.3235261-6-anskuma@redhat.com \
    --to=anskuma@redhat.com \
    --cc=abdobngad@gmail.com \
    --cc=aerosound161@gmail.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=lvivier@redhat.com \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).