suricata
app-layer-htp-mem.c
Go to the documentation of this file.
1 /* Copyright (C) 2013 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  * \ingroup httplayer
20  *
21  * @{
22  */
23 
24 /**
25  * \file
26  *
27  * \author Eric Leblond <eric@regit.org>
28  *
29  * This file provides a memory handling for the HTTP protocol support.
30  */
31 
32 #include "suricata-common.h"
33 #include "suricata.h"
34 
35 #include "conf.h"
36 #include "util-mem.h"
37 #include "util-misc.h"
38 
39 #include "app-layer-htp-mem.h"
40 
41 SC_ATOMIC_DECLARE(uint64_t, htp_config_memcap);
42 SC_ATOMIC_DECLARE(uint64_t, htp_memuse);
43 SC_ATOMIC_DECLARE(uint64_t, htp_memcap);
44 
46 {
47  const char *conf_val;
48 
49  SC_ATOMIC_INIT(htp_config_memcap);
50 
51  /** set config values for memcap, prealloc and hash_size */
52  uint64_t memcap;
53  if ((ConfGet("app-layer.protocols.http.memcap", &conf_val)) == 1)
54  {
55  if (ParseSizeStringU64(conf_val, &memcap) < 0) {
56  SCLogError(SC_ERR_SIZE_PARSE, "Error parsing http.memcap "
57  "from conf file - %s. Killing engine",
58  conf_val);
59  exit(EXIT_FAILURE);
60  } else {
61  SC_ATOMIC_SET(htp_config_memcap, memcap);
62  }
63  SCLogInfo("HTTP memcap: %"PRIu64, SC_ATOMIC_GET(htp_config_memcap));
64  } else {
65  /* default to unlimited */
66  SC_ATOMIC_SET(htp_config_memcap, 0);
67  }
68 
69  SC_ATOMIC_INIT(htp_memuse);
70  SC_ATOMIC_INIT(htp_memcap);
71 }
72 
73 static void HTPIncrMemuse(uint64_t size)
74 {
75  (void) SC_ATOMIC_ADD(htp_memuse, size);
76  return;
77 }
78 
79 static void HTPDecrMemuse(uint64_t size)
80 {
81  (void) SC_ATOMIC_SUB(htp_memuse, size);
82  return;
83 }
84 
85 uint64_t HTPMemuseGlobalCounter(void)
86 {
87  uint64_t tmpval = SC_ATOMIC_GET(htp_memuse);
88  return tmpval;
89 }
90 
91 uint64_t HTPMemcapGlobalCounter(void)
92 {
93  uint64_t tmpval = SC_ATOMIC_GET(htp_memcap);
94  return tmpval;
95 }
96 
97 /**
98  * \brief Check if alloc'ing "size" would mean we're over memcap
99  *
100  * \retval 1 if in bounds
101  * \retval 0 if not in bounds
102  */
103 static int HTPCheckMemcap(uint64_t size)
104 {
105  uint64_t memcapcopy = SC_ATOMIC_GET(htp_config_memcap);
106  if (memcapcopy == 0 || size + SC_ATOMIC_GET(htp_memuse) <= memcapcopy)
107  return 1;
108  (void) SC_ATOMIC_ADD(htp_memcap, 1);
109  return 0;
110 }
111 
112 /**
113  * \brief Update memcap value
114  *
115  * \param size new memcap value
116  */
117 int HTPSetMemcap(uint64_t size)
118 {
119  if (size == 0 || (uint64_t)SC_ATOMIC_GET(htp_memuse) < size) {
120  SC_ATOMIC_SET(htp_config_memcap, size);
121  return 1;
122  }
123  return 0;
124 }
125 
126 /**
127  * \brief Update memcap value
128  *
129  * \retval memcap value
130  */
131 uint64_t HTPGetMemcap(void)
132 {
133  uint64_t memcapcopy = SC_ATOMIC_GET(htp_config_memcap);
134  return memcapcopy;
135 }
136 
137 void *HTPMalloc(size_t size)
138 {
139  void *ptr = NULL;
140 
141  if (HTPCheckMemcap((uint32_t)size) == 0)
142  return NULL;
143 
144  ptr = SCMalloc(size);
145 
146  if (unlikely(ptr == NULL))
147  return NULL;
148 
149  HTPIncrMemuse((uint64_t)size);
150 
151  return ptr;
152 }
153 
154 void *HTPCalloc(size_t n, size_t size)
155 {
156  void *ptr = NULL;
157 
158  if (HTPCheckMemcap((uint32_t)(n * size)) == 0)
159  return NULL;
160 
161  ptr = SCCalloc(n, size);
162 
163  if (unlikely(ptr == NULL))
164  return NULL;
165 
166  HTPIncrMemuse((uint64_t)(n * size));
167 
168  return ptr;
169 }
170 
171 void *HTPRealloc(void *ptr, size_t orig_size, size_t size)
172 {
173  if (size > orig_size) {
174  if (HTPCheckMemcap((uint32_t)(size - orig_size)) == 0)
175  return NULL;
176  }
177 
178  void *rptr = SCRealloc(ptr, size);
179  if (rptr == NULL)
180  return NULL;
181 
182  if (size > orig_size) {
183  HTPIncrMemuse((uint64_t)(size - orig_size));
184  } else {
185  HTPDecrMemuse((uint64_t)(orig_size - size));
186  }
187 
188  return rptr;
189 }
190 
191 void HTPFree(void *ptr, size_t size)
192 {
193  SCFree(ptr);
194 
195  HTPDecrMemuse((uint64_t)size);
196 }
197 
199 {
200  SC_ATOMIC_DESTROY(htp_config_memcap);
201  SC_ATOMIC_DESTROY(htp_memcap);
202  SC_ATOMIC_DESTROY(htp_memuse);
203 }
204 
205 /**
206  * @}
207  */
uint64_t HTPGetMemcap(void)
Update memcap value.
#define unlikely(expr)
Definition: util-optimize.h:35
void HTPParseMemcap()
int HTPSetMemcap(uint64_t size)
Update memcap value.
uint64_t HTPMemuseGlobalCounter(void)
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:107
void * HTPCalloc(size_t n, size_t size)
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:124
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
#define SC_ATOMIC_DESTROY(name)
Destroy the lock used to protect this variable.
Definition: util-atomic.h:97
void * HTPRealloc(void *ptr, size_t orig_size, size_t size)
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it&#39;s lock.
Definition: util-atomic.h:81
#define SCCalloc(nm, a)
Definition: util-mem.h:197
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
uint64_t HTPMemcapGlobalCounter(void)
#define SCRealloc(x, a)
Definition: util-mem.h:182
void HTPFree(void *ptr, size_t size)
#define SCMalloc(a)
Definition: util-mem.h:166
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:207
SC_ATOMIC_DECLARE(uint64_t, htp_config_memcap)
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define SCFree(a)
Definition: util-mem.h:228
void HTPDestroyMemcap(void)
void * HTPMalloc(size_t size)
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:192