Skip to content

Commit 2811614

Browse files
morehouserustyrussell
authored andcommitted
fuzz: don't fail when fuzzer generates valid Act 1 or 2 packets
The handshake targets were based on a false premise: that it is impossible for any fuzzer to generate valid Act 1 or 2 packets. Niklas Gogge proved this premise incorrect using AFL++ with the CMPLOG feature, which enabled AFL++ to generate such valid packets. We modify the targets to allow the scenario where the fuzzer finds these valid packets and add the inputs AFL++ found to the corpus.
1 parent 2b5140f commit 2811614

6 files changed

+32
-10
lines changed

tests/fuzz/fuzz-connectd-handshake-act1.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
* The expected sequence of events for this test is:
55
* 1. responder calls io_read() for the Act 1 packet
66
* - we inject the fuzzer-generated packet
7-
* 2. responder fails to validate the packet
7+
* 2. if packet is valid, responder calls io_write() with an Act 2 packet
8+
* - we fail the handshake
89
*/
910
#include "config.h"
1011
#include <assert.h>
@@ -15,14 +16,22 @@
1516

1617
/* The io_write() interceptor.
1718
*
18-
* The handshake should fail during Act 1 packet validation, so this should
19-
* never be called. */
19+
* If the fuzzer-generated Act 1 packet was valid, this should be called exactly
20+
* once. Otherwise it should not be called at all. */
2021
static struct io_plan *
2122
test_write(struct io_conn *conn, const void *data, size_t len,
2223
struct io_plan *(*next)(struct io_conn *, struct handshake *),
2324
struct handshake *h)
2425
{
25-
assert(false && "unexpected call to io_write()");
26+
++write_count;
27+
assert(write_count == 1 && "too many calls to io_write()");
28+
29+
/* Act 1 packet validation succeeded. Responder is sending the Act 2
30+
* packet. Check that it is initialized. */
31+
assert(len == ACT_TWO_SIZE);
32+
memcheck(data, len);
33+
34+
return handshake_failed(conn, h);
2635
}
2736

2837
/* The io_read() interceptor.

tests/fuzz/fuzz-connectd-handshake-act2.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
* - we discard the valid Act 1 packet
77
* 2. initiator calls io_read() for the Act 2 packet
88
* - we inject the fuzzer-generated packet
9-
* 3. initiator fails to validate the packet
9+
* 3. if packet is valid, initiator calls io_write() with an Act 3 packet
10+
* - we fail the handshake
1011
*/
1112
#include "config.h"
1213
#include <assert.h>
@@ -18,20 +19,32 @@
1819

1920
/* The io_write() interceptor.
2021
*
21-
* This should be called exactly once, when the initiator is writing out its Act
22-
* 1 packet. We check that the packet is initialized and discard it. */
22+
* If the fuzzer-generated Act 2 packet was invalid, this should be called
23+
* exactly once, when the initiator is writing out its Act 1 packet. Otherwise,
24+
* if the Act 2 packet was valid, this should be called a second time, when the
25+
* initiator is writing out its Act 3 packet. */
2326
static struct io_plan *
2427
test_write(struct io_conn *conn, const void *data, size_t len,
2528
struct io_plan *(*next)(struct io_conn *, struct handshake *),
2629
struct handshake *h)
2730
{
2831
++write_count;
29-
assert(write_count == 1 && "too many calls to io_write()");
32+
if (write_count == 1) {
33+
/* Initiator is sending the Act 1 packet. Check that it is
34+
* initialized and discard it. */
35+
assert(len == ACT_ONE_SIZE);
36+
memcheck(data, len);
3037

31-
assert(len == ACT_ONE_SIZE);
38+
return next(conn, h);
39+
}
40+
assert(write_count == 2 && "too many calls to io_write()");
41+
42+
/* Act 2 packet validation succeeded. Initiator is sending the Act 3
43+
* packet. Check that it is initialized. */
44+
assert(len == ACT_THREE_SIZE);
3245
memcheck(data, len);
3346

34-
return next(conn, h);
47+
return handshake_failed(conn, h);
3548
}
3649

3750
/* The io_read() interceptor.

0 commit comments

Comments
 (0)