suricata
fuzz_sigpcap_aware.c
Go to the documentation of this file.
1 /**
2  * @file
3  * @author Philippe Antoine <contact@catenacyber.fr>
4  * fuzz target for AppLayerProtoDetectGetProto
5  */
6 
7 #include "suricata-common.h"
8 #include "source-pcap-file.h"
9 #include "detect-engine.h"
11 #include "util-reference-config.h"
12 #include "app-layer.h"
13 #include "tm-queuehandlers.h"
14 #include "util-cidr.h"
15 #include "util-profiling.h"
16 #include "util-proto-name.h"
17 #include "detect-engine-tag.h"
19 #include "host-bit.h"
20 #include "ippair-bit.h"
21 #include "app-layer-htp.h"
22 #include "detect-fast-pattern.h"
23 #include "util-unittest-helper.h"
24 #include "conf-yaml-loader.h"
25 #include "pkt-var.h"
26 #include "flow-util.h"
27 #include "flow-worker.h"
28 #include "tm-modules.h"
29 #include "tmqh-packetpool.h"
30 #include "util-conf.h"
31 #include "packet.h"
32 
33 #include <fuzz_pcap.h>
34 
35 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
36 
37 static int initialized = 0;
40 // FlowWorkerThreadData
41 void *fwd;
43 SC_ATOMIC_EXTERN(unsigned int, engine_stage);
44 
45 extern const char *configNoChecksum;
46 
47 static void SigGenerateAware(const uint8_t *data, size_t size, char *r, size_t *len)
48 {
49  *len = snprintf(r, 511, "alert ip any any -> any any (");
50  for (size_t i = 0; i + 1 < size && *len < 511; i++) {
51  if (data[i] & 0x80) {
52  size_t off = (data[i] & 0x7F + ((data[i + 1] & 0xF) << 7)) % (DETECT_TBLSIZE);
53  if (sigmatch_table[off].flags & SIGMATCH_NOOPT ||
54  ((data[i + 1] & 0x80) && sigmatch_table[off].flags & SIGMATCH_OPTIONAL_OPT)) {
55  *len += snprintf(r + *len, 511 - *len, "; %s;", sigmatch_table[off].name);
56  } else {
57  *len += snprintf(r + *len, 511 - *len, "; %s:", sigmatch_table[off].name);
58  }
59  i++;
60  } else {
61  r[*len] = data[i];
62  *len = *len + 1;
63  }
64  }
65  if (*len < 511) {
66  *len += snprintf(r + *len, 511 - *len, ")");
67  } else {
68  r[511] = 0;
69  *len = 511;
70  }
71 }
72 
73 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
74 {
75  FPC_buffer_t pkts;
76  const u_char *pkt;
77  struct pcap_pkthdr header;
78  int r;
79  Packet *p;
80  size_t pos;
81  size_t pcap_cnt = 0;
82 
83  if (initialized == 0) {
84  // Redirects logs to /dev/null
85  setenv("SC_LOG_OP_IFACE", "file", 0);
86  setenv("SC_LOG_FILE", "/dev/null", 0);
87 
88  InitGlobal();
89 
92  // redirect logs to /tmp
93  ConfigSetLogDirectory("/tmp/");
94  // disables checksums validation for fuzzing
96  abort();
97  }
98  // do not load rules before reproducible DetectEngineReload
99  remove("/tmp/fuzz.rules");
100  surifuzz.sig_file = strdup("/tmp/fuzz.rules");
102  // loads rules after init
104 
108 
109  memset(&tv, 0, sizeof(tv));
111  if (tv.flow_queue == NULL)
112  abort();
117 
118  extern uint32_t max_pending_packets;
119  max_pending_packets = 128;
120  PacketPoolInit();
121  SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
122  initialized = 1;
123  }
124 
125  if (size < 1 + FPC0_HEADER_LEN) {
126  return 0;
127  }
128  for (pos = 0; pos < size - FPC0_HEADER_LEN; pos++) {
129  if (data[pos] == 0) {
130  break;
131  }
132  }
133  // initialize FPC with the buffer
134  if (FPC_init(&pkts, data + pos + 1, size - pos - 1) < 0) {
135  return 0;
136  }
137 
138  // dump signatures to a file so as to reuse SigLoadSignatures
139  char sigaware[512];
140  size_t len;
141  SigGenerateAware(data, pos + 1, sigaware, &len);
142  if (TestHelperBufferToFile(surifuzz.sig_file, (uint8_t *)sigaware, len) < 0) {
143  return 0;
144  }
145 
146  if (DetectEngineReload(&surifuzz) < 0) {
147  return 0;
148  }
150 
152  de_ctx->ref_cnt--;
154  FlowWorkerReplaceDetectCtx(fwd, new_det_ctx);
155 
156  DetectEngineThreadCtxDeinit(NULL, old_det_ctx);
157 
158  // loop over packets
159  r = FPC_next(&pkts, &header, &pkt);
160  p = PacketGetFromAlloc();
161  if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
162  goto bail;
163  }
164  p->pkt_src = PKT_SRC_WIRE;
165  p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
166  p->datalink = pkts.datalink;
167  while (r > 0) {
168  if (PacketCopyData(p, pkt, header.caplen) == 0) {
169  // DecodePcapFile
171  if (ecode == TM_ECODE_FAILED) {
172  break;
173  }
174  Packet *extra_p = PacketDequeueNoLock(&tv.decode_pq);
175  while (extra_p != NULL) {
176  PacketFreeOrRelease(extra_p);
177  extra_p = PacketDequeueNoLock(&tv.decode_pq);
178  }
180  extra_p = PacketDequeueNoLock(&tv.decode_pq);
181  while (extra_p != NULL) {
182  PacketFreeOrRelease(extra_p);
183  extra_p = PacketDequeueNoLock(&tv.decode_pq);
184  }
185  }
186  r = FPC_next(&pkts, &header, &pkt);
187  if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
188  goto bail;
189  }
190  PacketRecycle(p);
191  p->pkt_src = PKT_SRC_WIRE;
192  p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
193  p->datalink = pkts.datalink;
194  pcap_cnt++;
195  p->pcap_cnt = pcap_cnt;
196  }
197 bail:
198  PacketFree(p);
199  FlowReset();
200 
201  return 0;
202 }
ThreadVars_::flow_queue
struct FlowQueue_ * flow_queue
Definition: threadvars.h:134
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
DetectEngineThreadCtxInitForReload
DetectEngineThreadCtx * DetectEngineThreadCtxInitForReload(ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
Definition: detect-engine.c:3412
SCRunmodeGet
int SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:260
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:127
PacketFreeOrRelease
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition: decode.c:250
flow-util.h
SC_ATOMIC_EXTERN
SC_ATOMIC_EXTERN(unsigned int, engine_stage)
fwd
void * fwd
Definition: fuzz_sigpcap_aware.c:41
PacketCopyData
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:351
source-pcap-file.h
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
DetectEngineCtx_::ref_cnt
uint32_t ref_cnt
Definition: detect.h:965
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:594
ippair-bit.h
PacketRecycle
void PacketRecycle(Packet *p)
Definition: packet.c:142
tv
ThreadVars tv
Definition: fuzz_sigpcap_aware.c:38
SCRunmodeSet
void SCRunmodeSet(int run_mode)
Set the current run mode.
Definition: suricata.c:265
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1298
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:841
DetectEngineGetCurrent
DetectEngineCtx * DetectEngineGetCurrent(void)
Definition: detect-engine.c:3796
FlowReset
void FlowReset(void)
Definition: flow.c:659
StatsSetupPrivate
int StatsSetupPrivate(ThreadVars *tv)
Definition: counters.c:1204
tm-modules.h
GlobalsInitPreConfig
void GlobalsInitPreConfig(void)
Definition: suricata.c:358
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
tmqh-packetpool.h
util-unittest-helper.h
PacketPoolInit
void PacketPoolInit(void)
Definition: tmqh-packetpool.c:244
Packet_::datalink
int datalink
Definition: decode.h:607
DecodeRegisterPerfCounters
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:602
util-cidr.h
app-layer-htp.h
configNoChecksum
const char * configNoChecksum
Definition: confyaml.c:1
PreRunPostPrivsDropInit
void PreRunPostPrivsDropInit(const int runmode)
Definition: suricata.c:2238
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:51
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1093
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition: fuzz_sigpcap_aware.c:73
Packet_::ts
SCTime_t ts
Definition: decode.h:523
PacketDequeueNoLock
Packet * PacketDequeueNoLock(PacketQueueNoLock *qnl)
Definition: packet-queue.c:208
flow-worker.h
util-reference-config.h
SCInstance_::delayed_detect
int delayed_detect
Definition: suricata.h:149
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:79
SURICATA_RUNTIME
@ SURICATA_RUNTIME
Definition: suricata.h:96
pkt-var.h
TmModule_::Func
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition: tm-modules.h:52
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:193
FlowQueueNew
FlowQueue * FlowQueueNew(void)
Definition: flow-queue.c:35
TestHelperBufferToFile
int TestHelperBufferToFile(const char *name, const uint8_t *data, size_t size)
writes the contents of a buffer into a file
Definition: util-unittest-helper.c:103
ConfYamlLoadString
int ConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:523
PostConfLoadedSetup
int PostConfLoadedSetup(SCInstance *suri)
Definition: suricata.c:2621
detect-engine-tag.h
util-profiling.h
Packet_
Definition: decode.h:475
PostConfLoadedDetectSetup
void PostConfLoadedDetectSetup(SCInstance *suri)
Definition: suricata.c:2530
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:29
conf-yaml-loader.h
TMM_DECODEPCAPFILE
@ TMM_DECODEPCAPFILE
Definition: tm-threads-common.h:41
TmEcode
TmEcode
Definition: tm-threads-common.h:79
util-proto-name.h
setenv
void setenv(const char *name, const char *value, int overwrite)
max_pending_packets
uint32_t max_pending_packets
Definition: suricata.c:180
TMM_FLOWWORKER
@ TMM_FLOWWORKER
Definition: tm-threads-common.h:34
tm-queuehandlers.h
FlowWorkerGetDetectCtxPtr
void * FlowWorkerGetDetectCtxPtr(void *flow_worker)
Definition: flow-worker.c:715
detect-fast-pattern.h
util-conf.h
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3560
packet.h
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
util-classification-config.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_sigpcap_aware.c:39
SCInstance_::sig_file
char * sig_file
Definition: suricata.h:128
SIGMATCH_OPTIONAL_OPT
#define SIGMATCH_OPTIONAL_OPT
Definition: detect.h:1497
ConfigSetLogDirectory
TmEcode ConfigSetLogDirectory(const char *name)
Definition: util-conf.c:33
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:232
DETECT_TBLSIZE
int DETECT_TBLSIZE
Definition: detect-engine-register.c:292
Packet_::pkt_src
uint8_t pkt_src
Definition: decode.h:579
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:931
DecodeThreadVarsAlloc
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:773
ThreadVars_::decode_pq
PacketQueueNoLock decode_pq
Definition: threadvars.h:111
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1488
DetectEngineReload
int DetectEngineReload(const SCInstance *suri)
Reload the detection engine.
Definition: detect-engine.c:4738
SCInstance_
Definition: suricata.h:123
InitGlobal
int InitGlobal(void)
Global initialization common to all runmodes.
Definition: suricata.c:2851
SCInstance_::sig_file_exclusive
bool sig_file_exclusive
Definition: suricata.h:129
RUNMODE_PCAP_FILE
@ RUNMODE_PCAP_FILE
Definition: runmodes.h:30
surifuzz
SCInstance surifuzz
Definition: fuzz_sigpcap_aware.c:42
host-bit.h
detect-engine-threshold.h
FlowWorkerReplaceDetectCtx
void FlowWorkerReplaceDetectCtx(void *flow_worker, void *detect_ctx)
Definition: flow-worker.c:708
app-layer.h