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