public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Anshu Kumari <anskuma@redhat.com>
To: sbrivio@redhat.com, passt-dev@passt.top
Cc: lvivier@redhat.com, anskuma@redhat.com, abdobngad@gmail.com
Subject: [PATCH v2 3/7] fuzz: Guard protocol handlers against invalid fuzz-injected state
Date: Mon, 28 Sep 2026 10:47:23 +0530	[thread overview]
Message-ID: <20260928051727.2251281-4-anskuma@redhat.com> (raw)
In-Reply-To: <20260928051727.2251281-1-anskuma@redhat.com>

Use fuzz_assert() instead of assert() for flow lookups, add NULL
checks after conn_at_sidx()/udp_at_sidx(), and validate timer
references — all no-ops in non-fuzzing builds.

Signed-off-by: Anshu Kumari <anskuma@redhat.com>
---
 icmp.c       |  8 +++++---
 tap.c        | 13 +++++++++++++
 tcp.c        | 18 ++++++++++++------
 tcp_buf.c    |  1 +
 tcp_splice.c |  4 +++-
 udp.c        | 29 +++++++++++++++++++++--------
 udp_flow.c   |  3 ++-
 util.c       |  1 +
 8 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/icmp.c b/icmp.c
index 0fe23667..539f8e77 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,7 @@ static struct icmp_ping_flow *ping_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
-	assert(flow->f.type == FLOW_PING4 || flow->f.type == FLOW_PING6);
+	fuzz_assert(flow->f.type == FLOW_PING4 || flow->f.type == FLOW_PING6);
 	return &flow->ping;
 }
 
@@ -72,7 +73,7 @@ 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;
 	union sockaddr_inany sr;
 	socklen_t sl = sizeof(sr);
 	char buf[USHRT_MAX];
@@ -82,7 +83,8 @@ void icmp_sock_handler(const struct ctx *c, union epoll_ref ref,
 	if (c->no_icmp)
 		return;
 
-	assert(pingf);
+	fuzz_assert(pingf);
+	ini = &pingf->f.side[INISIDE];
 
 	n = recvfrom(ref.fd, buf, sizeof(buf), 0, &sr.sa, &sl);
 	if (n < 0) {
diff --git a/tap.c b/tap.c
index dfa66c71..b8e6b61f 100644
--- a/tap.c
+++ b/tap.c
@@ -14,6 +14,7 @@
  */
 
 #include <sched.h>
+#include <time.h>
 #include <unistd.h>
 #include <signal.h>
 #include <stdio.h>
@@ -61,6 +62,7 @@
 #include "vhost_user.h"
 #include "vu_common.h"
 #include "epoll_ctl.h"
+#include "fuzz.h"
 
 /* Maximum allowed frame lengths (including L2 header) */
 
@@ -512,6 +514,9 @@ size_t tap_send_frames(const struct ctx *c, const struct iovec *iov,
 {
 	size_t m;
 
+#ifdef FUZZING
+	return nframes;
+#endif
 	if (c->fd_tap == -1)
 		return nframes;
 
@@ -1229,6 +1234,10 @@ static void tap_passt_input(struct ctx *c, const struct timespec *now)
 	ssize_t n;
 	char *p;
 
+#ifdef FUZZING
+	partial_frame = NULL;
+	partial_len = 0;
+#endif
 	tap_flush_pools();
 
 	if (partial_len) {
@@ -1412,6 +1421,10 @@ static void tap_sock_unix_init(const struct ctx *c)
  */
 bool tap_is_ready(const struct ctx *c)
 {
+#ifdef FUZZING
+	(void)c;
+	return true;
+#endif
 	if (c->fd_tap < 0)
 		return false;
 
diff --git a/tcp.c b/tcp.c
index 3b78d2ed..f491264d 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,7 @@ static struct tcp_tap_conn *conn_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
-	assert(flow->f.type == FLOW_TCP);
+	fuzz_assert(flow->f.type == FLOW_TCP);
 	return &flow->tcp;
 }
 
@@ -2606,7 +2607,7 @@ void tcp_listen_handler(const struct ctx *c, union epoll_ref ref,
 	union flow *flow;
 	int s;
 
-	assert(!c->no_tcp);
+	fuzz_assert(!c->no_tcp);
 
 	if (!(flow = flow_alloc()))
 		return;
@@ -2681,7 +2682,11 @@ 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;
+
+	fuzz_assert(ref.flow < FLOW_MAX);
+	fuzz_assert(FLOW(ref.flow)->f.type == FLOW_TCP);
+	conn = &FLOW(ref.flow)->tcp;
 
 	assert(!c->no_tcp);
 	assert(conn->f.type == FLOW_TCP);
@@ -2752,8 +2757,9 @@ void tcp_sock_handler(const struct ctx *c, union epoll_ref ref,
 {
 	struct tcp_tap_conn *conn = conn_at_sidx(ref.flowside);
 
-	assert(!c->no_tcp);
-	assert(pif_at_sidx(ref.flowside) != PIF_TAP);
+	fuzz_assert(!c->no_tcp);
+	fuzz_assert(conn);
+	fuzz_assert(pif_at_sidx(ref.flowside) != PIF_TAP);
 
 	if (conn->events == CLOSED)
 		return;
@@ -2939,7 +2945,7 @@ static void tcp_get_rto_params(struct ctx *c)
  */
 int tcp_init(struct ctx *c)
 {
-	assert(!c->no_tcp);
+	fuzz_assert(!c->no_tcp);
 
 	tcp_get_rto_params(c);
 
diff --git a/tcp_buf.c b/tcp_buf.c
index 72c45412..eb28abeb 100644
--- a/tcp_buf.c
+++ b/tcp_buf.c
@@ -32,6 +32,7 @@
 #include "tcp_conn.h"
 #include "tcp_internal.h"
 #include "tcp_buf.h"
+#include "fuzz.h"
 
 #define TCP_FRAMES_MEM			128
 #define TCP_FRAMES							   \
diff --git a/tcp_splice.c b/tcp_splice.c
index 4b01f1aa..f688dbdf 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -56,6 +56,7 @@
 #include "inany.h"
 #include "flow.h"
 #include "epoll_ctl.h"
+#include "fuzz.h"
 
 #include "flow_table.h"
 
@@ -105,7 +106,7 @@ static struct tcp_splice_conn *conn_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
-	assert(flow->f.type == FLOW_TCP_SPLICE);
+	fuzz_assert(flow->f.type == FLOW_TCP_SPLICE);
 	return &flow->tcp_splice;
 }
 
@@ -594,6 +595,7 @@ 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;
 
+	fuzz_assert(conn);
 	assert(conn->f.type == FLOW_TCP_SPLICE);
 
 	if (conn->events == SPLICE_CLOSED)
diff --git a/udp.c b/udp.c
index 505e5540..198ec4da 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 */
 
@@ -629,7 +630,7 @@ static int udp_sock_recverr(const struct ctx *c, int s, flow_sidx_t sidx,
 	}
 
 	uflow = udp_at_sidx(sidx);
-	assert(uflow);
+	fuzz_assert(uflow);
 	fromside = &uflow->f.side[sidx.sidei];
 	toside = &uflow->f.side[!sidx.sidei];
 	topif = uflow->f.pif[!sidx.sidei];
@@ -698,7 +699,8 @@ static int udp_sock_errs(const struct ctx *c, int s, flow_sidx_t sidx,
 	socklen_t errlen;
 	int rc, err;
 
-	assert(!c->no_udp);
+	fuzz_assert(!c->no_udp);
+	fuzz_assert(uflow);
 
 	/* Empty the error queue */
 	while ((rc = udp_sock_recverr(c, s, sidx, pif, port, now)) > 0)
@@ -780,7 +782,7 @@ static int udp_peek_addr(int s, union sockaddr_inany *src,
  */
 static int udp_sock_recv(const struct ctx *c, int s, struct mmsghdr *mmh, int n)
 {
-	assert(!c->no_udp);
+	fuzz_assert(!c->no_udp);
 
 	n = recvmmsg(s, mmh, n, 0, NULL);
 	if (n < 0) {
@@ -807,9 +809,12 @@ 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;
 
+	fuzz_assert(toside && uflow);
+	to_s = uflow->s[tosidx.sidei];
+
 	if ((n = udp_sock_recv(c, from_s, udp_mh_recv, n)) <= 0)
 		return;
 
@@ -836,9 +841,12 @@ 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;
 
+	fuzz_assert(toside && uflow);
+	omac = uflow->f.tap_omac;
+
 	if ((n = udp_sock_recv(c, s, udp_mh_recv, n)) <= 0)
 		return;
 
@@ -884,6 +892,9 @@ void udp_sock_fwd(const struct ctx *c, int s, int rule_hint,
 				    pif_name(frompif), port);
 				/* FIXME: what now?  close/re-open socket? */
 			}
+#ifdef FUZZING
+			break;
+#endif
 			continue;
 		}
 
@@ -901,10 +912,12 @@ 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);
 
+			fuzz_assert(uflow);
 			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,7 +962,7 @@ void udp_sock_handler(const struct ctx *c, union epoll_ref ref,
 {
 	struct udp_flow *uflow = udp_at_sidx(ref.flowside);
 
-	assert(!c->no_udp && uflow);
+	fuzz_assert(!c->no_udp && uflow);
 
 	if (events & EPOLLERR) {
 		if (udp_sock_errs(c, ref.fd, ref.flowside,
@@ -1034,7 +1047,7 @@ int udp_tap_handler(const struct ctx *c, uint8_t pif,
 	in_port_t src, dst;
 	uint8_t topif;
 
-	assert(!c->no_udp);
+	fuzz_assert(!c->no_udp);
 
 	if (!packet_get(p, idx, &data))
 		return 1;
@@ -1183,7 +1196,7 @@ static void udp_get_timeout_params(struct ctx *c)
  */
 int udp_init(struct ctx *c)
 {
-	assert(!c->no_udp);
+	fuzz_assert(!c->no_udp);
 
 	udp_get_timeout_params(c);
 
diff --git a/udp_flow.c b/udp_flow.c
index f59649f6..7500be14 100644
--- a/udp_flow.c
+++ b/udp_flow.c
@@ -16,6 +16,7 @@
 #include "flow_table.h"
 #include "udp_internal.h"
 #include "epoll_ctl.h"
+#include "fuzz.h"
 
 /**
  * udp_at_sidx() - Get UDP specific flow at given sidx
@@ -31,7 +32,7 @@ struct udp_flow *udp_at_sidx(flow_sidx_t sidx)
 	if (!flow)
 		return NULL;
 
-	assert(flow->f.type == FLOW_UDP);
+	fuzz_assert(flow->f.type == FLOW_UDP);
 	return &flow->udp;
 }
 
diff --git a/util.c b/util.c
index 28c32e43..a5e23299 100644
--- a/util.c
+++ b/util.c
@@ -36,6 +36,7 @@
 #include "epoll_ctl.h"
 #include "pasta.h"
 #include "serialise.h"
+#include "fuzz.h"
 #ifdef HAS_GETRANDOM
 #include <sys/random.h>
 #endif
-- 
2.55.0


  parent reply	other threads:[~2026-09-28  5:17 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-28  5:17 [PATCH v2 0/7] Add AFL++ fuzzing support for passt Anshu Kumari
2026-09-28  5:17 ` [PATCH v2 1/7] fuzz: Add AFL++ shared memory testcase buffer layout Anshu Kumari
2026-09-28  5:17 ` [PATCH v2 2/7] fuzz: Add deterministic wrappers for assert, clock and getsockopt Anshu Kumari
2026-09-28  5:17 ` Anshu Kumari [this message]
2026-09-28  5:17 ` [PATCH v2 4/7] fuzz: Bypass sandboxing for fuzzing builds Anshu Kumari
2026-09-28  5:17 ` [PATCH v2 5/7] fuzz: Add AFL++ persistent mode fuzz loop Anshu Kumari
2026-09-28  5:17 ` [PATCH v2 6/7] fuzz: Add host-side test server for bidirectional fuzzing Anshu Kumari
2026-09-28  5:17 ` [PATCH v2 7/7] fuzz: Add build targets, namespace setup and documentation 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=20260928051727.2251281-4-anskuma@redhat.com \
    --to=anskuma@redhat.com \
    --cc=abdobngad@gmail.com \
    --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).