On Linux, if the command we ran dumped core, set PR_SET_DUMPABLE

to 0.  This will prevent sudo itself from dumping core in this case.
This commit is contained in:
Todd C. Miller
2017-04-27 12:28:08 -06:00
parent f0425ca813
commit f57629c953

View File

@@ -70,6 +70,9 @@
# endif /* __hpux */ # endif /* __hpux */
# include <prot.h> # include <prot.h>
#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
#ifdef __linux__
# include <sys/prctl.h>
#endif
#include <sudo_usage.h> #include <sudo_usage.h>
#include "sudo.h" #include "sudo.h"
@@ -104,7 +107,7 @@ static struct sudo_gc_list sudo_gc_list = SLIST_HEAD_INITIALIZER(sudo_gc_list);
* Local functions * Local functions
*/ */
static void fix_fds(void); static void fix_fds(void);
static void disable_coredumps(void); static void disable_coredump(bool restore);
static void sudo_check_suid(const char *path); static void sudo_check_suid(const char *path);
static char **get_user_info(struct user_details *); static char **get_user_info(struct user_details *);
static void command_info_to_details(char * const info[], static void command_info_to_details(char * const info[],
@@ -136,9 +139,6 @@ static void iolog_close(struct plugin_container *plugin, int exit_status,
static int iolog_show_version(struct plugin_container *plugin, int verbose); static int iolog_show_version(struct plugin_container *plugin, int verbose);
static void iolog_unlink(struct plugin_container *plugin); static void iolog_unlink(struct plugin_container *plugin);
#ifdef RLIMIT_CORE
static struct rlimit corelimit;
#endif
#ifdef __linux__ #ifdef __linux__
static struct rlimit nproclimit; static struct rlimit nproclimit;
#endif #endif
@@ -201,7 +201,8 @@ main(int argc, char *argv[], char *envp[])
exit(EXIT_FAILURE); /* get_user_info printed error message */ exit(EXIT_FAILURE); /* get_user_info printed error message */
/* Disable core dumps if not enabled in sudo.conf. */ /* Disable core dumps if not enabled in sudo.conf. */
disable_coredumps(); if (sudo_conf_disable_coredump())
disable_coredump(false);
/* Parse command line arguments. */ /* Parse command line arguments. */
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add); sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
@@ -300,11 +301,6 @@ main(int argc, char *argv[], char *envp[])
/* Become full root (not just setuid) so user cannot kill us. */ /* Become full root (not just setuid) so user cannot kill us. */
if (setuid(ROOT_UID) == -1) if (setuid(ROOT_UID) == -1)
sudo_warn("setuid(%d)", ROOT_UID); sudo_warn("setuid(%d)", ROOT_UID);
/* Restore coredumpsize resource limit before running. */
#ifdef RLIMIT_CORE
if (sudo_conf_disable_coredump())
(void) setrlimit(RLIMIT_CORE, &corelimit);
#endif /* RLIMIT_CORE */
if (ISSET(command_details.flags, CD_SUDOEDIT)) { if (ISSET(command_details.flags, CD_SUDOEDIT)) {
status = sudo_edit(&command_details); status = sudo_edit(&command_details);
} else { } else {
@@ -325,7 +321,7 @@ main(int argc, char *argv[], char *envp[])
sigaction_t sa; sigaction_t sa;
if (WCOREDUMP(status)) if (WCOREDUMP(status))
disable_coredumps(); disable_coredump(false);
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
@@ -899,27 +895,39 @@ sudo_check_suid(const char *sudo)
/* /*
* Disable core dumps to avoid dropping a core with user password in it. * Disable core dumps to avoid dropping a core with user password in it.
* We will reset this limit before executing the command. * Called with restore set to true before executing the command.
* Not all operating systems disable core dumps for setuid processes. * Not all operating systems disable core dumps for setuid processes.
*/ */
static void static void
disable_coredumps(void) disable_coredump(bool restore)
{ {
#if defined(RLIMIT_CORE)
struct rlimit rl; struct rlimit rl;
debug_decl(disable_coredumps, SUDO_DEBUG_UTIL) static struct rlimit corelimit;
#ifdef __linux__
static int dumpflag;
#endif
debug_decl(disable_coredump, SUDO_DEBUG_UTIL)
if (restore) {
(void) setrlimit(RLIMIT_CORE, &corelimit);
#ifdef __linux__
(void) prctl(PR_SET_DUMPABLE, dumpflag, 0, 0, 0);
#endif /* __linux__ */
debug_return;
}
(void) getrlimit(RLIMIT_CORE, &corelimit);
rl.rlim_cur = 0;
rl.rlim_max = 0;
(void) setrlimit(RLIMIT_CORE, &rl);
#ifdef __linux__
/* On Linux, also set PR_SET_DUMPABLE to zero (reset by execve). */
if ((dumpflag = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) == -1)
dumpflag = 0;
(void) prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
#endif /* __linux__ */
/*
* Turn off core dumps?
*/
if (sudo_conf_disable_coredump()) {
(void) getrlimit(RLIMIT_CORE, &corelimit);
memcpy(&rl, &corelimit, sizeof(struct rlimit));
rl.rlim_cur = 0;
(void) setrlimit(RLIMIT_CORE, &rl);
}
debug_return; debug_return;
#endif /* RLIMIT_CORE */
} }
/* /*
@@ -1014,6 +1022,10 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
} }
#endif #endif
/* Restore coredumpsize resource limit before running. */
if (sudo_conf_disable_coredump())
disable_coredump(true);
if (details->pw != NULL) { if (details->pw != NULL) {
#ifdef HAVE_PROJECT_H #ifdef HAVE_PROJECT_H
set_project(details->pw); set_project(details->pw);