Skip to content

Commit

Permalink
fuzz: improve fuzzers using pl7m (#2486)
Browse files Browse the repository at this point in the history
For some unclear reasons, fuzzers using pl7m create huge corpus,
triggering OOM in oss-fuzz runs (where the memory RSS limit is set to
2560Mb). Example:

```
==25340== ERROR: libFuzzer: out-of-memory (used: 2564Mb; limit: 2560Mb)
To change the out-of-memory limit use -rss_limit_mb=<N>

Live Heap Allocations: 2364004039 bytes in 133791 chunks; quarantined: 60662293 bytes in 3664 chunks; 176432 other chunks; total chunks: 313887; showing top 95% (at most 8 unique contexts)
1285841683 byte(s) (54%) in 2956 allocation(s)
    #0 0x56f814ef4bde in __interceptor_malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x56f814e04416 in operator new(unsigned long) cxa_noexception.cpp:0
    #2 0x56f814de6b2d in assign<unsigned char *, 0> /work/llvm-stage2/runtimes/runtimes-bins/compiler-rt/lib/fuzzer/libcxx_fuzzer_x86_64/include/c++/v1/vector:1443:3
    #3 0x56f814de6b2d in operator= /work/llvm-stage2/runtimes/runtimes-bins/compiler-rt/lib/fuzzer/libcxx_fuzzer_x86_64/include/c++/v1/vector:1412:9
    #4 0x56f814de6b2d in fuzzer::InputCorpus::AddToCorpus(std::__Fuzzer::vector<unsigned char, std::__Fuzzer::allocator<unsigned char>> const&, unsigned long, bool, bool, bool, std::__Fuzzer::chrono::duration<long long, std::__Fuzzer::ratio<1l, 1000000l>>, std::__Fuzzer::vector<unsigned int, std::__Fuzzer::allocator<unsigned int>> const&, fuzzer::DataFlowTrace const&, fuzzer::InputInfo const*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerCorpus.h:221:10
    #5 0x56f814de60e5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:539:16
    #6 0x56f814de7df2 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:829:7
    #7 0x56f814de8127 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:867:3
    #8 0x56f814dd6736 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6
    #9 0x56f814e02c62 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #10 0x7fa11e2c3082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/libc-start.c:308:16

1031350683 byte(s) (43%) in 2468 allocation(s)
    #0 0x56f814ef4bde in __interceptor_malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x56f814e04416 in operator new(unsigned long) cxa_noexception.cpp:0
    #2 0x56f814de6b2d in assign<unsigned char *, 0> /work/llvm-stage2/runtimes/runtimes-bins/compiler-rt/lib/fuzzer/libcxx_fuzzer_x86_64/include/c++/v1/vector:1443:3
    #3 0x56f814de6b2d in operator= /work/llvm-stage2/runtimes/runtimes-bins/compiler-rt/lib/fuzzer/libcxx_fuzzer_x86_64/include/c++/v1/vector:1412:9
    #4 0x56f814de6b2d in fuzzer::InputCorpus::AddToCorpus(std::__Fuzzer::vector<unsigned char, std::__Fuzzer::allocator<unsigned char>> const&, unsigned long, bool, bool, bool, std::__Fuzzer::chrono::duration<long long, std::__Fuzzer::ratio<1l, 1000000l>>, std::__Fuzzer::vector<unsigned int, std::__Fuzzer::allocator<unsigned int>> const&, fuzzer::DataFlowTrace const&, fuzzer::InputInfo const*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerCorpus.h:221:10
    #5 0x56f814de60e5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:539:16
    #6 0x56f814de7635 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19
    #7 0x56f814de8425 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5
    #8 0x56f814dd6736 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6
    #9 0x56f814e02c62 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #10 0x7fa11e2c3082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/libc-start.c:308:16
```

See: https://oss-fuzz.com/testcase-detail/4717811415449600
See: https://oss-fuzz.com/testcase-detail/6164130982068224

Let's *try* the following workaround: set the parameter `-max-len` to
512K, to force the engine to not genereate inputs (i.e. pcap files...)
larger than 512K. Right now the value used is 1MB, i.e the default,
because we have file larger than 1MB in the initial seeds (i.e.
`/tests/pcaps/*`).

Let's hope than having smaller files lead to smaller corpus...

Update pl7m code (fix a Use-of-uninitialized-value error)
  • Loading branch information
IvanNardi committed Jun 29, 2024
1 parent 83e6e75 commit ebcea42
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 14 deletions.
2 changes: 2 additions & 0 deletions fuzz/fuzz_ndpi_reader_pl7m.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[libfuzzer]
max_len=524288
2 changes: 2 additions & 0 deletions fuzz/fuzz_ndpi_reader_pl7m_64k.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[libfuzzer]
max_len=524288
2 changes: 2 additions & 0 deletions fuzz/fuzz_ndpi_reader_pl7m_internal.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[libfuzzer]
max_len=524288
2 changes: 2 additions & 0 deletions fuzz/fuzz_ndpi_reader_pl7m_internal_simplest.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[libfuzzer]
max_len=524288
2 changes: 2 additions & 0 deletions fuzz/fuzz_ndpi_reader_pl7m_simplest.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[libfuzzer]
max_len=524288
35 changes: 21 additions & 14 deletions src/lib/third_party/src/fuzz/pl7m.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
#endif


/* If you want custom memory allocators, you can simply change these defines */
#define pl7m_malloc(size) malloc(size)
#define pl7m_calloc(num, size) calloc(num, size)
#define pl7m_free(p) free(p)



struct gre_header {
#if defined(__LITTLE_ENDIAN_BITFIELD)
u_int16_t rec:3,
Expand Down Expand Up @@ -402,8 +409,8 @@ static int dissect_l3(struct m_pkt *p)
switch (p->l3_proto) {
case ETH_P_IP:
ip4 = (struct ip *)data;
if (ip4->ip_v != 4 ||
data_len < 20 /* min */ ||
if (data_len < 20 /* min */ ||
ip4->ip_v != 4 ||
ip4->ip_hl < 5 ||
data_len < ip4->ip_hl * 4 ||
ntohs(ip4->ip_len) < ip4->ip_hl * 4) {
Expand Down Expand Up @@ -931,12 +938,12 @@ static struct m_pkt *__dup_pkt(struct m_pkt *p)
{
struct m_pkt *n;

n = (struct m_pkt *)malloc(sizeof(struct m_pkt));
n = (struct m_pkt *)pl7m_malloc(sizeof(struct m_pkt));
if (!n)
return NULL;
n->raw_data = (unsigned char *)malloc(MAX_PKT_LENGTH);
n->raw_data = (unsigned char *)pl7m_malloc(MAX_PKT_LENGTH);
if(!n->raw_data) {
free(n);
pl7m_free(n);
return NULL;
}
memcpy(n->raw_data, p->raw_data, p->header.caplen);
Expand All @@ -960,8 +967,8 @@ static struct m_pkt *__dup_pkt(struct m_pkt *p)
}
static void __free_pkt(struct m_pkt *p)
{
free(p->raw_data);
free(p);
pl7m_free(p->raw_data);
pl7m_free(p);
}
static void __add_pkt(struct pl7m_handle *h, struct m_pkt *p,
struct m_pkt *prev, struct m_pkt *next)
Expand Down Expand Up @@ -1023,7 +1030,7 @@ static void __free_m_pkts(struct pl7m_handle *h)
__free_pkt(p);
p = n;
}
free(h);
pl7m_free(h);
}

static struct m_pkt *do_pkt_actions(struct pl7m_handle *h, struct m_pkt *p, struct m_pkt **prev)
Expand Down Expand Up @@ -1167,7 +1174,7 @@ static struct pl7m_handle *__deserialize_from_fd(FILE *fd_in)
return NULL;
}

h = (struct pl7m_handle *)calloc(1, sizeof(struct pl7m_handle));
h = (struct pl7m_handle *)pl7m_calloc(1, sizeof(struct pl7m_handle));
if (!h) {
pcap_close(pcap_h);
return NULL;
Expand All @@ -1183,15 +1190,15 @@ static struct pl7m_handle *__deserialize_from_fd(FILE *fd_in)
/* Ignore current pkt, but keep going */
continue;
}
p = (struct m_pkt *)calloc(sizeof(struct m_pkt), 1);
p = (struct m_pkt *)pl7m_calloc(sizeof(struct m_pkt), 1);
if (!p) {
__free_m_pkts(h);
pcap_close(pcap_h);
return NULL;
}
p->raw_data = (unsigned char *)malloc(MAX_PKT_LENGTH);
p->raw_data = (unsigned char *)pl7m_malloc(MAX_PKT_LENGTH);
if (!p->raw_data) {
free(p);
pl7m_free(p);
__free_m_pkts(h);
pcap_close(pcap_h);
return NULL;
Expand All @@ -1205,8 +1212,8 @@ static struct pl7m_handle *__deserialize_from_fd(FILE *fd_in)
if (rc != 0) {
derr("Error dissect_do\n");
/* Ignore current pkt, but keep going */
free(p->raw_data);
free(p);
pl7m_free(p->raw_data);
pl7m_free(p);
continue;
}

Expand Down

0 comments on commit ebcea42

Please sign in to comment.