From: Todd C. Miller Date: Fri, 3 Feb 2012 19:57:03 +0000 (-0500) Subject: Normally, sudo disables core dumps while it is running. This X-Git-Tag: SUDO_1_8_4~28^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c970d464cbf53821670b9a1a7ae14998c0635392;p=sudo Normally, sudo disables core dumps while it is running. This behavior can now be modified at run time with a line in sudo.conf like "Set disable_coredumps false" --- diff --git a/NEWS b/NEWS index 657345a88..6f139299c 100644 --- a/NEWS +++ b/NEWS @@ -72,6 +72,16 @@ What's new in Sudo 1.8.4? now run "visudo -c". Previously, write permissions were required even though no writing is down in check-only mode. + * It is now possible to prevent the disabling of core dumps from + within sudo itself by adding a line to the sudo.conf file like + "Set disable_coredump false". + +What's new in Sudo 1.8.3p2? + + * Fixed a format string vulnerability when the sudo binary (or a + symbolic link to the sudo binary) contains printf format escapes + and the -D (debugging) flag is used. + What's new in Sudo 1.8.3p1? * Fixed a crash in the monitor process on Solaris when NOPASSWD diff --git a/common/sudo_conf.c b/common/sudo_conf.c index 108f43178..3ddd8619e 100644 --- a/common/sudo_conf.c +++ b/common/sudo_conf.c @@ -59,6 +59,8 @@ # define _PATH_SUDO_ASKPASS NULL #endif +extern bool atobool(const char *str); /* atobool.c */ + struct sudo_conf_table { const char *name; unsigned int namelen; @@ -74,19 +76,23 @@ struct sudo_conf_paths { static bool set_debug(const char *entry); static bool set_path(const char *entry); static bool set_plugin(const char *entry); +static bool set_variable(const char *entry); static struct sudo_conf_table sudo_conf_table[] = { { "Debug", sizeof("Debug") - 1, set_debug }, { "Path", sizeof("Path") - 1, set_path }, { "Plugin", sizeof("Plugin") - 1, set_plugin }, + { "Set", sizeof("Set") - 1, set_variable }, { NULL } }; static struct sudo_conf_data { + bool disable_coredump; const char *debug_flags; struct sudo_conf_paths paths[3]; struct plugin_info_list plugins; } sudo_conf_data = { + true, NULL, { #define SUDO_CONF_ASKPASS_IDX 0 @@ -99,6 +105,26 @@ static struct sudo_conf_data { } }; +/* + * "Set variable_name value" + */ +static bool +set_variable(const char *entry) +{ +#undef DC_LEN +#define DC_LEN (sizeof("disable_coredump") - 1) + /* Currently the only variable supported is "disable_coredump". */ + if (strncmp(entry, "disable_coredump", DC_LEN) == 0 && + isblank((unsigned char)entry[DC_LEN])) { + entry += DC_LEN + 1; + while (isblank((unsigned char)*entry)) + entry++; + sudo_conf_data.disable_coredump = atobool(entry); + } +#undef DC_LEN + return true; +} + /* * "Debug progname debug_file debug_flags" */ @@ -217,6 +243,12 @@ sudo_conf_plugins(void) return &sudo_conf_data.plugins; } +bool +sudo_conf_disable_coredump(void) +{ + return sudo_conf_data.disable_coredump; +} + /* * Reads in /etc/sudo.conf * Returns a list of plugins. diff --git a/doc/sample.sudo.conf b/doc/sample.sudo.conf index 18baa59bb..529602fb1 100644 --- a/doc/sample.sudo.conf +++ b/doc/sample.sudo.conf @@ -5,6 +5,8 @@ # Plugin plugin_name plugin_path # Path askpass /path/to/askpass # Path noexec /path/to/noexec.so +# Debug sudo /var/log/sudo_debug all@warn +# Set disable_coredump true # # Sudo plugins: # @@ -40,3 +42,13 @@ Plugin sudoers_io sudoers.so # if you rename or move the sudo_noexec.so file. # #Path noexec /usr/libexec/sudo_noexec.so + +# +# Core dumps: +# +# By default, sudo disables core dumps while it is executing (they +# are re-enabled for the command that is run). +# To aid in debugging sudo problems, you may wish to enable core +# dumps by setting "disable_coredump" to false. +# +#Set disable_coredump false diff --git a/doc/sudo.pod b/doc/sudo.pod index b6e5915f3..f35930fd9 100644 --- a/doc/sudo.pod +++ b/doc/sudo.pod @@ -425,6 +425,7 @@ which corresponds to the following F<@sysconfdir@/sudo.conf> file. # Path askpass /path/to/askpass # Path noexec /path/to/noexec.so # Debug sudo /var/log/sudo_debug all@warn + # Set disable_coredump true # # The plugin_path is relative to @prefix@/libexec unless # fully qualified. @@ -553,6 +554,20 @@ commands via B to verify that the command does not inadvertently give the user an effective root shell. For more information, please see the C section in L. +To prevent the disclosure of potentially sensitive information, +B disables core dumps by default while it is executing (they +are re-enabled for the command that is run). To aid in debugging +B crashes, you may wish to re-enable core dumps by setting +"disable_coredump" to false in the F<@sysconfdir@/sudo.conf> file. + + Set disable_coredump false + +Note that by default, most operating systems disable core dumps +from setuid programs, which includes B. To actually get a +B core file you may need to enable core dumps for setuid +processes. On BSD and Linux systems this is accomplished via the +sysctl command, on Solaris the coreadm command can be used. + =head1 ENVIRONMENT B utilizes the following environment variables. The security diff --git a/include/sudo_conf.h b/include/sudo_conf.h index 7bd4489e1..6efc302f8 100644 --- a/include/sudo_conf.h +++ b/include/sudo_conf.h @@ -35,5 +35,6 @@ const char *sudo_conf_askpass_path(void); const char *sudo_conf_noexec_path(void); const char *sudo_conf_debug_flags(void); struct plugin_info_list *sudo_conf_plugins(void); +bool sudo_conf_disable_coredump(void); #endif /* _SUDO_CONF_H */ diff --git a/src/sudo.c b/src/sudo.c index 0efaee091..d80a204b0 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -137,9 +137,9 @@ static void iolog_close(struct plugin_container *plugin, int exit_status, int error); static int iolog_show_version(struct plugin_container *plugin, int verbose); -#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) +#ifdef RLIMIT_CORE static struct rlimit corelimit; -#endif /* RLIMIT_CORE && !SUDO_DEVEL */ +#endif /* RLIMIT_CORE */ #if defined(__linux__) static struct rlimit nproclimit; #endif @@ -188,10 +188,9 @@ main(int argc, char *argv[], char *envp[]) if (geteuid() != 0) errorx(1, _("must be setuid root")); - /* Reset signal mask, disable core dumps and make sure fds 0-2 are open. */ + /* Reset signal mask and make sure fds 0-2 are open. */ (void) sigemptyset(&mask); (void) sigprocmask(SIG_SETMASK, &mask, NULL); - disable_coredumps(); fix_fds(); /* Fill in user_info with user name, uid, cwd, etc. */ @@ -201,6 +200,9 @@ main(int argc, char *argv[], char *envp[]) /* Read sudo.conf. */ sudo_conf_read(); + /* Disable core dumps if not enabled in sudo.conf. */ + disable_coredumps(); + /* Parse command line arguments. */ sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add); sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_mode %d", sudo_mode); @@ -287,9 +289,10 @@ main(int argc, char *argv[], char *envp[]) if (ISSET(sudo_mode, MODE_BACKGROUND)) SET(command_details.flags, CD_BACKGROUND); /* Restore coredumpsize resource limit before running. */ -#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) - (void) setrlimit(RLIMIT_CORE, &corelimit); -#endif /* RLIMIT_CORE && !SUDO_DEVEL */ +#ifdef RLIMIT_CORE + if (sudo_conf_disable_coredump()) + (void) setrlimit(RLIMIT_CORE, &corelimit); +#endif /* RLIMIT_CORE */ if (ISSET(command_details.flags, CD_SUDOEDIT)) { exitcode = sudo_edit(&command_details); } else { @@ -722,7 +725,7 @@ command_info_to_details(char * const info[], struct command_details *details) static void disable_coredumps(void) { -#if defined(__linux__) || (defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)) +#if defined(__linux__) || defined(RLIMIT_CORE) struct rlimit rl; #endif debug_decl(disable_coredumps, SUDO_DEBUG_UTIL) @@ -741,15 +744,17 @@ disable_coredumps(void) (void)setrlimit(RLIMIT_NPROC, &rl); } #endif /* __linux__ */ -#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) +#ifdef RLIMIT_CORE /* - * Turn off core dumps. + * Turn off core dumps? */ - (void) getrlimit(RLIMIT_CORE, &corelimit); - memcpy(&rl, &corelimit, sizeof(struct rlimit)); - rl.rlim_cur = 0; - (void) setrlimit(RLIMIT_CORE, &rl); -#endif /* RLIMIT_CORE && !SUDO_DEVEL */ + 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); + } +#endif /* RLIMIT_CORE */ debug_return; }