public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
6366528fb2875ed5c81835d016d743ff41d88aff blob 4210 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
 
// SPDX-License-Identifier: GPL-2.0-or-later

/* fuzz-testbuf.h - AFL++ testcase buffer layout shared between passt
 *                  and the test server.
 *
 * Copyright Red Hat
 * Author: Anshu Kumari <anskuma@redhat.com>
 */

#ifndef FUZZ_TESTBUF_H
#define FUZZ_TESTBUF_H

#include <stdint.h>
#include <string.h>
#include <sys/epoll.h>

/*
 * AFL++ testcase buffer layout
 *
 * Each fuzz iteration receives a single flat buffer split into a
 * fixed 10-byte header followed by four variable-length regions:
 *
 *   Header (FUZZ_HDR_SIZE = 10 bytes):
 *     [0..3]   u32  n_events      number of epoll events
 *     [4..5]   u16  tap_len       bytes of tap (L2 frame) data
 *     [6..7]   u16  testbuf_len   bytes of test-server payload
 *     [8..9]   u16  sockopt_len   bytes of getsockopt() overrides
 *
 *   Payload (starts at offset FUZZ_HDR_SIZE):
 *     (a) events:  n_events * sizeof(struct epoll_event)
 *                  Simulated epoll events consumed by passt.
 *     (b) tap:     tap_len bytes of length-prefixed L2 frames
 *                  injected into passt as tap input.
 *     (c) testbuf: testbuf_len bytes consumed only by the
 *                  test server to send load to passt.
 *     (d) sockopt: sockopt_len bytes of fuzzer-controlled
 *                  TCP_INFO data returned by getsockopt().
 *
 */
#define FUZZ_EV_COUNT_OFF	0
#define FUZZ_TAP_LEN_OFF	4
#define FUZZ_TESTBUF_LEN_OFF	6
#define FUZZ_SOCKOPT_LEN_OFF	8
#define FUZZ_HDR_SIZE		10

#define FUZZ_TAP_MAX		(64 * 1024)
#define FUZZ_TESTBUF_MAX	(64 * 1024)
#define FUZZ_SOCKOPT_MAX	256

/**
 * struct fuzz_layout - testcase layout
 * @n_events:		Number of epoll events in region (a)
 * @tap_off:		Byte offset of region (b) in the testcase
 * @tap_len:		Byte length of region (b)
 * @testbuf_off:	Byte offset of region (c) in the testcase
 * @testbuf_len:	Byte length of region (c)
 * @sockopt_off:	Byte offset of region (d) in the testcase
 * @sockopt_len:	Byte length of region (d)
 */
struct fuzz_layout {
	uint32_t n_events;
	uint32_t tap_off;
	uint32_t tap_len;
	uint32_t testbuf_off;
	uint32_t testbuf_len;
	uint32_t sockopt_off;
	uint32_t sockopt_len;
};

/**
 * fuzz_parse_layout() - Split a testcase into non-overlapping regions
 * @buf:	Raw AFL++ testcase buffer
 * @total_len:	Total byte length of @buf
 *
 * Each AFL++ testcase starts with a 10-byte header that says how
 * large each payload region should be.  This function reads that
 * header and figures out where each region actually starts and
 * ends, making sure nothing runs past the end of the buffer and
 * no two regions overlap.
 *
 * Return: a fuzz_layout with offsets and lengths for every region,
 *         or all zeros if the buffer is too small for the header
 */
static inline struct fuzz_layout fuzz_parse_layout(const uint8_t *buf,
						   uint32_t total_len)
{
	struct fuzz_layout l = { 0 };
	uint32_t raw_n_events;
	uint32_t remaining;
	uint16_t raw16;

	if (total_len < FUZZ_HDR_SIZE)
		return l;

	memcpy(&raw_n_events, buf + FUZZ_EV_COUNT_OFF, sizeof(raw_n_events));

	if (total_len > FUZZ_HDR_SIZE) {
		uint32_t ev_space = total_len - FUZZ_HDR_SIZE;
		uint32_t max_ev = ev_space / sizeof(struct epoll_event);

		l.n_events = raw_n_events > max_ev ? max_ev : raw_n_events;
	}

	l.tap_off = FUZZ_HDR_SIZE + l.n_events * sizeof(struct epoll_event);
	remaining = total_len > l.tap_off ? total_len - l.tap_off : 0;

	memcpy(&raw16, buf + FUZZ_TAP_LEN_OFF, sizeof(raw16));
	l.tap_len = raw16;
	if (l.tap_len > FUZZ_TAP_MAX)
		l.tap_len = FUZZ_TAP_MAX;
	if (l.tap_len > remaining)
		l.tap_len = remaining;
	remaining -= l.tap_len;

	l.testbuf_off = l.tap_off + l.tap_len;
	memcpy(&raw16, buf + FUZZ_TESTBUF_LEN_OFF, sizeof(raw16));
	l.testbuf_len = raw16;
	if (l.testbuf_len > FUZZ_TESTBUF_MAX)
		l.testbuf_len = FUZZ_TESTBUF_MAX;
	if (l.testbuf_len > remaining)
		l.testbuf_len = remaining;
	remaining -= l.testbuf_len;

	l.sockopt_off = l.testbuf_off + l.testbuf_len;
	memcpy(&raw16, buf + FUZZ_SOCKOPT_LEN_OFF, sizeof(raw16));
	l.sockopt_len = raw16;
	if (l.sockopt_len > FUZZ_SOCKOPT_MAX)
		l.sockopt_len = FUZZ_SOCKOPT_MAX;
	if (l.sockopt_len > remaining)
		l.sockopt_len = remaining;

	return l;
}

#endif /* FUZZ_TESTBUF_H */
debug log:

solving 6366528f ...
found 6366528f in https://archives.passt.top/passt-dev/20260928051727.2251281-2-anskuma@redhat.com/

applying [1/1] https://archives.passt.top/passt-dev/20260928051727.2251281-2-anskuma@redhat.com/
diff --git a/fuzz-testbuf.h b/fuzz-testbuf.h
new file mode 100644
index 00000000..6366528f

Checking patch fuzz-testbuf.h...
Applied patch fuzz-testbuf.h cleanly.

index at:
100644 6366528fb2875ed5c81835d016d743ff41d88aff	fuzz-testbuf.h

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