mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-22 01:49:11 +00:00
Set resource limits in the sudo process to unlimited.
We don't want sudo to be limited by the caller's resource limits. The original resource limits are restore before session setup.
This commit is contained in:
parent
f57e2d04a3
commit
e80079eaa8
1
MANIFEST
1
MANIFEST
@ -780,6 +780,7 @@ src/exec_nopty.c
|
||||
src/exec_pty.c
|
||||
src/get_pty.c
|
||||
src/hooks.c
|
||||
src/limits.c
|
||||
src/load_plugins.c
|
||||
src/net_ifs.c
|
||||
src/openbsd.c
|
||||
|
@ -957,9 +957,13 @@ snprintf.i: $(srcdir)/snprintf.c $(incdir)/sudo_compat.h \
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
snprintf.plog: snprintf.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/snprintf.c --i-file $< --output-file $@
|
||||
str2sig.lo: $(srcdir)/str2sig.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
|
||||
str2sig.lo: $(srcdir)/str2sig.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
|
||||
$(top_builddir)/config.h
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/str2sig.c
|
||||
str2sig.i: $(srcdir)/str2sig.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
|
||||
str2sig.i: $(srcdir)/str2sig.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
|
||||
$(top_builddir)/config.h
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
str2sig.plog: str2sig.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/str2sig.c --i-file $< --output-file $@
|
||||
|
@ -121,8 +121,8 @@ SHELL = @SHELL@
|
||||
PROGS = @PROGS@
|
||||
|
||||
OBJS = conversation.o env_hooks.o exec.o exec_common.o exec_monitor.o \
|
||||
exec_nopty.o exec_pty.o get_pty.o hooks.o net_ifs.o load_plugins.o \
|
||||
parse_args.o preserve_fds.o signal.o sudo.o sudo_edit.o \
|
||||
exec_nopty.o exec_pty.o get_pty.o hooks.o limits.o load_plugins.o \
|
||||
net_ifs.o parse_args.o preserve_fds.o signal.o sudo.o sudo_edit.o \
|
||||
tcsetpgrp_nobg.o tgetpass.o ttyname.o utmp.o @SUDO_OBJS@
|
||||
|
||||
IOBJS = $(OBJS:.o=.i) sesh.i
|
||||
@ -472,6 +472,20 @@ hooks.i: $(srcdir)/hooks.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
hooks.plog: hooks.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/hooks.c --i-file $< --output-file $@
|
||||
limits.o: $(srcdir)/limits.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
|
||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/limits.c
|
||||
limits.i: $(srcdir)/limits.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
|
||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
limits.plog: limits.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/limits.c --i-file $< --output-file $@
|
||||
load_plugins.o: $(srcdir)/load_plugins.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \
|
||||
|
49
src/exec.c
49
src/exec.c
@ -56,50 +56,6 @@
|
||||
#include "sudo_plugin.h"
|
||||
#include "sudo_plugin_int.h"
|
||||
|
||||
#ifdef __linux__
|
||||
static struct rlimit nproclimit;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unlimit the number of processes since Linux's setuid() will
|
||||
* apply resource limits when changing uid and return EAGAIN if
|
||||
* nproc would be exceeded by the uid switch.
|
||||
*/
|
||||
static void
|
||||
unlimit_nproc(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
struct rlimit rl;
|
||||
debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0)
|
||||
sudo_warn("getrlimit");
|
||||
rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
|
||||
if (setrlimit(RLIMIT_NPROC, &rl) != 0) {
|
||||
rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max;
|
||||
if (setrlimit(RLIMIT_NPROC, &rl) != 0)
|
||||
sudo_warn("setrlimit");
|
||||
}
|
||||
debug_return;
|
||||
#endif /* __linux__ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore saved value of RLIMIT_NPROC.
|
||||
*/
|
||||
static void
|
||||
restore_nproc(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
debug_decl(restore_nproc, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0)
|
||||
sudo_warn("setrlimit");
|
||||
|
||||
debug_return;
|
||||
#endif /* __linux__ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the execution environment immediately prior to the call to execve().
|
||||
* Group setup is performed by policy_init_session(), called earlier.
|
||||
@ -401,11 +357,10 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore coredumpsize resource limit before running.
|
||||
* Restore resource limits before running.
|
||||
* We must do this *before* calling the PAM session module.
|
||||
*/
|
||||
if (sudo_conf_disable_coredump())
|
||||
disable_coredump(true);
|
||||
restore_limits();
|
||||
|
||||
/*
|
||||
* Run the command in a new pty if there is an I/O plugin or the policy
|
||||
|
200
src/limits.c
Normal file
200
src/limits.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1999-2019 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
#include <unistd.h>
|
||||
#ifdef __linux__
|
||||
# include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include "sudo.h"
|
||||
|
||||
static struct saved_limit {
|
||||
int resource;
|
||||
bool saved;
|
||||
struct rlimit limit;
|
||||
} saved_limits[] = {
|
||||
#ifdef RLIMIT_AS
|
||||
{ RLIMIT_AS },
|
||||
#endif
|
||||
{ RLIMIT_CPU },
|
||||
{ RLIMIT_DATA },
|
||||
{ RLIMIT_FSIZE },
|
||||
{ RLIMIT_NOFILE },
|
||||
{ RLIMIT_NPROC },
|
||||
{ RLIMIT_RSS },
|
||||
{ RLIMIT_STACK }
|
||||
};
|
||||
|
||||
static struct rlimit corelimit;
|
||||
static bool coredump_disabled;
|
||||
#ifdef __linux__
|
||||
static struct rlimit nproclimit;
|
||||
static int dumpflag;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable core dumps to avoid dropping a core with user password in it.
|
||||
* Not all operating systems disable core dumps for setuid processes.
|
||||
*/
|
||||
void
|
||||
disable_coredump(void)
|
||||
{
|
||||
struct rlimit rl = { 0, 0 };
|
||||
debug_decl(disable_coredump, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (getrlimit(RLIMIT_CORE, &corelimit) == -1)
|
||||
sudo_warn("getrlimit(RLIMIT_CORE)");
|
||||
if (setrlimit(RLIMIT_CORE, &rl) == -1)
|
||||
sudo_warn("setrlimit(RLIMIT_CORE)");
|
||||
#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__ */
|
||||
coredump_disabled = true;
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore core resource limit before executing the command.
|
||||
*/
|
||||
static void
|
||||
restore_coredump(void)
|
||||
{
|
||||
debug_decl(restore_coredump, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (coredump_disabled) {
|
||||
if (setrlimit(RLIMIT_CORE, &corelimit) == -1)
|
||||
sudo_warn("setrlimit(RLIMIT_CORE)");
|
||||
#ifdef __linux__
|
||||
(void) prctl(PR_SET_DUMPABLE, dumpflag, 0, 0, 0);
|
||||
#endif /* __linux__ */
|
||||
}
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlimit the number of processes since Linux's setuid() will
|
||||
* apply resource limits when changing uid and return EAGAIN if
|
||||
* nproc would be exceeded by the uid switch.
|
||||
*
|
||||
* This function is called *after* session setup and before the
|
||||
* final setuid() call.
|
||||
*/
|
||||
void
|
||||
unlimit_nproc(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
|
||||
debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0)
|
||||
sudo_warn("getrlimit(RLIMIT_NPROC)");
|
||||
if (setrlimit(RLIMIT_NPROC, &rl) == -1) {
|
||||
rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max;
|
||||
if (setrlimit(RLIMIT_NPROC, &rl) != 0)
|
||||
sudo_warn("setrlimit(RLIMIT_NPROC)");
|
||||
}
|
||||
debug_return;
|
||||
#endif /* __linux__ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore saved value of RLIMIT_NPROC before execve().
|
||||
*/
|
||||
void
|
||||
restore_nproc(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
debug_decl(restore_nproc, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0)
|
||||
sudo_warn("setrlimit(RLIMIT_NPROC)");
|
||||
|
||||
debug_return;
|
||||
#endif /* __linux__ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlimit resource limits so sudo is not limited by, e.g.
|
||||
* stack, data or file table sizes.
|
||||
*/
|
||||
void
|
||||
unlimit_sudo(void)
|
||||
{
|
||||
struct rlimit inf = { RLIM_INFINITY, RLIM_INFINITY };
|
||||
unsigned int idx;
|
||||
debug_decl(unlimit_sudo, SUDO_DEBUG_UTIL)
|
||||
|
||||
/* Set resource limits to unlimited and stash the old values. */
|
||||
for (idx = 0; idx < nitems(saved_limits); idx++) {
|
||||
struct saved_limit *lim = &saved_limits[idx];
|
||||
if (getrlimit(lim->resource, &lim->limit) == -1)
|
||||
continue;
|
||||
lim->saved = true;
|
||||
if (setrlimit(lim->resource, &inf) == -1) {
|
||||
struct rlimit rl = lim->limit;
|
||||
rl.rlim_cur = rl.rlim_max;
|
||||
if (setrlimit(lim->resource, &rl) == -1)
|
||||
sudo_warn("setrlimit(%d)", lim->resource);
|
||||
}
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore resource limits modified by unlimit_sudo() and disable_coredump().
|
||||
*/
|
||||
void
|
||||
restore_limits(void)
|
||||
{
|
||||
unsigned int idx;
|
||||
debug_decl(restore_limits, SUDO_DEBUG_UTIL)
|
||||
|
||||
/* Restore resource limits to saved values. */
|
||||
for (idx = 0; idx < nitems(saved_limits); idx++) {
|
||||
struct saved_limit *lim = &saved_limits[idx];
|
||||
if (lim->saved) {
|
||||
if (setrlimit(lim->resource, &lim->limit) == -1)
|
||||
sudo_warn("setrlimit(%d)", lim->resource);
|
||||
}
|
||||
}
|
||||
restore_coredump();
|
||||
|
||||
debug_return;
|
||||
}
|
51
src/sudo.c
51
src/sudo.c
@ -31,7 +31,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/resource.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
@ -64,9 +63,6 @@
|
||||
# endif /* __hpux */
|
||||
# include <prot.h>
|
||||
#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
|
||||
#ifdef __linux__
|
||||
# include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include <sudo_usage.h>
|
||||
#include "sudo.h"
|
||||
@ -146,6 +142,11 @@ main(int argc, char *argv[], char *envp[])
|
||||
sigset_t mask;
|
||||
debug_decl_vars(main, SUDO_DEBUG_MAIN)
|
||||
|
||||
initprogname(argc > 0 ? argv[0] : "sudo");
|
||||
|
||||
/* Crank resource limits to unlimited. */
|
||||
unlimit_sudo();
|
||||
|
||||
/* Make sure fds 0-2 are open and do OS-specific initialization. */
|
||||
fix_fds();
|
||||
os_init(argc, argv, envp);
|
||||
@ -192,7 +193,7 @@ main(int argc, char *argv[], char *envp[])
|
||||
|
||||
/* Disable core dumps if not enabled in sudo.conf. */
|
||||
if (sudo_conf_disable_coredump())
|
||||
disable_coredump(false);
|
||||
disable_coredump();
|
||||
|
||||
/* Parse command line arguments. */
|
||||
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
|
||||
@ -314,7 +315,7 @@ main(int argc, char *argv[], char *envp[])
|
||||
struct sigaction sa;
|
||||
|
||||
if (WCOREDUMP(status))
|
||||
disable_coredump(false);
|
||||
disable_coredump();
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sigemptyset(&sa.sa_mask);
|
||||
@ -332,7 +333,6 @@ main(int argc, char *argv[], char *envp[])
|
||||
int
|
||||
os_init_common(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
initprogname(argc > 0 ? argv[0] : "sudo");
|
||||
#ifdef STATIC_SUDOERS_PLUGIN
|
||||
preload_static_symbols();
|
||||
#endif
|
||||
@ -900,43 +900,6 @@ sudo_check_suid(const char *sudo)
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable core dumps to avoid dropping a core with user password in it.
|
||||
* Called with restore set to true before executing the command.
|
||||
* Not all operating systems disable core dumps for setuid processes.
|
||||
*/
|
||||
void
|
||||
disable_coredump(bool restore)
|
||||
{
|
||||
struct rlimit rl;
|
||||
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__ */
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
bool
|
||||
set_user_groups(struct command_details *details)
|
||||
{
|
||||
|
@ -223,7 +223,6 @@ int policy_init_session(struct command_details *details);
|
||||
int run_command(struct command_details *details);
|
||||
int os_init_common(int argc, char *argv[], char *envp[]);
|
||||
bool gc_add(enum sudo_gc_types type, void *v);
|
||||
void disable_coredump(bool restore);
|
||||
bool set_user_groups(struct command_details *details);
|
||||
extern const char *list_user;
|
||||
extern struct user_details user_details;
|
||||
@ -287,4 +286,11 @@ void parse_preserved_fds(struct preserved_fd_list *pfds, const char *fdstr);
|
||||
/* setpgrp_nobg.c */
|
||||
int tcsetpgrp_nobg(int fd, pid_t pgrp_id);
|
||||
|
||||
/* limits.c */
|
||||
void disable_coredump();
|
||||
void restore_limits(void);
|
||||
void restore_nproc(void);
|
||||
void unlimit_nproc(void);
|
||||
void unlimit_sudo(void);
|
||||
|
||||
#endif /* SUDO_SUDO_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user