suricata
util-coredump-config.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2010 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 * \author Eileen Donlon <emdonlo@gmail.com>
22 *
23 * Coredump configuration
24 */
25
26#include "suricata-common.h"
28#include "conf.h"
29#ifdef HAVE_SYS_RESOURCE_H
30#include <sys/resource.h>
31#endif
32#ifdef HAVE_SYS_PRCTL_H
33#include <sys/prctl.h>
34#endif
35#include "util-byte.h"
36#include "util-debug.h"
37
38#ifdef OS_WIN32
39
40void CoredumpEnable(void) {
41}
42
43int32_t CoredumpLoadConfig(void) {
44 /* todo: use the registry to get/set dump configuration */
45 SCLogInfo("Configuring core dump is not yet supported on Windows.");
46 return 0;
47}
48
50{
51}
52
53#else
54
55static bool unlimited = false;
56static rlim_t max_dump = 0;
57
58/**
59 * \brief Enable coredumps on systems where coredumps can and need to
60 * be enabled.
61 */
63{
64 if (!unlimited && !max_dump) {
65 return;
66 }
67#if HAVE_SYS_PRCTL_H
68 /* Linux specific core dump configuration; set dumpable flag if needed */
69 int dumpable = 0;
70 dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
71 if (dumpable == -1) {
72 SCLogNotice("Failed to get dumpable state of process, "
73 "core dumps may not be enabled: %s",
74 strerror(errno));
75 }
76 else if (unlimited || max_dump > 0) {
77 /* try to enable core dump for this process */
78 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
79 SCLogInfo("Unable to make this process dumpable.");
80 } else {
81 SCLogDebug("Process is dumpable.");
82 }
83 }
84 /* don't clear dumpable flag since this will have other effects;
85 * just set dump size to 0 below */
86#endif /* HAVE_SYS_PRCTL_H */
87}
88
89/**
90 * \brief Configures the core dump size.
91 *
92 * \retval Returns 1 on success and 0 on failure.
93 *
94 */
95int32_t CoredumpLoadConfig (void)
96{
97#ifdef HAVE_SYS_RESOURCE_H
98 /* get core dump configuration settings for suricata */
99 int ret = 0;
100 uint64_t max_dump64 = 0;
101 uint32_t max_dump32 = 0;
102 const char *dump_size_config = NULL;
103 size_t rlim_size = sizeof(rlim_t);
104
105 if (SCConfGet("coredump.max-dump", &dump_size_config) == 0) {
106 SCLogDebug ("core dump size not specified");
107 return 1;
108 }
109 if (dump_size_config == NULL) {
110 SCLogError("malformed value for coredump.max-dump: NULL");
111 return 0;
112 }
113 if (strcasecmp (dump_size_config, "unlimited") == 0) {
114 unlimited = true;
115 }
116 else {
117 /* disallow negative values */
118 if (strchr (dump_size_config, '-') != NULL) {
119 SCLogInfo ("Negative value for core dump size; ignored.");
120 return 0;
121 }
122 /* the size of rlim_t is platform dependent */
123 if (rlim_size > 8) {
124 SCLogInfo ("Unexpected type for rlim_t");
125 return 0;
126 }
127 if (rlim_size == 8) {
129 &max_dump64, 10, strlen(dump_size_config), dump_size_config);
130 }
131 else if (rlim_size == 4) {
133 &max_dump32, 10, strlen(dump_size_config), dump_size_config);
134 }
135 if (ret <= 0) {
136 SCLogInfo ("Illegal core dump size: %s.", dump_size_config);
137 return 0;
138 }
139
140 max_dump = rlim_size == 8 ? (rlim_t)max_dump64 : (rlim_t)max_dump32;
141 if (max_dump == 0) {
142 SCLogInfo("Max dump is 0, disable core dumping.");
143 } else {
144 SCLogInfo("Max dump is %" PRIu64, (uint64_t)max_dump);
145 }
146 }
147
149
150 struct rlimit lim; /*existing limit*/
151 struct rlimit new_lim; /*desired limit*/
152
153 /* get the current core dump file configuration */
154 if (getrlimit (RLIMIT_CORE, &lim) == -1) {
155 SCLogInfo ("Can't read coredump limit for this process.");
156 return 0;
157 }
158
159 if (unlimited) {
160 /* we want no limit on coredump size */
161 if (lim.rlim_max == RLIM_INFINITY && lim.rlim_cur == RLIM_INFINITY) {
162 SCLogConfig ("Core dump size is unlimited.");
163 return 1;
164 }
165 else {
166 new_lim.rlim_max = RLIM_INFINITY;
167 new_lim.rlim_cur = RLIM_INFINITY;
168 if (setrlimit (RLIMIT_CORE, &new_lim) == 0) {
169 SCLogConfig ("Core dump size set to unlimited.");
170 return 1;
171 }
172 if (errno == EPERM) {
173 /* couldn't raise the hard limit to unlimited;
174 * try increasing the soft limit to the hard limit instead */
175 if (lim.rlim_cur < lim.rlim_max) {
176 new_lim.rlim_cur = lim.rlim_max;
177 if (setrlimit (RLIMIT_CORE, & new_lim) == 0) {
178 SCLogInfo ("Could not set core dump size to unlimited; core dump size set to the hard limit.");
179 return 0;
180 }
181 else {
182 SCLogInfo ("Failed to set core dump size to unlimited or to the hard limit.");
183 return 0;
184 }
185 }
186 SCLogInfo ("Could not set core dump size to unlimited; it's set to the hard limit.");
187 return 0;
188 }
189 }
190 }
191 else {
192 /* we want a non-infinite soft limit on coredump size */
193 new_lim.rlim_cur = max_dump;
194
195 /* check whether the hard limit needs to be adjusted */
196 if (lim.rlim_max == RLIM_INFINITY) {
197 /* keep the current value (unlimited) for the hard limit */
198 new_lim.rlim_max = lim.rlim_max;
199 }
200#ifdef RLIM_SAVED_MAX
201 else if (lim.rlim_max == RLIM_SAVED_MAX) {
202 /* keep the current value (unknown) for the hard limit */
203 new_lim.rlim_max = lim.rlim_max;
204 }
205#endif
206 else if (lim.rlim_max < max_dump) {
207 /* need to raise the hard coredump size limit */
208 new_lim.rlim_max = max_dump;
209 }
210 else {
211 /* hard limit is ample */
212 new_lim.rlim_max = lim.rlim_max;
213 }
214 if (setrlimit (RLIMIT_CORE, &new_lim) == 0) {
215 SCLogInfo ("Core dump setting attempted is %"PRIu64, (uint64_t) new_lim.rlim_cur);
216 struct rlimit actual_lim;
217 if (getrlimit (RLIMIT_CORE, &actual_lim) == 0) {
218 if (actual_lim.rlim_cur == RLIM_INFINITY) {
219 SCLogConfig ("Core dump size set to unlimited.");
220 }
221#ifdef RLIM_SAVED_CUR
222 else if (actual_lim.rlim_cur == RLIM_SAVED_CUR) {
223 SCLogInfo ("Core dump size set to soft limit.");
224 }
225#endif
226 else {
227 SCLogInfo ("Core dump size set to %"PRIu64, (uint64_t) actual_lim.rlim_cur);
228 }
229 }
230 return 1;
231 }
232
233 if (errno == EINVAL || errno == EPERM) {
234 /* couldn't increase the hard limit, or the soft limit exceeded the hard
235 * limit; try to raise the soft limit to the hard limit */
236 if ((lim.rlim_cur < max_dump && lim.rlim_cur < lim.rlim_max)
237#ifdef RLIM_SAVED_CUR
238 || (lim.rlim_cur == RLIM_SAVED_CUR)
239#endif
240 ){
241 new_lim.rlim_max = lim.rlim_max;
242 new_lim.rlim_cur = lim.rlim_max;
243 if (setrlimit (RLIMIT_CORE, &new_lim) == 0) {
244 SCLogInfo("Core dump size set to the hard limit.");
245 return 0;
246 }
247 }
248 }
249 }
250 /* failed to set the coredump limit */
251 SCLogInfo("Couldn't set coredump size to %s.", dump_size_config);
252#endif /* HAVE_SYS_RESOURCE_H */
253 return 0;
254}
255
256#if defined UNITTESTS && defined HAVE_SYS_RESOURCE_H
257#include "conf-yaml-loader.h"
258
259static void ResetCoredumpConfig(void)
260{
261 unlimited = false;
262 max_dump = 0;
263}
264
265/**
266 * \test CoredumpConfigTest01 is a test for the coredump configuration
267 * with unlimited coredump size.
268 */
269static int CoredumpConfigTest01(void)
270{
271 char config[] = "\
272%YAML 1.1\n\
273---\n\
274coredump:\n\
275 max-dump: unlimited\n\
276";
277
278 int ret = 0;
279 ResetCoredumpConfig();
281 SCConfInit();
282
283 SCConfYamlLoadString(config, strlen(config));
284 ret = CoredumpLoadConfig();
285 FAIL_IF(errno != EPERM && ret != 1);
286
287 FAIL_IF(unlimited != true);
288 FAIL_IF(max_dump != 0);
289
290 SCConfDeInit();
292 PASS;
293}
294
295/**
296 * \test CoredumpConfigTest02 is a test for the coredump configuration
297 * with a specific coredump size.
298 */
299static int CoredumpConfigTest02(void)
300{
301 char config[] = "\
302%YAML 1.1\n\
303---\n\
304coredump:\n\
305 max-dump: 1000000\n\
306";
307
308 int ret = 0;
309 ResetCoredumpConfig();
311 SCConfInit();
312
313 SCConfYamlLoadString(config, strlen(config));
314 ret = CoredumpLoadConfig();
315 FAIL_IF(errno != EPERM && ret != 1);
316
317 FAIL_IF(unlimited != false);
318 FAIL_IF(max_dump != 1000000);
319
320 SCConfDeInit();
322 PASS;
323}
324
325/**
326 * \test CoredumpConfigTest03 is a test for the coredump configuration
327 * with an invalid coredump size.
328 */
329static int CoredumpConfigTest03(void)
330{
331 char config[] = "\
332%YAML 1.1\n\
333---\n\
334coredump:\n\
335 max-dump: -1000000\n\
336";
337
338 ResetCoredumpConfig();
340 SCConfInit();
341
342 SCConfYamlLoadString(config, strlen(config));
344
345 FAIL_IF(unlimited != false);
346 FAIL_IF(max_dump != 0);
347
348 SCConfDeInit();
350 PASS;
351}
352
353/**
354 * \test CoredumpConfigTest04 is a test for the coredump configuration
355 * with a non-numeric coredump size.
356 */
357static int CoredumpConfigTest04(void)
358{
359 char config[] = "\
360%YAML 1.1\n\
361---\n\
362coredump:\n\
363 max-dump: a\n\
364";
365
366 ResetCoredumpConfig();
368 SCConfInit();
369
370 SCConfYamlLoadString(config, strlen(config));
372
373 FAIL_IF(unlimited != false);
374 FAIL_IF(max_dump != 0);
375
376 SCConfDeInit();
378 PASS;
379}
380
381/**
382 * \test CoredumpConfigTest05 is a test for the coredump configuration
383 * with a zero coredump size.
384 */
385static int CoredumpConfigTest05(void)
386{
387 char config[] = "\
388%YAML 1.1\n\
389---\n\
390coredump:\n\
391 max-dump: 0\n\
392";
393
394 int ret = 0;
395 ResetCoredumpConfig();
397 SCConfInit();
398
399 SCConfYamlLoadString(config, strlen(config));
400 ret = CoredumpLoadConfig();
401 /* should return 1 because zero coredump size is allowed. */
402 FAIL_IF(errno != EPERM && ret != 1);
403
404 FAIL_IF(unlimited != false);
405 FAIL_IF(max_dump != 0);
406
407 SCConfDeInit();
409 PASS;
410}
411#endif /* UNITTESTS */
412
414{
415#if defined UNITTESTS && defined HAVE_SYS_RESOURCE_H
416 UtRegisterTest("CoredumpConfigTest01", CoredumpConfigTest01);
417 UtRegisterTest("CoredumpConfigTest02", CoredumpConfigTest02);
418 UtRegisterTest("CoredumpConfigTest03", CoredumpConfigTest03);
419 UtRegisterTest("CoredumpConfigTest04", CoredumpConfigTest04);
420 UtRegisterTest("CoredumpConfigTest05", CoredumpConfigTest05);
421#endif /* UNITTESTS */
422}
423
424#endif /* OS_WIN32 */
int SCConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
void SCConfInit(void)
Initialize the configuration system.
Definition conf.c:120
void SCConfDeInit(void)
De-initializes the configuration system.
Definition conf.c:703
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition conf.c:350
void SCConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition conf.c:684
void SCConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition conf.c:694
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
int ByteExtractStringUint32(uint32_t *res, int base, size_t len, const char *str)
Definition util-byte.c:239
int ByteExtractStringUint64(uint64_t *res, int base, size_t len, const char *str)
Definition util-byte.c:234
void CoredumpEnable(void)
Enable coredumps on systems where coredumps can and need to be enabled.
int32_t CoredumpLoadConfig(void)
Configures the core dump size.
void CoredumpConfigRegisterTests(void)
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition util-debug.h:243
#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
#define SCLogConfig(...)
Definition util-debug.h:229