suricata
fuzz_dataset.c
Go to the documentation of this file.
1 /**
2  * @file
3  * @author Philippe Antoine <contact@catenacyber.fr>
4  */
5 
6 #include "suricata-common.h"
7 #include "detect-engine.h"
8 #include "detect-engine-build.h"
9 #include "detect-parse.h"
10 #include "util-fmemopen.h"
11 #include "reputation.h"
12 #include "util-unittest-helper.h"
13 #include "tmqh-packetpool.h"
14 #include "util-conf.h"
15 #include "stream-tcp-private.h"
16 #include "stream-tcp.h"
17 #include "app-layer-parser.h"
18 #include "flow-util.h"
19 #include "flow-worker.h"
20 #include "rust.h"
21 #include "tm-modules.h"
22 #include "datasets.h"
23 #include "util-conf.h"
24 
25 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
26 
28 static int initialized = 0;
33 uint8_t http_buf1[] = "GET /";
34 uint32_t http_len1 = sizeof(http_buf1) - 1;
35 uint8_t http_buf2[] = " HTTP/1.0\r\n"
36  "Host: suricata.fuzz\r\n\r\n";
37 uint32_t http_len2 = sizeof(http_buf2) - 1;
39 SC_ATOMIC_EXTERN(unsigned int, engine_stage);
40 // FlowWorkerThreadData
41 void *fwd;
42 
43 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
44 {
45  if (initialized == 0) {
46  // Redirects logs to /dev/null
47  setenv("SC_LOG_OP_IFACE", "file", 0);
48  setenv("SC_LOG_FILE", "/dev/null", 0);
49 
50  InitGlobal();
51 
54  // redirect logs to /tmp
55  ConfigSetLogDirectory("/tmp/");
56  ConfigSetDataDirectory((char *)"/tmp/");
57 
58  // do not load rules before reproducible DetectEngineReload
59  remove("/tmp/fuzz.rules");
60  surifuzz.sig_file = strdup("/tmp/fuzz.rules");
63 
67 
68  extern uint32_t max_pending_packets;
69  max_pending_packets = 128;
72  SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
74 
75  memset(&f, 0, sizeof(f));
76  memset(&ssn, 0, sizeof(ssn));
77  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
79  f.protoctx = (void *)&ssn;
80  f.proto = IPPROTO_TCP;
81  f.flags |= FLOW_IPV4;
82  p->flow = &f;
87  StreamTcpInitConfig(true);
89  initialized = 1;
90  }
91 
93  p->alerts.cnt = 0;
94  p->action = 0;
95  size_t kw_len = 0;
96  if (size == 0) {
97  return 0;
98  }
99  // First byte/bit : datarep or dataset keyword
100  bool rep = data[0] & 1;
101  data++;
102  size--;
103  // Then split on first ;
104  // Before is the argument in the signature
105  // After is the contents of a dataset file
106  while (kw_len < size && data[kw_len] != ';') {
107  kw_len++;
108  }
109  if (kw_len >= size) {
110  return 0;
111  }
112  // Then split on first null character
113  // Before is the contents of a dataset file
114  // After is the uri to use in the network traffic
115  const uint8_t *dataset_data = data + kw_len + 1;
116  size_t dataset_len = 0;
117  while (kw_len + 1 + dataset_len < size && data[kw_len + 1 + dataset_len] != 0) {
118  dataset_len++;
119  }
120  const uint8_t *uri_data = data + kw_len + 1 + dataset_len + 1;
121  size_t uri_len = 0;
122  if (size > (kw_len + 1 + dataset_len + 1))
123  uri_len = size - (kw_len + 1 + dataset_len + 1);
124 
125  /* Build the full signature string */
126  char sig_buf[DETECT_MAX_RULE_SIZE] = { 0 };
127  size_t sig_len = strlcat(sig_buf, "alert http any any -> any any (http.uri; ", sizeof(sig_buf));
128  if (sig_len + strlen("datarep:") + kw_len + strlen("; sid:1;)") >= DETECT_MAX_RULE_SIZE) {
129  return 0;
130  }
131  if (rep) {
132  sig_len += strlcat(sig_buf + sig_len, "datarep:", sizeof(sig_buf) - sig_len);
133  } else {
134  sig_len += strlcat(sig_buf + sig_len, "dataset:", sizeof(sig_buf) - sig_len);
135  }
136  memcpy(sig_buf + sig_len, data, kw_len);
137  sig_len += kw_len;
138  sig_len += strlcat(sig_buf + sig_len, "; sid:1;)", sizeof(sig_buf) - sig_len);
139 
140  if (TestHelperBufferToFile(surifuzz.sig_file, (const uint8_t *)sig_buf, sig_len) < 0) {
141  return 0;
142  }
143  if (TestHelperBufferToFile("/tmp/dataset.fuzz", dataset_data, dataset_len) < 0) {
144  return 0;
145  }
146 
147  // DetectEngineReload is not enough
148  DatasetsDestroy();
149  DatasetsInit();
150  if (DetectEngineReload(&surifuzz) < 0) {
151  return 0;
152  }
155  de_ctx->ref_cnt--;
157  FlowWorkerReplaceDetectCtx(fwd, new_det_ctx);
158  DetectEngineThreadCtxDeinit(NULL, old_det_ctx);
159 
160  FLOWLOCK_WRLOCK(&f);
161  AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_len1);
162  if (uri_len)
164  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, uri_data, (uint32_t)uri_len);
165  AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf2, http_len2);
166  SigMatchSignatures(th_v, de_ctx, new_det_ctx, p);
168  FLOWLOCK_UNLOCK(&f);
169 
170  return 0;
171 }
http_len1
uint32_t http_len1
Definition: fuzz_dataset.c:34
FlowCleanupAppLayer
void FlowCleanupAppLayer(Flow *f)
Definition: flow.c:139
detect-engine.h
DetectEngineThreadCtxInitForReload
DetectEngineThreadCtx * DetectEngineThreadCtxInitForReload(ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
Definition: detect-engine.c:3718
Flow_::flags
uint64_t flags
Definition: flow.h:404
SURICATA_RUNTIME
@ SURICATA_RUNTIME
Definition: suricata.h:101
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1311
util-fmemopen.h
flow-util.h
stream-tcp.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:1118
Flow_::proto
uint8_t proto
Definition: flow.h:377
PacketAlerts_::cnt
uint16_t cnt
Definition: decode.h:289
Packet_::flags
uint32_t flags
Definition: decode.h:562
ssn
TcpSession ssn
Definition: fuzz_dataset.c:31
Packet_::action
uint8_t action
Definition: decode.h:624
Flow_
Flow data structure.
Definition: flow.h:355
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:987
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_dataset.c:38
DetectEngineGetCurrent
DetectEngineCtx * DetectEngineGetCurrent(void)
Definition: detect-engine.c:4108
PacketAlerts_::alerts
PacketAlert * alerts
Definition: decode.h:293
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:232
rust.h
tm-modules.h
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:243
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:3064
p
Packet * p
Definition: fuzz_dataset.c:30
GlobalsInitPreConfig
void GlobalsInitPreConfig(void)
Definition: suricata.c:413
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:547
Flow_::protoctx
void * protoctx
Definition: flow.h:434
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:100
Packet_::alerts
PacketAlerts alerts
Definition: decode.h:637
tmqh-packetpool.h
util-unittest-helper.h
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:272
PacketPoolInit
void PacketPoolInit(void)
Definition: tmqh-packetpool.c:235
ThreadVarsAlloc
ThreadVars * ThreadVarsAlloc(void)
Allocate a new ThreadVars structure.
Definition: threadvars.c:28
SCRunmodeSet
void SCRunmodeSet(SCRunMode run_mode)
Set the current run mode.
Definition: suricata.c:306
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:498
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
datasets.h
SCRunmodeGet
SCRunMode SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:301
PreRunPostPrivsDropInit
void PreRunPostPrivsDropInit(const int runmode)
Definition: suricata.c:2388
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
DetectEngineThreadCtx_
Definition: detect.h:1306
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
flow-worker.h
FLOWLOCK_WRLOCK
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:269
SCInstance_::delayed_detect
int delayed_detect
Definition: suricata.h:166
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
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
PostConfLoadedSetup
int PostConfLoadedSetup(SCInstance *suri)
Definition: suricata.c:2820
app-layer-parser.h
surifuzz
SCInstance surifuzz
Definition: fuzz_dataset.c:27
DatasetsDestroy
void DatasetsDestroy(void)
Definition: datasets.c:770
SC_ATOMIC_EXTERN
SC_ATOMIC_EXTERN(unsigned int, engine_stage)
http_len2
uint32_t http_len2
Definition: fuzz_dataset.c:37
Packet_
Definition: decode.h:516
PostConfLoadedDetectSetup
void PostConfLoadedDetectSetup(SCInstance *suri)
Definition: suricata.c:2715
detect-engine-build.h
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:29
stream-tcp-private.h
DETECT_MAX_RULE_SIZE
#define DETECT_MAX_RULE_SIZE
Definition: detect.h:46
reputation.h
ConfigSetDataDirectory
TmEcode ConfigSetDataDirectory(char *name)
Definition: util-conf.c:66
setenv
void setenv(const char *name, const char *value, int overwrite)
http_buf2
uint8_t http_buf2[]
Definition: fuzz_dataset.c:35
max_pending_packets
uint32_t max_pending_packets
Definition: suricata.c:187
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:329
TMM_FLOWWORKER
@ TMM_FLOWWORKER
Definition: tm-threads-common.h:34
FlowWorkerGetDetectCtxPtr
void * FlowWorkerGetDetectCtxPtr(void *flow_worker)
Definition: flow-worker.c:743
th_v
ThreadVars * th_v
Definition: fuzz_dataset.c:29
util-conf.h
Packet_::flow
struct Flow_ * flow
Definition: decode.h:564
http_buf1
uint8_t http_buf1[]
Definition: fuzz_dataset.c:33
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1554
suricata-common.h
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3871
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:51
SCInstance_::sig_file
char * sig_file
Definition: suricata.h:139
ConfigSetLogDirectory
TmEcode ConfigSetLogDirectory(const char *name)
Definition: util-conf.c:33
DatasetsInit
int DatasetsInit(void)
Definition: datasets.c:618
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition: fuzz_dataset.c:43
detect-parse.h
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:234
fwd
void * fwd
Definition: fuzz_dataset.c:41
PacketAlertRecycle
void PacketAlertRecycle(PacketAlert *pa_array, uint16_t cnt)
Definition: decode.c:149
DetectEngineReload
int DetectEngineReload(const SCInstance *suri)
Reload the detection engine.
Definition: detect-engine.c:5060
SCInstance_
Definition: suricata.h:134
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:60
InitGlobal
int InitGlobal(void)
Global initialization common to all runmodes.
Definition: suricata.c:3069
SCInstance_::sig_file_exclusive
bool sig_file_exclusive
Definition: suricata.h:140
TcpSession_
Definition: stream-tcp-private.h:283
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:451
RUNMODE_PCAP_FILE
@ RUNMODE_PCAP_FILE
Definition: runmodes.h:30
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1307
FlowWorkerReplaceDetectCtx
void FlowWorkerReplaceDetectCtx(void *flow_worker, void *detect_ctx)
Definition: flow-worker.c:736
f
Flow f
Definition: fuzz_dataset.c:32