suricata
fuzz_sigpcap.c
Go to the documentation of this file.
1/**
2 * @file
3 * @author Philippe Antoine <contact@catenacyber.fr>
4 * fuzz target for signature file and pcap file
5 */
6
7#include "suricata-common.h"
8#include "source-pcap-file.h"
9#include "detect-engine.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"
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-file.h"
31#include "util-conf.h"
32#include "packet.h"
33
34int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
35
36
37static int initialized = 0;
40//FlowWorkerThreadData
41void *fwd;
43SC_ATOMIC_EXTERN(unsigned int, engine_stage);
44
45extern const char *configNoChecksum;
46
47int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
48{
49 pcap_t * pkts;
50 char errbuf[PCAP_ERRBUF_SIZE];
51 const u_char *pkt;
52 struct pcap_pkthdr *header;
53 int r;
54 Packet *p;
55 size_t pos;
56 size_t pcap_cnt = 0;
57
58 if (initialized == 0) {
59 //Redirects logs to /dev/null
60 setenv("SC_LOG_OP_IFACE", "file", 0);
61 setenv("SC_LOG_FILE", "/dev/null", 0);
62
63 InitGlobal();
64
67 //redirect logs to /tmp
68 ConfigSetLogDirectory("/tmp/");
69 //disables checksums validation for fuzzing
71 abort();
72 }
73 // do not load rules before reproducible DetectEngineReload
74 remove("/tmp/fuzz.rules");
75 surifuzz.sig_file = strdup("/tmp/fuzz.rules");
77 //loads rules after init
79
83
84 memset(&tv, 0, sizeof(tv));
86 if (tv.flow_queue == NULL)
87 abort();
92
93 extern uint32_t max_pending_packets;
96 SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
97 initialized = 1;
98 }
99
100 /* TODO add yaml config
101 for (pos = 0; pos < size; pos++) {
102 if (data[pos] == 0) {
103 break;
104 }
105 }
106 if (SCConfYamlLoadString(data, pos) != 0) {
107 return 0;
108 }
109 if (pos < size) {
110 //skip zero
111 pos++;
112 }
113 data += pos;
114 size -= pos;*/
115
116 for (pos=0; pos < size; pos++) {
117 if (data[pos] == 0) {
118 break;
119 }
120 }
121 if (pos > 0 && pos < size) {
122 // dump signatures to a file so as to reuse SigLoadSignatures
123 if (TestHelperBufferToFile(surifuzz.sig_file, data, pos-1) < 0) {
124 return 0;
125 }
126 } else {
127 if (TestHelperBufferToFile(surifuzz.sig_file, data, pos) < 0) {
128 return 0;
129 }
130 }
131
132 if (DetectEngineReload(&surifuzz) < 0) {
133 return 0;
134 }
136
138 de_ctx->ref_cnt--;
140 FlowWorkerReplaceDetectCtx(fwd, new_det_ctx);
141
142 DetectEngineThreadCtxDeinit(NULL, old_det_ctx);
143
144 if (pos < size) {
145 //skip zero
146 pos++;
147 }
148 data += pos;
149 size -= pos;
150
151 //rewrite buffer to a file as libpcap does not have buffer inputs
152 if (TestHelperBufferToFile("/tmp/fuzz.pcap", data, size) < 0) {
153 return 0;
154 }
155
156 //initialize structure
157 pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
158 if (pkts == NULL) {
159 return 0;
160 }
161
162 //loop over packets
163 r = pcap_next_ex(pkts, &header, &pkt);
164 p = PacketGetFromAlloc();
165 if (r <= 0 || header->ts.tv_sec >= INT_MAX - 3600 || header->ts.tv_usec < 0) {
166 goto bail;
167 }
168 p->ts = SCTIME_FROM_TIMEVAL(&header->ts);
169 p->datalink = pcap_datalink(pkts);
171 while (r > 0) {
172 if (PacketCopyData(p, pkt, header->caplen) == 0) {
173 // DecodePcapFile
175 if (ecode == TM_ECODE_FAILED) {
176 break;
177 }
179 while (extra_p != NULL) {
180 PacketFreeOrRelease(extra_p);
181 extra_p = PacketDequeueNoLock(&tv.decode_pq);
182 }
184 extra_p = PacketDequeueNoLock(&tv.decode_pq);
185 while (extra_p != NULL) {
186 PacketFreeOrRelease(extra_p);
187 extra_p = PacketDequeueNoLock(&tv.decode_pq);
188 }
189 }
190 r = pcap_next_ex(pkts, &header, &pkt);
191 if (r <= 0 || header->ts.tv_sec >= INT_MAX - 3600 || header->ts.tv_usec < 0) {
192 goto bail;
193 }
194 PacketRecycle(p);
195 p->ts = SCTIME_FROM_TIMEVAL(&header->ts);
196 p->datalink = pcap_datalink(pkts);
198 pcap_cnt++;
199 p->pcap_cnt = pcap_cnt;
200 }
201bail:
202 //close structure
203 pcap_close(pkts);
204 PacketFree(p);
205 FlowReset();
206
207 return 0;
208}
int SCConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
int StatsSetupPrivate(ThreadVars *tv)
Definition counters.c:1209
@ PKT_SRC_WIRE
Definition decode.h:52
int DetectEngineReload(const SCInstance *suri)
Reload the detection engine.
DetectEngineCtx * DetectEngineGetCurrent(void)
DetectEngineThreadCtx * DetectEngineThreadCtxInitForReload(ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
FlowQueue * FlowQueueNew(void)
Definition flow-queue.c:35
void FlowWorkerReplaceDetectCtx(void *flow_worker, void *detect_ctx)
void * FlowWorkerGetDetectCtxPtr(void *flow_worker)
void FlowReset(void)
Definition flow.c:673
DetectEngineCtx * de_ctx
DecodeThreadVars * dtv
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
const char * configNoChecksum
Definition confyaml.c:1
ThreadVars tv
SCInstance surifuzz
void * fwd
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition decode.c:628
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition decode.c:804
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition decode.c:258
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition decode.c:377
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition decode.c:276
void PacketFree(Packet *p)
Return a malloced packet.
Definition decode.c:219
Packet * PacketDequeueNoLock(PacketQueueNoLock *qnl)
void PacketRecycle(Packet *p)
Definition packet.c:150
uint32_t max_pending_packets
Definition suricata.c:183
@ RUNMODE_PCAP_FILE
Definition runmodes.h:30
uint64_t ts
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
main detection engine ctx
Definition detect.h:932
uint32_t ref_cnt
Definition detect.h:1056
uint64_t pcap_cnt
Definition decode.h:626
SCTime_t ts
Definition decode.h:555
uint8_t pkt_src
Definition decode.h:611
int datalink
Definition decode.h:639
char * sig_file
Definition suricata.h:138
bool sig_file_exclusive
Definition suricata.h:139
int delayed_detect
Definition suricata.h:165
Per thread variable structure.
Definition threadvars.h:58
PacketQueueNoLock decode_pq
Definition threadvars.h:112
struct FlowQueue_ * flow_queue
Definition threadvars.h:135
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition tm-modules.h:56
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition tm-modules.h:51
int InitGlobal(void)
Global initialization common to all runmodes.
Definition suricata.c:2965
void PostConfLoadedDetectSetup(SCInstance *suri)
Definition suricata.c:2625
void PreRunPostPrivsDropInit(const int runmode)
Definition suricata.c:2315
SCRunMode SCRunmodeGet(void)
Get the current run mode.
Definition suricata.c:279
void SCRunmodeSet(SCRunMode run_mode)
Set the current run mode.
Definition suricata.c:284
void GlobalsInitPreConfig(void)
Definition suricata.c:382
int PostConfLoadedSetup(SCInstance *suri)
Definition suricata.c:2716
@ SURICATA_RUNTIME
Definition suricata.h:101
TmModule tmm_modules[TMM_SIZE]
Definition tm-modules.c:29
@ TMM_FLOWWORKER
@ TMM_DECODEPCAPFILE
@ TM_ECODE_FAILED
void PacketPoolInit(void)
#define SC_ATOMIC_EXTERN(type, name)
wrapper for referencing an atomic variable declared on another file.
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
TmEcode ConfigSetLogDirectory(const char *name)
Definition util-conf.c:33
#define SCTIME_FROM_TIMEVAL(tv)
Definition util-time.h:79
int TestHelperBufferToFile(const char *name, const uint8_t *data, size_t size)
writes the contents of a buffer into a file
void setenv(const char *name, const char *value, int overwrite)