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 2/5] fuzz: Add flow type guards for fuzzing stability
Date: Wed, 12 Aug 2026 12:56:25 +0530	[thread overview]
Message-ID: <20260812072630.3235261-3-anskuma@redhat.com> (raw)
In-Reply-To: <20260812072630.3235261-1-anskuma@redhat.com>

Under FUZZING, AFL++ can inject arbitrary epoll event types
from its shared memory buffer. When an event references a flow
table entry whose type doesn't match the handler, the existing
assert() crashes the process eventually masking the real bugs.
If there is no flow at the start of fuzzing then also we are
just returning early instead of hitting crashes. Allowing the
fuzzer to explore other code path.

Replace assert() with NULL returns in the flow-lookup functions
when compiled with -DFUZZING:

- tcp.c: conn_at_sidx(), tcp_timer_handler(), tcp_sock_handler()
- tcp_splice.c: conn_at_sidx(), tcp_splice_sock_handler()
- udp.c: udp_sock_handler(), udp_sock_to_sock(),
  udp_buf_sock_to_tap(), udp_sock_fwd() error path
- udp_flow.c: udp_at_sidx()
- icmp.c: ping_at_sidx(), icmp_sock_handler()

Signed-off-by: Anshu Kumari <anskuma@redhat.com>
---
 icmp.c       | 14 +++++++++++++-
 tcp.c        | 19 ++++++++++++++++++-
 tcp_splice.c | 10 ++++++++++
 udp.c        | 29 +++++++++++++++++++++++++++--
 udp_flow.c   |  5 +++++
 5 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/icmp.c b/icmp.c
index 0fe2366..cdfa253 100644
--- a/icmp.c
+++ b/icmp.c
@@ -39,6 +39,7 @@
 #include "icmp.h"
 #include "flow_table.h"
 #include "epoll_ctl.h"
+#include "fuzz.h"
 
 #define ICMP_ECHO_TIMEOUT	60 /* s, timeout for ICMP socket activity */
 #define ICMP_NUM_IDS		(1U << 16)
@@ -58,7 +59,12 @@ static struct icmp_ping_flow *ping_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
+#ifdef FUZZING
+	if (flow->f.type != FLOW_PING4 && flow->f.type != FLOW_PING6)
+		return NULL;
+#else
 	assert(flow->f.type == FLOW_PING4 || flow->f.type == FLOW_PING6);
+#endif
 	return &flow->ping;
 }
 
@@ -72,7 +78,13 @@ void icmp_sock_handler(const struct ctx *c, union epoll_ref ref,
 		       const struct timespec *now)
 {
 	struct icmp_ping_flow *pingf = ping_at_sidx(ref.flowside);
-	const struct flowside *ini = &pingf->f.side[INISIDE];
+	const struct flowside *ini;
+
+#ifdef FUZZING
+	if (!pingf)
+		return;
+#endif
+	ini = &pingf->f.side[INISIDE];
 	union sockaddr_inany sr;
 	socklen_t sl = sizeof(sr);
 	char buf[USHRT_MAX];
diff --git a/tcp.c b/tcp.c
index 3b78d2e..612c884 100644
--- a/tcp.c
+++ b/tcp.c
@@ -316,6 +316,7 @@
 #include "tcp_buf.h"
 #include "tcp_vu.h"
 #include "epoll_ctl.h"
+#include "fuzz.h"
 
 /*
  * The size of TCP header (including options) is given by doff (Data Offset)
@@ -456,7 +457,12 @@ static struct tcp_tap_conn *conn_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
+#ifdef FUZZING
+	if (flow->f.type != FLOW_TCP)
+		return NULL;
+#else
 	assert(flow->f.type == FLOW_TCP);
+#endif
 	return &flow->tcp;
 }
 
@@ -2681,7 +2687,14 @@ void tcp_timer_handler(const struct ctx *c, union epoll_ref ref,
 		       const struct timespec *now)
 {
 	struct itimerspec check_armed = { { 0 }, { 0 } };
-	struct tcp_tap_conn *conn = &FLOW(ref.flow)->tcp;
+	struct tcp_tap_conn *conn;
+
+#ifdef FUZZING
+	if (ref.flow >= FLOW_MAX ||
+	    FLOW(ref.flow)->f.type != FLOW_TCP)
+		return;
+#endif
+	conn = &FLOW(ref.flow)->tcp;
 
 	assert(!c->no_tcp);
 	assert(conn->f.type == FLOW_TCP);
@@ -2752,6 +2765,10 @@ void tcp_sock_handler(const struct ctx *c, union epoll_ref ref,
 {
 	struct tcp_tap_conn *conn = conn_at_sidx(ref.flowside);
 
+#ifdef FUZZING
+	if (!conn)
+		return;
+#endif
 	assert(!c->no_tcp);
 	assert(pif_at_sidx(ref.flowside) != PIF_TAP);
 
diff --git a/tcp_splice.c b/tcp_splice.c
index 4b01f1a..005ecd1 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -105,7 +105,12 @@ static struct tcp_splice_conn *conn_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
+#ifdef FUZZING
+	if (flow->f.type != FLOW_TCP_SPLICE)
+		return NULL;
+#else
 	assert(flow->f.type == FLOW_TCP_SPLICE);
+#endif
 	return &flow->tcp_splice;
 }
 
@@ -594,6 +599,11 @@ void tcp_splice_sock_handler(struct ctx *c, union epoll_ref ref,
 	struct tcp_splice_conn *conn = conn_at_sidx(ref.flowside);
 	unsigned evsidei = ref.flowside.sidei;
 
+#ifdef FUZZING
+	if (!conn)
+		return;
+#endif
+
 	assert(conn->f.type == FLOW_TCP_SPLICE);
 
 	if (conn->events == SPLICE_CLOSED)
diff --git a/udp.c b/udp.c
index 505e554..9431353 100644
--- a/udp.c
+++ b/udp.c
@@ -118,6 +118,7 @@
 #include "udp_internal.h"
 #include "udp_vu.h"
 #include "epoll_ctl.h"
+#include "fuzz.h"
 
 #define UDP_MAX_FRAMES		32  /* max # of frames to receive at once */
 
@@ -807,9 +808,15 @@ static void udp_sock_to_sock(const struct ctx *c, int from_s, int n,
 	const struct flowside *toside = flowside_at_sidx(tosidx);
 	const struct udp_flow *uflow = udp_at_sidx(tosidx);
 	uint8_t topif = pif_at_sidx(tosidx);
-	int to_s = uflow->s[tosidx.sidei];
+	int to_s;
 	int i;
 
+#ifdef FUZZING
+	if (!uflow)
+		return;
+#endif
+	to_s = uflow->s[tosidx.sidei];
+
 	if ((n = udp_sock_recv(c, from_s, udp_mh_recv, n)) <= 0)
 		return;
 
@@ -836,9 +843,15 @@ static void udp_buf_sock_to_tap(const struct ctx *c, int s, int n,
 {
 	const struct flowside *toside = flowside_at_sidx(tosidx);
 	struct udp_flow *uflow = udp_at_sidx(tosidx);
-	uint8_t *omac = uflow->f.tap_omac;
+	uint8_t *omac;
 	int i;
 
+#ifdef FUZZING
+	if (!uflow)
+		return;
+#endif
+	omac = uflow->f.tap_omac;
+
 	if ((n = udp_sock_recv(c, s, udp_mh_recv, n)) <= 0)
 		return;
 
@@ -901,10 +914,18 @@ void udp_sock_fwd(const struct ctx *c, int s, int rule_hint,
 		} else if (flow_sidx_valid(tosidx)) {
 			struct udp_flow *uflow = udp_at_sidx(tosidx);
 
+#ifdef FUZZING
+			if (!uflow) {
+				discard = true;
+				continue;
+			}
+#endif
+
 			flow_err_ratelimit(
 				uflow, now,
 				"No support for forwarding UDP from %s to %s",
 				pif_name(frompif), pif_name(topif));
+
 			discard = true;
 		} else {
 			warn_ratelimit(now, "Discarding datagram without flow");
@@ -949,6 +970,10 @@ void udp_sock_handler(const struct ctx *c, union epoll_ref ref,
 {
 	struct udp_flow *uflow = udp_at_sidx(ref.flowside);
 
+#ifdef FUZZING
+	if (!uflow)
+		return;
+#endif
 	assert(!c->no_udp && uflow);
 
 	if (events & EPOLLERR) {
diff --git a/udp_flow.c b/udp_flow.c
index f59649f..6c5b010 100644
--- a/udp_flow.c
+++ b/udp_flow.c
@@ -31,7 +31,12 @@ struct udp_flow *udp_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
+#ifdef FUZZING
+	if (flow->f.type != FLOW_UDP)
+		return NULL;
+#else
 	assert(flow->f.type == FLOW_UDP);
+#endif
 	return &flow->udp;
 }
 
-- 
2.55.0


  parent reply	other threads:[~2026-08-12  7:26 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 ` Anshu Kumari [this message]
2026-08-13  4:45   ` [PATCH 2/5] fuzz: Add flow type guards for fuzzing stability 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 ` [PATCH 5/5] fuzz: Add test server for bidirectional protocol fuzzing Anshu Kumari

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-3-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).