diff --git a/src/Makefile.am b/src/Makefile.am index 01daf44ae5..845ccf9aee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -203,6 +203,7 @@ util-random.c util-random.h \ util-classification-config.c util-classification-config.h \ util-threshold-config.c util-threshold-config.h \ util-reference-config.c util-reference-config.h \ +util-coredump-config.c util-coredump-config.h \ util-strlcatu.c \ util-strlcpyu.c \ util-cuda.c util-cuda.h \ diff --git a/src/suricata.c b/src/suricata.c index 5bb4c86379..4690cf257a 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -138,6 +138,8 @@ #include "util-profiling.h" #include "util-magic.h" +#include "util-coredump-config.h" + #include "defrag.h" #include "runmodes.h" @@ -1499,6 +1501,8 @@ int main(int argc, char **argv) SCThresholdConfInitContext(de_ctx,NULL); SCAsn1LoadConfig(); + CoredumpLoadConfig(); + struct timeval start_time; memset(&start_time, 0, sizeof(start_time)); gettimeofday(&start_time, NULL); diff --git a/src/util-coredump-config.c b/src/util-coredump-config.c new file mode 100644 index 0000000000..2b9abe72ee --- /dev/null +++ b/src/util-coredump-config.c @@ -0,0 +1,193 @@ +/* Copyright (C) 2007-2010 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Eileen Donlon + * + * Coredump configuration + */ + +#define _FILE_OFFSET_BITS 64 +#include "util-coredump-config.h" +#include "conf.h" +#include +#include + +/** + * \brief Configures the core dump size. + * + * \retval Returns 1 on success and 0 on failure. + * + */ +int32_t CoredumpLoadConfig (void) +{ + /* get core dump configuration settings for suricata */ + char* dump_size_config = NULL; + rlim_t max_dump = 0; + uint32_t unlimited = 0; + size_t rlim_size = sizeof(rlim_t); + + if (ConfGet ("coredump.max_dump", &dump_size_config) == 0) { + SCLogInfo ("Core dump size not specified."); + return 1; + } + if (strcasecmp (dump_size_config, "unlimited") == 0) { + unlimited = 1; + } + else { + /* disallow negative values */ + if (strchr (dump_size_config, '-') != NULL) { + SCLogInfo ("Negative value for core dump size; ignored."); + return 0; + } + /* the size of rlim_t is platform dependent */ + if (rlim_size > 8) { + SCLogInfo ("Unexpected type for rlim_t"); + return 0; + } + errno = 0; + if (rlim_size == 8) { + max_dump = (rlim_t) strtoull (dump_size_config, NULL, 10); + } + else if (rlim_size == 4) { + max_dump = (rlim_t) strtoul (dump_size_config, NULL, 10); + } + if ((errno == ERANGE) || (errno != 0 && max_dump == 0)) { + SCLogInfo ("Illegal core dump size: %s.", dump_size_config); + return 0; + } + SCLogInfo ("Max dump is %llu", (unsigned long long) max_dump); + } + +#if defined OS_WIN32 + /* todo: use the registry to get/set dump configuration */ + SCLogInfo("Configuring core dump is not yet supported on Windows."); + return 0; + +#elif !defined OS_FREEBSD && !defined __OpenBSD__ + /* Linux specific core dump configuration; set dumpable flag if needed */ + int dumpable = 0; + dumpable = prctl (PR_GET_DUMPABLE, 0, 0, 0, 0); + if (dumpable == -1) { + SCLogInfo ("Can't get core dump configuration of process."); + } + else if (unlimited == 1 || max_dump > 0) { + /* try to enable core dump for this process */ + if (prctl (PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { + SCLogInfo ("Unable to make this process dumpable."); + return 0; + } + else SCLogInfo ("Process is dumpable."); + } + /* don't clear dumpable flag since this will have other effects; + * just set dump size to 0 below */ +#endif /* Linux specific */ + + struct rlimit lim; /*existing limit*/ + struct rlimit new_lim; /*desired limit*/ + + /* get the current core dump file configuration */ + if (getrlimit (RLIMIT_CORE, &lim) == -1) { + SCLogInfo ("Can't read coredump limit for this process."); + return 0; + } + + if (unlimited) { + /* we want no limit on coredump size */ + if (lim.rlim_max == RLIM_INFINITY && lim.rlim_cur == RLIM_INFINITY) { + SCLogInfo ("Core dump size is unlimited."); + return 1; + } + else { + new_lim.rlim_max = RLIM_INFINITY; + new_lim.rlim_cur = RLIM_INFINITY; + if (setrlimit (RLIMIT_CORE, &new_lim) == 0) { + SCLogInfo ("Core dump size set to unlimited."); + return 1; + } + if (errno == EPERM) { + /* couldn't raise the hard limit to unlimited; + * try increasing the soft limit to the hard limit instead */ + if (lim.rlim_cur < lim.rlim_max) { + new_lim.rlim_cur = lim.rlim_max; + if (setrlimit (RLIMIT_CORE, & new_lim) == 0) { + SCLogInfo ("Could not set core dump size to unlimited; core dump size set to the hard limit."); + return 0; + } + else { + SCLogInfo ("Failed to set core dump size to unlimited or to the hard limit."); + return 0; + } + } + SCLogInfo ("Could not set core dump size to unlimited; it's set to the hard limit."); + return 0; + } + } + } + else { + /* we want a non-infinite soft limit on coredump size */ + new_lim.rlim_cur = max_dump; + + /* check whether the hard limit needs to be adjusted */ + if (lim.rlim_max == RLIM_SAVED_MAX || lim.rlim_max == RLIM_INFINITY) { + /* keep the current value (unknown or unlimited) for the hard limit */ + new_lim.rlim_max = lim.rlim_max; + } + else if (lim.rlim_max < max_dump) { + /* need to raise the hard coredump size limit */ + new_lim.rlim_max = max_dump; + } + else { + /* hard limit is ample */ + new_lim.rlim_max = lim.rlim_max; + } + if (setrlimit (RLIMIT_CORE, &new_lim) == 0) { + SCLogInfo ("Core dump setting attempted is %llu", (unsigned long long) new_lim.rlim_cur); + struct rlimit actual_lim; + if (getrlimit (RLIMIT_CORE, &actual_lim) == 0) { + if (actual_lim.rlim_cur == RLIM_INFINITY) { + SCLogInfo ("Core dump size set to unlimited."); + } + else if (actual_lim.rlim_cur == RLIM_SAVED_CUR) { + SCLogInfo ("Core dump size set to soft limit."); + } + else { + SCLogInfo ("Core dump size set to %llu", (unsigned long long) actual_lim.rlim_cur); + } + } + return 1; + } + + if (errno == EINVAL || errno == EPERM) { + /* could't increase the hard limit, or the soft limit exceeded the hard + * limit; try to raise the soft limit to the hard limit */ + if (lim.rlim_cur == RLIM_SAVED_CUR || (lim.rlim_cur < max_dump && lim.rlim_cur < lim.rlim_max)) { + new_lim.rlim_max = lim.rlim_max; + new_lim.rlim_cur = lim.rlim_max; + if (setrlimit (RLIMIT_CORE, &new_lim) == 0) { + SCLogInfo("Core dump size set to the hard limit."); + return 0; + } + } + } + } + /* failed to set the coredump limit */ + SCLogInfo ("Could't set coredump size to %s.", dump_size_config); + return 0; +} diff --git a/src/util-coredump-config.h b/src/util-coredump-config.h new file mode 100644 index 0000000000..7994421bce --- /dev/null +++ b/src/util-coredump-config.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2007-2010 Open Information Security Foundation + + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Eileen Donlon + */ + +#ifndef __COREDUMP_CONFIG_H__ +#define __COREDUMP_CONFIG_H__ + +#include "suricata-common.h" + +int32_t CoredumpLoadConfig (void); + +#endif /* __COREDUMP_CONFIG_H__ */ diff --git a/suricata.yaml b/suricata.yaml index a63d07897f..993c0a99b6 100644 --- a/suricata.yaml +++ b/suricata.yaml @@ -824,3 +824,14 @@ profiling: enabled: no filename: packet_stats.csv +# Suricata core dump configuration. Limits the size of the core dump file to +# approximately max_dump. The actual core dump size will be a multiple of the +# page size. Core dumps that would be larger than max_dump are truncated. On +# Linux, the actual core dump size may be a few pages larger than max_dump. +# Setting max_dump to 0 disables core dumping. +# Setting max_dump to 'unlimited' will give the full core dump file. +# On 32-bit Linux, a max_dump value >= ULONG_MAX may cause the core dump size +# to be 'unlimited'. + +coredump: + max_dump: unlimited