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