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 "app-layer-htp-mem.h"
34 
35 #include "conf.h"
36 #include "util-misc.h"
37 #include "util-debug.h"
38 
39 SC_ATOMIC_DECLARE(uint64_t, htp_config_memcap);
40 SC_ATOMIC_DECLARE(uint64_t, htp_memuse);
41 SC_ATOMIC_DECLARE(uint64_t, htp_memcap);
42 
43 void HTPParseMemcap(void)
44 {
45  const char *conf_val;
46 
47  SC_ATOMIC_INIT(htp_config_memcap);
48 
49  /** set config values for memcap, prealloc and hash_size */
50  uint64_t memcap;
51  if ((ConfGet("app-layer.protocols.http.memcap", &conf_val)) == 1)
52  {
53  if (ParseSizeStringU64(conf_val, &memcap) < 0) {
54  SCLogError("Error parsing http.memcap "
55  "from conf file - %s. Killing engine",
56  conf_val);
57  exit(EXIT_FAILURE);
58  } else {
59  SC_ATOMIC_SET(htp_config_memcap, memcap);
60  }
61  SCLogInfo("HTTP memcap: %"PRIu64, SC_ATOMIC_GET(htp_config_memcap));
62  } else {
63  /* default to unlimited */
64  SC_ATOMIC_SET(htp_config_memcap, 0);
65  }
66 
67  SC_ATOMIC_INIT(htp_memuse);
68  SC_ATOMIC_INIT(htp_memcap);
69 }
70 
71 static void HTPIncrMemuse(uint64_t size)
72 {
73  (void)SC_ATOMIC_ADD(htp_memuse, size);
74 }
75 
76 static void HTPDecrMemuse(uint64_t size)
77 {
78  (void)SC_ATOMIC_SUB(htp_memuse, size);
79 }
80 
81 uint64_t HTPMemuseGlobalCounter(void)
82 {
83  uint64_t tmpval = SC_ATOMIC_GET(htp_memuse);
84  return tmpval;
85 }
86 
87 uint64_t HTPMemcapGlobalCounter(void)
88 {
89  uint64_t tmpval = SC_ATOMIC_GET(htp_memcap);
90  return tmpval;
91 }
92 
93 /**
94  * \brief Check if alloc'ing "size" would mean we're over memcap
95  *
96  * \retval 1 if in bounds
97  * \retval 0 if not in bounds
98  */
99 static int HTPCheckMemcap(uint64_t size)
100 {
101  uint64_t memcapcopy = SC_ATOMIC_GET(htp_config_memcap);
102  if (memcapcopy == 0 || size + SC_ATOMIC_GET(htp_memuse) <= memcapcopy)
103  return 1;
104  (void) SC_ATOMIC_ADD(htp_memcap, 1);
105  return 0;
106 }
107 
108 /**
109  * \brief Update memcap value
110  *
111  * \param size new memcap value
112  */
113 int HTPSetMemcap(uint64_t size)
114 {
115  if (size == 0 || (uint64_t)SC_ATOMIC_GET(htp_memuse) < size) {
116  SC_ATOMIC_SET(htp_config_memcap, size);
117  return 1;
118  }
119  return 0;
120 }
121 
122 /**
123  * \brief Update memcap value
124  *
125  * \retval memcap value
126  */
127 uint64_t HTPGetMemcap(void)
128 {
129  uint64_t memcapcopy = SC_ATOMIC_GET(htp_config_memcap);
130  return memcapcopy;
131 }
132 
133 void *HTPMalloc(size_t size)
134 {
135  void *ptr = NULL;
136 
137  if (HTPCheckMemcap((uint32_t)size) == 0) {
139  return NULL;
140  }
141 
142  ptr = SCMalloc(size);
143 
144  if (unlikely(ptr == NULL)) {
146  return NULL;
147  }
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) {
160  return NULL;
161  }
162 
163  ptr = SCCalloc(n, size);
164 
165  if (unlikely(ptr == NULL)) {
167  return NULL;
168  }
169 
170  HTPIncrMemuse((uint64_t)(n * size));
171 
172  return ptr;
173 }
174 
175 void *HTPRealloc(void *ptr, size_t orig_size, size_t size)
176 {
177  if (size > orig_size) {
178  if (HTPCheckMemcap((uint32_t)(size - orig_size)) == 0) {
180  return NULL;
181  }
182  }
183 
184  void *rptr = SCRealloc(ptr, size);
185  if (rptr == NULL) {
187  return NULL;
188  }
189 
190  if (size > orig_size) {
191  HTPIncrMemuse((uint64_t)(size - orig_size));
192  } else {
193  HTPDecrMemuse((uint64_t)(orig_size - size));
194  }
195 
196  return rptr;
197 }
198 
199 void HTPFree(void *ptr, size_t size)
200 {
201  SCFree(ptr);
202 
203  HTPDecrMemuse((uint64_t)size);
204 }
205 
206 /**
207  * @}
208  */
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:190
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
HTPRealloc
void * HTPRealloc(void *ptr, size_t orig_size, size_t size)
Definition: app-layer-htp-mem.c:175
HTPMemuseGlobalCounter
uint64_t HTPMemuseGlobalCounter(void)
Definition: app-layer-htp-mem.c:81
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(uint64_t, htp_config_memcap)
SC_ELIMIT
@ SC_ELIMIT
Definition: util-error.h:31
HTPParseMemcap
void HTPParseMemcap(void)
Definition: app-layer-htp-mem.c:43
HTPSetMemcap
int HTPSetMemcap(uint64_t size)
Update memcap value.
Definition: app-layer-htp-mem.c:113
SC_ENOMEM
@ SC_ENOMEM
Definition: util-error.h:29
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
util-debug.h
HTPGetMemcap
uint64_t HTPGetMemcap(void)
Update memcap value.
Definition: app-layer-htp-mem.c:127
HTPCalloc
void * HTPCalloc(size_t n, size_t size)
Definition: app-layer-htp-mem.c:154
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:341
conf.h
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
suricata-common.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
HTPMemcapGlobalCounter
uint64_t HTPMemcapGlobalCounter(void)
Definition: app-layer-htp-mem.c:87
sc_errno
thread_local SCError sc_errno
Definition: util-error.c:31
app-layer-htp-mem.h
HTPMalloc
void * HTPMalloc(size_t size)
Definition: app-layer-htp-mem.c:133
HTPFree
void HTPFree(void *ptr, size_t size)
Definition: app-layer-htp-mem.c:199
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
util-misc.h
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53