suricata
util-spm-mm.c
Go to the documentation of this file.
1 /* Copyright (C) 2024 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  */
22 
23 #include "suricata-common.h"
24 #include "suricata.h"
25 
26 #include "util-spm.h"
27 #include "util-spm-mm.h"
28 
29 #ifdef HAVE_MEMMEM
30 #include "util-debug.h"
31 #include "util-error.h"
32 #include "util-memcpy.h"
33 #include "util-validate.h"
34 
35 /** \param needle lowercase version of the pattern to look for
36  *
37  * Convert haystack data to lowercase before inspecting it with
38  * `memmem`. Do this in a sliding window manner. */
39 static const uint8_t *SCMemimem(const uint8_t *haystack, uint32_t haystack_len,
40  const uint8_t *needle, const uint32_t needle_len)
41 {
42  if (needle_len > haystack_len)
43  return NULL;
44  uint32_t slice_size = MAX(MIN(haystack_len, 128), needle_len * 3);
45  uint8_t slice[slice_size];
46  uint32_t o = 0;
47  do {
48  const uint32_t size = MIN(haystack_len - o, slice_size);
49  MemcpyToLower(slice, haystack + o, size);
50  uint8_t *found = memmem(slice, size, needle, needle_len);
51  if (found) {
52  size_t slice_offset = found - slice;
53  return haystack + (o + slice_offset);
54  }
55  o += (size - (needle_len - 1));
56  } while (o + needle_len <= haystack_len);
57  return NULL;
58 }
59 
60 uint8_t *MMScan(const SpmCtx *ctx, SpmThreadCtx *_thread_ctx, const uint8_t *haystack,
61  uint32_t haystack_len)
62 {
63  const SpmMmCtx *sctx = ctx->ctx;
64 
65  if (sctx->nocase) {
66  return (uint8_t *)SCMemimem(haystack, haystack_len, sctx->needle, sctx->needle_len);
67  } else {
68  return memmem(haystack, haystack_len, sctx->needle, sctx->needle_len);
69  }
70 }
71 
72 static SpmCtx *MMInitCtx(const uint8_t *needle, uint16_t needle_len, int nocase,
73  SpmGlobalThreadCtx *global_thread_ctx)
74 {
75  SpmCtx *ctx = SCCalloc(1, sizeof(SpmCtx));
76  if (ctx == NULL) {
77  SCLogDebug("Unable to alloc SpmCtx.");
78  return NULL;
79  }
80 
81  SpmMmCtx *sctx = SCCalloc(1, sizeof(SpmMmCtx) + needle_len);
82  if (sctx == NULL) {
83  SCFree(ctx);
84  return NULL;
85  }
86 
87  sctx->nocase = nocase;
88  sctx->needle_len = needle_len;
89  if (nocase)
90  MemcpyToLower(sctx->needle, needle, needle_len);
91  else
92  memcpy(sctx->needle, needle, needle_len);
93 
94  ctx->ctx = sctx;
95  ctx->matcher = SPM_MM;
96  return ctx;
97 }
98 
99 static void MMDestroyCtx(SpmCtx *ctx)
100 {
101  if (ctx == NULL) {
102  return;
103  }
104 
105  SpmMmCtx *sctx = ctx->ctx;
106  if (sctx != NULL) {
107  SCFree(sctx);
108  }
109 
110  SCFree(ctx);
111 }
112 
113 static SpmGlobalThreadCtx *MMInitGlobalThreadCtx(void)
114 {
115  SpmGlobalThreadCtx *global_thread_ctx = SCCalloc(1, sizeof(SpmGlobalThreadCtx));
116  if (global_thread_ctx == NULL) {
117  SCLogDebug("Unable to alloc SpmThreadCtx.");
118  return NULL;
119  }
120  global_thread_ctx->matcher = SPM_MM;
121  return global_thread_ctx;
122 }
123 
124 static void MMDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
125 {
126  if (global_thread_ctx == NULL) {
127  return;
128  }
129  SCFree(global_thread_ctx);
130 }
131 
132 static void MMDestroyThreadCtx(SpmThreadCtx *thread_ctx)
133 {
134  if (thread_ctx == NULL) {
135  return;
136  }
137  SCFree(thread_ctx);
138 }
139 
140 static SpmThreadCtx *MMMakeThreadCtx(const SpmGlobalThreadCtx *global_thread_ctx)
141 {
142  SpmThreadCtx *thread_ctx = SCCalloc(1, sizeof(SpmThreadCtx));
143  if (thread_ctx == NULL) {
144  SCLogDebug("Unable to alloc SpmThreadCtx.");
145  return NULL;
146  }
147  thread_ctx->matcher = SPM_MM;
148  return thread_ctx;
149 }
150 #endif /* HAVE_MEMMEM */
151 
152 void SpmMMRegister(void)
153 {
154 #ifdef HAVE_MEMMEM
155  spm_table[SPM_MM].name = "mm";
156  spm_table[SPM_MM].Scan = MMScan;
157  spm_table[SPM_MM].InitCtx = MMInitCtx;
158  spm_table[SPM_MM].DestroyCtx = MMDestroyCtx;
159  spm_table[SPM_MM].InitGlobalThreadCtx = MMInitGlobalThreadCtx;
160  spm_table[SPM_MM].DestroyGlobalThreadCtx = MMDestroyGlobalThreadCtx;
161  spm_table[SPM_MM].MakeThreadCtx = MMMakeThreadCtx;
162  spm_table[SPM_MM].DestroyThreadCtx = MMDestroyThreadCtx;
163 #endif /* HAVE_MEMMEM */
164 }
SpmTableElmt_::Scan
uint8_t *(* Scan)(const SpmCtx *ctx, SpmThreadCtx *thread_ctx, const uint8_t *haystack, uint32_t haystack_len)
Definition: util-spm.h:69
util-spm-mm.h
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
SpmTableElmt_::InitCtx
SpmCtx *(* InitCtx)(const uint8_t *needle, uint16_t needle_len, int nocase, SpmGlobalThreadCtx *g_thread_ctx)
Definition: util-spm.h:66
ctx
struct Thresholds ctx
SpmTableElmt_::name
const char * name
Definition: util-spm.h:61
util-memcpy.h
SpmTableElmt_::MakeThreadCtx
SpmThreadCtx *(* MakeThreadCtx)(const SpmGlobalThreadCtx *g_thread_ctx)
Definition: util-spm.h:64
MIN
#define MIN(x, y)
Definition: suricata-common.h:408
MAX
#define MAX(x, y)
Definition: suricata-common.h:412
util-debug.h
SpmMMRegister
void SpmMMRegister(void)
Definition: util-spm-mm.c:152
util-error.h
SpmTableElmt_::InitGlobalThreadCtx
SpmGlobalThreadCtx *(* InitGlobalThreadCtx)(void)
Definition: util-spm.h:62
SPM_MM
@ SPM_MM
Definition: util-spm.h:32
SpmGlobalThreadCtx_::matcher
uint8_t matcher
Definition: util-spm.h:49
SpmCtx_
Definition: util-spm.h:41
suricata-common.h
SpmTableElmt_::DestroyCtx
void(* DestroyCtx)(SpmCtx *)
Definition: util-spm.h:68
util-spm.h
util-validate.h
SpmGlobalThreadCtx_
Definition: util-spm.h:48
SCFree
#define SCFree(p)
Definition: util-mem.h:61
spm_table
SpmTableElmt spm_table[SPM_TABLE_SIZE]
Definition: util-spm.c:63
suricata.h
SpmThreadCtx_::matcher
uint8_t matcher
Definition: util-spm.h:56
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(SpmThreadCtx *thread_ctx)
Definition: util-spm.h:65
SpmTableElmt_::DestroyGlobalThreadCtx
void(* DestroyGlobalThreadCtx)(SpmGlobalThreadCtx *g_thread_ctx)
Definition: util-spm.h:63
SpmThreadCtx_
Definition: util-spm.h:55