2 * SPDX-License-Identifier: ISC
4 * Copyright (c) 2009-2017 Todd C. Miller <Todd.Miller@sudo.ws>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * This is an open source non-commercial project. Dear PVS-Studio, please check it.
21 * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
26 #include <sys/types.h>
27 #include <sys/resource.h>
33 #endif /* HAVE_STRING_H */
36 #endif /* HAVE_STRINGS_H */
42 #ifdef HAVE_LOGIN_CAP_H
43 # include <login_cap.h>
45 # define LOGIN_SETENV 0
50 # include <sys/task.h>
54 #include "sudo_exec.h"
55 #include "sudo_event.h"
56 #include "sudo_plugin.h"
57 #include "sudo_plugin_int.h"
60 static struct rlimit nproclimit;
64 * Unlimit the number of processes since Linux's setuid() will
65 * apply resource limits when changing uid and return EAGAIN if
66 * nproc would be exceeded by the uid switch.
73 debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL)
75 if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0)
76 sudo_warn("getrlimit");
77 rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
78 if (setrlimit(RLIMIT_NPROC, &rl) != 0) {
79 rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max;
80 if (setrlimit(RLIMIT_NPROC, &rl) != 0)
81 sudo_warn("setrlimit");
84 #endif /* __linux__ */
88 * Restore saved value of RLIMIT_NPROC.
94 debug_decl(restore_nproc, SUDO_DEBUG_UTIL)
96 if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0)
97 sudo_warn("setrlimit");
100 #endif /* __linux__ */
104 * Setup the execution environment immediately prior to the call to execve().
105 * Group setup is performed by policy_init_session(), called earlier.
106 * Returns true on success and false on failure.
109 exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
112 debug_decl(exec_setup, SUDO_DEBUG_EXEC)
115 if (ISSET(details->flags, CD_RBAC_ENABLED)) {
116 if (selinux_setup(details->selinux_role, details->selinux_type,
117 ptyname ? ptyname : user_details.tty, ptyfd) == -1)
122 /* Restore coredumpsize resource limit before running. */
123 if (sudo_conf_disable_coredump())
124 disable_coredump(true);
126 if (details->pw != NULL) {
127 #ifdef HAVE_PROJECT_H
128 set_project(details->pw);
131 if (details->privs != NULL) {
132 if (setppriv(PRIV_SET, PRIV_INHERITABLE, details->privs) != 0) {
133 sudo_warn("unable to set privileges");
137 if (details->limitprivs != NULL) {
138 if (setppriv(PRIV_SET, PRIV_LIMIT, details->limitprivs) != 0) {
139 sudo_warn("unable to set limit privileges");
142 } else if (details->privs != NULL) {
143 if (setppriv(PRIV_SET, PRIV_LIMIT, details->privs) != 0) {
144 sudo_warn("unable to set limit privileges");
148 #endif /* HAVE_PRIV_SET */
150 #ifdef HAVE_GETUSERATTR
151 if (aix_prep_user(details->pw->pw_name, ptyname ? ptyname : user_details.tty) != 0) {
152 /* error message displayed by aix_prep_user */
156 #ifdef HAVE_LOGIN_CAP_H
157 if (details->login_class) {
162 * We only use setusercontext() to set the nice value and rlimits
163 * unless this is a login shell (sudo -i).
165 lc = login_getclass((char *)details->login_class);
167 sudo_warnx(U_("unknown login class %s"), details->login_class);
171 if (ISSET(details->flags, CD_LOGIN_SHELL)) {
172 /* Set everything except user, group and login name. */
173 flags = LOGIN_SETALL;
174 CLR(flags, LOGIN_SETGROUP|LOGIN_SETLOGIN|LOGIN_SETUSER|LOGIN_SETENV|LOGIN_SETPATH);
175 CLR(details->flags, CD_SET_UMASK); /* LOGIN_UMASK instead */
177 flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
179 if (setusercontext(lc, details->pw, details->pw->pw_uid, flags)) {
180 sudo_warn(U_("unable to set user context"));
181 if (details->pw->pw_uid != ROOT_UID)
185 #endif /* HAVE_LOGIN_CAP_H */
188 if (ISSET(details->flags, CD_SET_GROUPS)) {
189 /* set_user_groups() prints error message on failure. */
190 if (!set_user_groups(details))
194 if (ISSET(details->flags, CD_SET_PRIORITY)) {
195 if (setpriority(PRIO_PROCESS, 0, details->priority) != 0) {
196 sudo_warn(U_("unable to set process priority"));
200 if (ISSET(details->flags, CD_SET_UMASK))
201 (void) umask(details->umask);
202 if (details->chroot) {
203 if (chroot(details->chroot) != 0 || chdir("/") != 0) {
204 sudo_warn(U_("unable to change root to %s"), details->chroot);
210 * Unlimit the number of processes since Linux's setuid() will
211 * return EAGAIN if RLIMIT_NPROC would be exceeded by the uid switch.
215 #if defined(HAVE_SETRESUID)
216 if (setresuid(details->uid, details->euid, details->euid) != 0) {
217 sudo_warn(U_("unable to change to runas uid (%u, %u)"),
218 (unsigned int)details->uid, (unsigned int)details->euid);
221 #elif defined(HAVE_SETREUID)
222 if (setreuid(details->uid, details->euid) != 0) {
223 sudo_warn(U_("unable to change to runas uid (%u, %u)"),
224 (unsigned int)details->uid, (unsigned int)details->euid);
228 /* Cannot support real user ID that is different from effective user ID. */
229 if (setuid(details->euid) != 0) {
230 sudo_warn(U_("unable to change to runas uid (%u, %u)"),
231 (unsigned int)details->euid, (unsigned int)details->euid);
234 #endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
236 /* Restore previous value of RLIMIT_NPROC. */
240 * Only change cwd if we have chroot()ed or the policy modules
241 * specifies a different cwd. Must be done after uid change.
243 if (details->cwd != NULL) {
244 if (details->chroot || user_details.cwd == NULL ||
245 strcmp(details->cwd, user_details.cwd) != 0) {
246 /* Note: cwd is relative to the new root, if any. */
247 if (chdir(details->cwd) != 0) {
248 sudo_warn(U_("unable to change directory to %s"), details->cwd);
257 debug_return_bool(ret);
261 * Setup the execution environment and execute the command.
262 * If SELinux is enabled, run the command via sesh, otherwise
263 * execute it directly.
264 * If the exec fails, cstat is filled in with the value of errno.
267 exec_cmnd(struct command_details *details, int errfd)
269 debug_decl(exec_cmnd, SUDO_DEBUG_EXEC)
272 if (exec_setup(details, NULL, -1) == true) {
273 /* headed for execve() */
274 if (details->closefrom >= 0) {
276 unsigned char *debug_fds;
278 /* Preserve debug fds and error pipe as needed. */
279 maxfd = sudo_debug_get_fds(&debug_fds);
280 for (fd = 0; fd <= maxfd; fd++) {
281 if (sudo_isset(debug_fds, fd))
282 add_preserved_fd(&details->preserved_fds, fd);
285 add_preserved_fd(&details->preserved_fds, errfd);
287 /* Close all fds except those explicitly preserved. */
288 closefrom_except(details->closefrom, &details->preserved_fds);
291 if (ISSET(details->flags, CD_RBAC_ENABLED)) {
292 selinux_execve(details->execfd, details->command, details->argv,
293 details->envp, ISSET(details->flags, CD_NOEXEC));
297 sudo_execve(details->execfd, details->command, details->argv,
298 details->envp, ISSET(details->flags, CD_NOEXEC));
301 sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s",
302 details->command, strerror(errno));
307 * Check for caught signals sent to sudo before command execution.
308 * Also suspends the process if SIGTSTP was caught.
309 * Returns true if we should terminate, else false.
312 sudo_terminated(struct command_status *cstat)
315 bool sigtstp = false;
316 debug_decl(sudo_terminated, SUDO_DEBUG_EXEC)
318 for (signo = 0; signo < NSIG; signo++) {
319 if (signal_pending(signo)) {
325 /* Suspend below if not terminated. */
329 /* Terminal signal, do not exec command. */
330 cstat->type = CMD_WSTATUS;
331 cstat->val = signo + 128;
332 debug_return_bool(true);
341 /* Send SIGTSTP to ourselves, unblocking it if needed. */
342 memset(&sa, 0, sizeof(sa));
343 sigemptyset(&sa.sa_mask);
344 sa.sa_flags = SA_RESTART;
345 sa.sa_handler = SIG_DFL;
346 if (sudo_sigaction(SIGTSTP, &sa, NULL) != 0)
347 sudo_warn(U_("unable to set handler for signal %d"), SIGTSTP);
349 sigaddset(&set, SIGTSTP);
350 sigprocmask(SIG_UNBLOCK, &set, &oset);
351 if (kill(getpid(), SIGTSTP) != 0)
352 sudo_warn("kill(%d, SIGTSTP)", (int)getpid());
353 sigprocmask(SIG_SETMASK, &oset, NULL);
354 /* No need to restore old SIGTSTP handler. */
356 debug_return_bool(false);
359 #if SUDO_API_VERSION != SUDO_API_MKVERSION(1, 13)
360 # error "Update sudo_needs_pty() after changing the plugin API"
363 sudo_needs_pty(struct command_details *details)
365 struct plugin_container *plugin;
367 if (ISSET(details->flags, CD_USE_PTY))
370 TAILQ_FOREACH(plugin, &io_plugins, entries) {
371 if (plugin->u.io->log_ttyin != NULL ||
372 plugin->u.io->log_ttyout != NULL ||
373 plugin->u.io->log_stdin != NULL ||
374 plugin->u.io->log_stdout != NULL ||
375 plugin->u.io->log_stderr != NULL ||
376 plugin->u.io->change_winsize != NULL ||
377 plugin->u.io->log_suspend != NULL)
384 * Execute a command, potentially in a pty with I/O loggging, and
385 * wait for it to finish.
386 * This is a little bit tricky due to how POSIX job control works and
387 * we fact that we have two different controlling terminals to deal with.
390 sudo_execute(struct command_details *details, struct command_status *cstat)
392 debug_decl(sudo_execute, SUDO_DEBUG_EXEC)
394 /* If running in background mode, fork and exit. */
395 if (ISSET(details->flags, CD_BACKGROUND)) {
396 switch (sudo_debug_fork()) {
398 cstat->type = CMD_ERRNO;
400 debug_return_int(-1);
402 /* child continues without controlling terminal */
406 /* parent exits (but does not flush buffers) */
407 sudo_debug_exit_int(__func__, __FILE__, __LINE__,
408 sudo_debug_subsys, 0);
414 * Run the command in a new pty if there is an I/O plugin or the policy
415 * has requested a pty. If /dev/tty is unavailable and no I/O plugin
416 * is configured, this returns false and we run the command without a pty.
418 if (sudo_needs_pty(details)) {
419 if (exec_pty(details, cstat))
424 * If we are not running the command in a pty, we were not invoked
425 * as sudoedit, there is no command timeout and there is no close
426 * function, just exec directly. Only returns on error.
428 if (!ISSET(details->flags, CD_SET_TIMEOUT|CD_SUDOEDIT) &&
429 policy_plugin.u.policy->close == NULL) {
430 if (!sudo_terminated(cstat)) {
431 exec_cmnd(details, -1);
432 cstat->type = CMD_ERRNO;
439 * Run the command in the existing tty (if any) and wait for it to finish.
441 exec_nopty(details, cstat);
444 /* The caller will run any plugin close functions. */
445 debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
449 * Kill command with increasing urgency.
452 terminate_command(pid_t pid, bool use_pgrp)
454 debug_decl(terminate_command, SUDO_DEBUG_EXEC);
456 /* Avoid killing more than a single process or process group. */
461 * Note that SIGCHLD will interrupt the sleep()
464 sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGHUP", (int)pid);
466 sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGTERM", (int)pid);
467 killpg(pid, SIGTERM);
469 sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGKILL", (int)pid);
470 killpg(pid, SIGKILL);
472 sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGHUP", (int)pid);
474 sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGTERM", (int)pid);
477 sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGKILL", (int)pid);