diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /src/util-coredump-config.c | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/util-coredump-config.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/src/util-coredump-config.c b/src/util-coredump-config.c new file mode 100644 index 0000000..09485cb --- /dev/null +++ b/src/util-coredump-config.c @@ -0,0 +1,242 @@ +/* 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 <emdonlo@gmail.com> + * + * Coredump configuration + */ + +#include "suricata-common.h" +#define _FILE_OFFSET_BITS 64 +#include "util-coredump-config.h" +#include "conf.h" +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif +#include "util-debug.h" + +#ifdef OS_WIN32 + +void CoredumpEnable(void) { +} + +int32_t CoredumpLoadConfig(void) { + /* todo: use the registry to get/set dump configuration */ + SCLogInfo("Configuring core dump is not yet supported on Windows."); + return 0; +} + +#else + +static bool unlimited = false; +static rlim_t max_dump = 0; + +/** + * \brief Enable coredumps on systems where coredumps can and need to + * be enabled. + */ +void CoredumpEnable(void) +{ + if (!unlimited && !max_dump) { + return; + } +#if HAVE_SYS_PRCTL_H + /* 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) { + SCLogNotice("Failed to get dumpable state of process, " + "core dumps may not be enabled: %s", + strerror(errno)); + } + else if (unlimited || 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."); + } else { + SCLogDebug("Process is dumpable."); + } + } + /* don't clear dumpable flag since this will have other effects; + * just set dump size to 0 below */ +#endif /* HAVE_SYS_PRCTL_H */ +} + +/** + * \brief Configures the core dump size. + * + * \retval Returns 1 on success and 0 on failure. + * + */ +int32_t CoredumpLoadConfig (void) +{ +#ifdef HAVE_SYS_RESOURCE_H + /* get core dump configuration settings for suricata */ + const char *dump_size_config = NULL; + size_t rlim_size = sizeof(rlim_t); + + if (ConfGet ("coredump.max-dump", &dump_size_config) == 0) { + SCLogDebug ("core dump size not specified"); + return 1; + } + if (dump_size_config == NULL) { + SCLogError("malformed value for coredump.max-dump: NULL"); + return 0; + } + if (strcasecmp (dump_size_config, "unlimited") == 0) { + unlimited = true; + } + 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 %"PRIu64, (uint64_t) max_dump); + } + + CoredumpEnable(); + + 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) { + SCLogConfig ("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) { + SCLogConfig ("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_INFINITY) { + /* keep the current value (unlimited) for the hard limit */ + new_lim.rlim_max = lim.rlim_max; + } +#ifdef RLIM_SAVED_MAX + else if (lim.rlim_max == RLIM_SAVED_MAX) { + /* keep the current value (unknown) for the hard limit */ + new_lim.rlim_max = lim.rlim_max; + } +#endif + 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 %"PRIu64, (uint64_t) new_lim.rlim_cur); + struct rlimit actual_lim; + if (getrlimit (RLIMIT_CORE, &actual_lim) == 0) { + if (actual_lim.rlim_cur == RLIM_INFINITY) { + SCLogConfig ("Core dump size set to unlimited."); + } +#ifdef RLIM_SAVED_CUR + else if (actual_lim.rlim_cur == RLIM_SAVED_CUR) { + SCLogInfo ("Core dump size set to soft limit."); + } +#endif + else { + SCLogInfo ("Core dump size set to %"PRIu64, (uint64_t) actual_lim.rlim_cur); + } + } + return 1; + } + + if (errno == EINVAL || errno == EPERM) { + /* couldn'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 < max_dump && lim.rlim_cur < lim.rlim_max) +#ifdef RLIM_SAVED_CUR + || (lim.rlim_cur == RLIM_SAVED_CUR) +#endif + ){ + 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("Couldn't set coredump size to %s.", dump_size_config); +#endif /* HAVE_SYS_RESOURCE_H */ + return 0; +} + +#endif /* OS_WIN32 */ |