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 ((SCConfGet("app-layer.protocols.http.memcap", &conf_val)) == 1) {
52  if (ParseSizeStringU64(conf_val, &memcap) < 0) {
53  SCLogError("Error parsing http.memcap "
54  "from conf file - %s. Killing engine",
55  conf_val);
56  exit(EXIT_FAILURE);
57  } else {
58  SC_ATOMIC_SET(htp_config_memcap, memcap);
59  }
60  SCLogInfo("HTTP memcap: %"PRIu64, SC_ATOMIC_GET(htp_config_memcap));
61  } else {
62  /* default to unlimited */
63  SC_ATOMIC_SET(htp_config_memcap, 0);
64  }
65 
66  SC_ATOMIC_INIT(htp_memuse);
67  SC_ATOMIC_INIT(htp_memcap);
68 }
69 
70 static void HTPIncrMemuse(uint64_t size)
71 {
72  (void)SC_ATOMIC_ADD(htp_memuse, size);
73 }
74 
75 static void HTPDecrMemuse(uint64_t size)
76 {
77  (void)SC_ATOMIC_SUB(htp_memuse, size);
78 }
79 
80 uint64_t HTPMemuseGlobalCounter(void)
81 {
82  uint64_t tmpval = SC_ATOMIC_GET(htp_memuse);
83  return tmpval;
84 }
85 
86 uint64_t HTPMemcapGlobalCounter(void)
87 {
88  uint64_t tmpval = SC_ATOMIC_GET(htp_memcap);
89  return tmpval;
90 }
91 
92 /**
93  * \brief Check if alloc'ing "size" would mean we're over memcap
94  *
95  * \retval 1 if in bounds
96  * \retval 0 if not in bounds
97  */
98 static int HTPCheckMemcap(uint64_t size)
99 {
100  uint64_t memcapcopy = SC_ATOMIC_GET(htp_config_memcap);
101  if (memcapcopy == 0 || size + SC_ATOMIC_GET(htp_memuse) <= memcapcopy)
102  return 1;
103  (void) SC_ATOMIC_ADD(htp_memcap, 1);
104  return 0;
105 }
106 
107 /**
108  * \brief Update memcap value
109  *
110  * \param size new memcap value
111  */
112 int HTPSetMemcap(uint64_t size)
113 {
114  if (size == 0 || (uint64_t)SC_ATOMIC_GET(htp_memuse) < size) {
115  SC_ATOMIC_SET(htp_config_memcap, size);
116  return 1;
117  }
118  return 0;
119 }
120 
121 /**
122  * \brief Update memcap value
123  *
124  * \retval memcap value
125  */
126 uint64_t HTPGetMemcap(void)
127 {
128  uint64_t memcapcopy = SC_ATOMIC_GET(htp_config_memcap);
129  return memcapcopy;
130 }
131 
132 void *HTPMalloc(size_t size)
133 {
134  void *ptr = NULL;
135 
136  if (HTPCheckMemcap((uint32_t)size) == 0) {
138  return NULL;
139  }
140 
141  ptr = SCMalloc(size);
142 
143  if (unlikely(ptr == NULL)) {
145  return NULL;
146  }
147 
148  HTPIncrMemuse((uint64_t)size);
149 
150  return ptr;
151 }
152 
153 void *HTPCalloc(size_t n, size_t size)
154 {
155  void *ptr = NULL;
156 
157  if (HTPCheckMemcap((uint32_t)(n * size)) == 0) {
159  return NULL;
160  }
161 
162  ptr = SCCalloc(n, size);
163 
164  if (unlikely(ptr == NULL)) {
166  return NULL;
167  }
168 
169  HTPIncrMemuse((uint64_t)(n * size));
170 
171  return ptr;
172 }
173 
174 void *HTPRealloc(void *ptr, size_t orig_size, size_t size)
175 {
176  if (size > orig_size) {
177  if (HTPCheckMemcap((uint32_t)(size - orig_size)) == 0) {
179  return NULL;
180  }
181  }
182 
183  void *rptr = SCRealloc(ptr, size);
184  if (rptr == NULL) {
186  return NULL;
187  }
188 
189  if (size > orig_size) {
190  HTPIncrMemuse((uint64_t)(size - orig_size));
191  } else {
192  HTPDecrMemuse((uint64_t)(orig_size - size));
193  }
194 
195  return rptr;
196 }
197 
198 void HTPFree(void *ptr, size_t size)
199 {
200  SCFree(ptr);
201 
202  HTPDecrMemuse((uint64_t)size);
203 }
204 
205 /**
206  * @}
207  */
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
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:350
HTPRealloc
void * HTPRealloc(void *ptr, size_t orig_size, size_t size)
Definition: app-layer-htp-mem.c:174
HTPMemuseGlobalCounter
uint64_t HTPMemuseGlobalCounter(void)
Definition: app-layer-htp-mem.c:80
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:112
SC_ENOMEM
@ SC_ENOMEM
Definition: util-error.h:29
util-debug.h
HTPGetMemcap
uint64_t HTPGetMemcap(void)
Update memcap value.
Definition: app-layer-htp-mem.c:126
HTPCalloc
void * HTPCalloc(size_t n, size_t size)
Definition: app-layer-htp-mem.c:153
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:86
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:132
HTPFree
void HTPFree(void *ptr, size_t size)
Definition: app-layer-htp-mem.c:198
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