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
39SC_ATOMIC_DECLARE(uint64_t, htp_config_memcap);
40SC_ATOMIC_DECLARE(uint64_t, htp_memuse);
41SC_ATOMIC_DECLARE(uint64_t, htp_memcap);
42
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
70static void HTPIncrMemuse(uint64_t size)
71{
72 (void)SC_ATOMIC_ADD(htp_memuse, size);
73}
74
75static void HTPDecrMemuse(uint64_t size)
76{
77 (void)SC_ATOMIC_SUB(htp_memuse, size);
78}
79
81{
82 uint64_t tmpval = SC_ATOMIC_GET(htp_memuse);
83 return tmpval;
84}
85
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 */
98static 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 */
112int 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 */
126uint64_t HTPGetMemcap(void)
127{
128 uint64_t memcapcopy = SC_ATOMIC_GET(htp_config_memcap);
129 return memcapcopy;
130}
131
132void *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
153void *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
174void *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
198void HTPFree(void *ptr, size_t size)
199{
200 SCFree(ptr);
201
202 HTPDecrMemuse((uint64_t)size);
203}
204
205/**
206 * @}
207 */
uint64_t HTPMemuseGlobalCounter(void)
void HTPParseMemcap(void)
void * HTPCalloc(size_t n, size_t size)
int HTPSetMemcap(uint64_t size)
Update memcap value.
void * HTPRealloc(void *ptr, size_t orig_size, size_t size)
void HTPFree(void *ptr, size_t size)
uint64_t HTPMemcapGlobalCounter(void)
uint64_t HTPGetMemcap(void)
Update memcap value.
void * HTPMalloc(size_t size)
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition conf.c:350
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
#define SC_ATOMIC_DECLARE(type, name)
wrapper for declaring atomic variables.
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
thread_local SCError sc_errno
Definition util-error.c:31
@ SC_ELIMIT
Definition util-error.h:31
@ SC_ENOMEM
Definition util-error.h:29
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define SCRealloc(ptr, sz)
Definition util-mem.h:50
#define SCCalloc(nm, sz)
Definition util-mem.h:53
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition util-misc.c:190
#define unlikely(expr)