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"
27 #include "util-coredump-config.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-debug.h"
36 
37 #ifdef OS_WIN32
38 
39 void CoredumpEnable(void) {
40 }
41 
42 int32_t CoredumpLoadConfig(void) {
43  /* todo: use the registry to get/set dump configuration */
44  SCLogInfo("Configuring core dump is not yet supported on Windows.");
45  return 0;
46 }
47 
48 #else
49 
50 static bool unlimited = false;
51 static rlim_t max_dump = 0;
52 
53 /**
54  * \brief Enable coredumps on systems where coredumps can and need to
55  * be enabled.
56  */
57 void CoredumpEnable(void)
58 {
59  if (!unlimited && !max_dump) {
60  return;
61  }
62 #if HAVE_SYS_PRCTL_H
63  /* Linux specific core dump configuration; set dumpable flag if needed */
64  int dumpable = 0;
65  dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
66  if (dumpable == -1) {
67  SCLogNotice("Failed to get dumpable state of process, "
68  "core dumps may not be enabled: %s",
69  strerror(errno));
70  }
71  else if (unlimited || max_dump > 0) {
72  /* try to enable core dump for this process */
73  if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
74  SCLogInfo("Unable to make this process dumpable.");
75  } else {
76  SCLogDebug("Process is dumpable.");
77  }
78  }
79  /* don't clear dumpable flag since this will have other effects;
80  * just set dump size to 0 below */
81 #endif /* HAVE_SYS_PRCTL_H */
82 }
83 
84 /**
85  * \brief Configures the core dump size.
86  *
87  * \retval Returns 1 on success and 0 on failure.
88  *
89  */
90 int32_t CoredumpLoadConfig (void)
91 {
92 #ifdef HAVE_SYS_RESOURCE_H
93  /* get core dump configuration settings for suricata */
94  const char *dump_size_config = NULL;
95  size_t rlim_size = sizeof(rlim_t);
96 
97  if (ConfGet ("coredump.max-dump", &dump_size_config) == 0) {
98  SCLogDebug ("core dump size not specified");
99  return 1;
100  }
101  if (dump_size_config == NULL) {
102  SCLogError("malformed value for coredump.max-dump: NULL");
103  return 0;
104  }
105  if (strcasecmp (dump_size_config, "unlimited") == 0) {
106  unlimited = true;
107  }
108  else {
109  /* disallow negative values */
110  if (strchr (dump_size_config, '-') != NULL) {
111  SCLogInfo ("Negative value for core dump size; ignored.");
112  return 0;
113  }
114  /* the size of rlim_t is platform dependent */
115  if (rlim_size > 8) {
116  SCLogInfo ("Unexpected type for rlim_t");
117  return 0;
118  }
119  errno = 0;
120  if (rlim_size == 8) {
121  max_dump = (rlim_t) strtoull (dump_size_config, NULL, 10);
122  }
123  else if (rlim_size == 4) {
124  max_dump = (rlim_t) strtoul (dump_size_config, NULL, 10);
125  }
126  if ((errno == ERANGE) || (errno != 0 && max_dump == 0)) {
127  SCLogInfo ("Illegal core dump size: %s.", dump_size_config);
128  return 0;
129  }
130  SCLogInfo ("Max dump is %"PRIu64, (uint64_t) max_dump);
131  }
132 
133  CoredumpEnable();
134 
135  struct rlimit lim; /*existing limit*/
136  struct rlimit new_lim; /*desired limit*/
137 
138  /* get the current core dump file configuration */
139  if (getrlimit (RLIMIT_CORE, &lim) == -1) {
140  SCLogInfo ("Can't read coredump limit for this process.");
141  return 0;
142  }
143 
144  if (unlimited) {
145  /* we want no limit on coredump size */
146  if (lim.rlim_max == RLIM_INFINITY && lim.rlim_cur == RLIM_INFINITY) {
147  SCLogConfig ("Core dump size is unlimited.");
148  return 1;
149  }
150  else {
151  new_lim.rlim_max = RLIM_INFINITY;
152  new_lim.rlim_cur = RLIM_INFINITY;
153  if (setrlimit (RLIMIT_CORE, &new_lim) == 0) {
154  SCLogConfig ("Core dump size set to unlimited.");
155  return 1;
156  }
157  if (errno == EPERM) {
158  /* couldn't raise the hard limit to unlimited;
159  * try increasing the soft limit to the hard limit instead */
160  if (lim.rlim_cur < lim.rlim_max) {
161  new_lim.rlim_cur = lim.rlim_max;
162  if (setrlimit (RLIMIT_CORE, & new_lim) == 0) {
163  SCLogInfo ("Could not set core dump size to unlimited; core dump size set to the hard limit.");
164  return 0;
165  }
166  else {
167  SCLogInfo ("Failed to set core dump size to unlimited or to the hard limit.");
168  return 0;
169  }
170  }
171  SCLogInfo ("Could not set core dump size to unlimited; it's set to the hard limit.");
172  return 0;
173  }
174  }
175  }
176  else {
177  /* we want a non-infinite soft limit on coredump size */
178  new_lim.rlim_cur = max_dump;
179 
180  /* check whether the hard limit needs to be adjusted */
181  if (lim.rlim_max == RLIM_INFINITY) {
182  /* keep the current value (unlimited) for the hard limit */
183  new_lim.rlim_max = lim.rlim_max;
184  }
185 #ifdef RLIM_SAVED_MAX
186  else if (lim.rlim_max == RLIM_SAVED_MAX) {
187  /* keep the current value (unknown) for the hard limit */
188  new_lim.rlim_max = lim.rlim_max;
189  }
190 #endif
191  else if (lim.rlim_max < max_dump) {
192  /* need to raise the hard coredump size limit */
193  new_lim.rlim_max = max_dump;
194  }
195  else {
196  /* hard limit is ample */
197  new_lim.rlim_max = lim.rlim_max;
198  }
199  if (setrlimit (RLIMIT_CORE, &new_lim) == 0) {
200  SCLogInfo ("Core dump setting attempted is %"PRIu64, (uint64_t) new_lim.rlim_cur);
201  struct rlimit actual_lim;
202  if (getrlimit (RLIMIT_CORE, &actual_lim) == 0) {
203  if (actual_lim.rlim_cur == RLIM_INFINITY) {
204  SCLogConfig ("Core dump size set to unlimited.");
205  }
206 #ifdef RLIM_SAVED_CUR
207  else if (actual_lim.rlim_cur == RLIM_SAVED_CUR) {
208  SCLogInfo ("Core dump size set to soft limit.");
209  }
210 #endif
211  else {
212  SCLogInfo ("Core dump size set to %"PRIu64, (uint64_t) actual_lim.rlim_cur);
213  }
214  }
215  return 1;
216  }
217 
218  if (errno == EINVAL || errno == EPERM) {
219  /* couldn't increase the hard limit, or the soft limit exceeded the hard
220  * limit; try to raise the soft limit to the hard limit */
221  if ((lim.rlim_cur < max_dump && lim.rlim_cur < lim.rlim_max)
222 #ifdef RLIM_SAVED_CUR
223  || (lim.rlim_cur == RLIM_SAVED_CUR)
224 #endif
225  ){
226  new_lim.rlim_max = lim.rlim_max;
227  new_lim.rlim_cur = lim.rlim_max;
228  if (setrlimit (RLIMIT_CORE, &new_lim) == 0) {
229  SCLogInfo("Core dump size set to the hard limit.");
230  return 0;
231  }
232  }
233  }
234  }
235  /* failed to set the coredump limit */
236  SCLogInfo("Couldn't set coredump size to %s.", dump_size_config);
237 #endif /* HAVE_SYS_RESOURCE_H */
238  return 0;
239 }
240 
241 #endif /* OS_WIN32 */
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
util-coredump-config.h
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
util-debug.h
CoredumpLoadConfig
int32_t CoredumpLoadConfig(void)
Configures the core dump size.
Definition: util-coredump-config.c:90
conf.h
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
suricata-common.h
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
CoredumpEnable
void CoredumpEnable(void)
Enable coredumps on systems where coredumps can and need to be enabled.
Definition: util-coredump-config.c:57
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:237