Add support for disabling exec via solaris privileges.

Includes preparation for moving noexec support out of sudoers
and into front end as documented.
This commit is contained in:
Todd C. Miller
2011-03-10 14:24:10 -05:00
parent 7599034e69
commit c7a7d31905
10 changed files with 63 additions and 38 deletions

View File

@@ -382,6 +382,9 @@
/* Define to 1 if you have the `posix_openpt' function. */ /* Define to 1 if you have the `posix_openpt' function. */
#undef HAVE_POSIX_OPENPT #undef HAVE_POSIX_OPENPT
/* Define to 1 if you have the `priv_set' function. */
#undef HAVE_PRIV_SET
/* Define to 1 if you have the <project.h> header file. */ /* Define to 1 if you have the <project.h> header file. */
#undef HAVE_PROJECT_H #undef HAVE_PROJECT_H

11
configure vendored
View File

@@ -12974,6 +12974,17 @@ case "$host" in
: ${mansectform='4'} : ${mansectform='4'}
: ${with_rpath='yes'} : ${with_rpath='yes'}
test -z "$with_pam" && AUTH_EXCL_DEF="PAM" test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
for ac_func in priv_set
do :
ac_fn_c_check_func "$LINENO" "priv_set" "ac_cv_func_priv_set"
if test "x$ac_cv_func_priv_set" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PRIV_SET 1
_ACEOF
fi
done
;; ;;
*-*-aix*) *-*-aix*)
# To get all prototypes (so we pass -Wall) # To get all prototypes (so we pass -Wall)

View File

@@ -1462,6 +1462,7 @@ case "$host" in
: ${mansectform='4'} : ${mansectform='4'}
: ${with_rpath='yes'} : ${with_rpath='yes'}
test -z "$with_pam" && AUTH_EXCL_DEF="PAM" test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
AC_CHECK_FUNCS(priv_set)
;; ;;
*-*-aix*) *-*-aix*)
# To get all prototypes (so we pass -Wall) # To get all prototypes (so we pass -Wall)

View File

@@ -433,7 +433,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
def_env_reset = FALSE; def_env_reset = FALSE;
/* Build a new environment that avoids any nasty bits. */ /* Build a new environment that avoids any nasty bits. */
rebuild_env(def_noexec); rebuild_env(def_noexec); /* XXX - move noexec bits */
/* Require a password if sudoers says so. */ /* Require a password if sudoers says so. */
if (def_authenticate) { if (def_authenticate) {
@@ -533,6 +533,9 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
command_info[info_len++] = estrdup("iolog_compress=true"); command_info[info_len++] = estrdup("iolog_compress=true");
} }
if (def_noexec)
command_info[info_len++] = estrdup("noexec=true");
log_allowed(validated); log_allowed(validated);
if (ISSET(sudo_mode, MODE_CHECK)) if (ISSET(sudo_mode, MODE_CHECK))
rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw); rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);

View File

@@ -107,8 +107,7 @@ my_execve(const char *path, char *const argv[], char *const envp[])
* Fork and execute a command, returns the child's pid. * Fork and execute a command, returns the child's pid.
* Sends errno back on sv[1] if execve() fails. * Sends errno back on sv[1] if execve() fails.
*/ */
static int fork_cmnd(struct command_details *details, char *argv[], static int fork_cmnd(struct command_details *details, int sv[2])
char *envp[], int sv[2])
{ {
struct command_status cstat; struct command_status cstat;
sigaction_t sa; sigaction_t sa;
@@ -138,10 +137,10 @@ static int fork_cmnd(struct command_details *details, char *argv[],
closefrom(details->closefrom); closefrom(details->closefrom);
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
if (ISSET(details->flags, CD_RBAC_ENABLED)) if (ISSET(details->flags, CD_RBAC_ENABLED))
selinux_execve(details->command, argv, envp); selinux_execve(details->command, details->argv, details->envp);
else else
#endif #endif
my_execve(details->command, argv, envp); my_execve(details->command, details->argv, details->envp);
} }
cstat.type = CMD_ERRNO; cstat.type = CMD_ERRNO;
cstat.val = errno; cstat.val = errno;
@@ -201,8 +200,7 @@ restore_signals(void)
* we fact that we have two different controlling terminals to deal with. * we fact that we have two different controlling terminals to deal with.
*/ */
int int
sudo_execve(struct command_details *details, char *argv[], char *envp[], sudo_execve(struct command_details *details, struct command_status *cstat)
struct command_status *cstat)
{ {
int maxfd, n, nready, sv[2], log_io = FALSE; int maxfd, n, nready, sv[2], log_io = FALSE;
fd_set *fdsr, *fdsw; fd_set *fdsr, *fdsw;
@@ -279,9 +277,9 @@ sudo_execve(struct command_details *details, char *argv[], char *envp[],
* to and from pty. Adjusts maxfd as needed. * to and from pty. Adjusts maxfd as needed.
*/ */
if (log_io) if (log_io)
child = fork_pty(details, argv, envp, sv, &maxfd); child = fork_pty(details, sv, &maxfd);
else else
child = fork_cmnd(details, argv, envp, sv); child = fork_cmnd(details, sv);
close(sv[1]); close(sv[1]);
/* Set command timeout if specified. */ /* Set command timeout if specified. */

View File

@@ -108,10 +108,8 @@ static sigset_t ttyblock;
static struct io_buffer *iobufs; static struct io_buffer *iobufs;
static void flush_output(void); static void flush_output(void);
static int exec_monitor(struct command_details *details, char *argv[], static int exec_monitor(struct command_details *details, int backchannel);
char *envp[], int backchannel); static void exec_pty(struct command_details *detail);
static void exec_pty(struct command_details *detail, char *argv[],
char *envp[]);
static void sigwinch(int s); static void sigwinch(int s);
static void sync_ttysize(int src, int dst); static void sync_ttysize(int src, int dst);
static void deliver_signal(pid_t pid, int signo); static void deliver_signal(pid_t pid, int signo);
@@ -640,8 +638,7 @@ perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat)
* Returns the child pid. * Returns the child pid.
*/ */
int int
fork_pty(struct command_details *details, char *argv[], char *envp[], fork_pty(struct command_details *details, int sv[], int *maxfd)
int sv[], int *maxfd)
{ {
struct command_status cstat; struct command_status cstat;
struct io_buffer *iob; struct io_buffer *iob;
@@ -758,7 +755,7 @@ fork_pty(struct command_details *details, char *argv[], char *envp[],
close(io_pipe[STDOUT_FILENO][0]); close(io_pipe[STDOUT_FILENO][0]);
if (io_pipe[STDERR_FILENO][0]) if (io_pipe[STDERR_FILENO][0])
close(io_pipe[STDERR_FILENO][0]); close(io_pipe[STDERR_FILENO][0]);
exec_monitor(details, argv, envp, sv[1]); exec_monitor(details, sv[1]);
} }
cstat.type = CMD_ERRNO; cstat.type = CMD_ERRNO;
cstat.val = errno; cstat.val = errno;
@@ -973,8 +970,7 @@ handle_sigchld(int backchannel, struct command_status *cstat)
* Returns an error if fork(2) fails, else calls _exit(2). * Returns an error if fork(2) fails, else calls _exit(2).
*/ */
static int static int
exec_monitor(struct command_details *details, char *argv[], char *envp[], exec_monitor(struct command_details *details, int backchannel)
int backchannel)
{ {
struct command_status cstat; struct command_status cstat;
struct timeval tv; struct timeval tv;
@@ -1062,7 +1058,7 @@ exec_monitor(struct command_details *details, char *argv[], char *envp[],
restore_signals(); restore_signals();
/* setup tty and exec command */ /* setup tty and exec command */
exec_pty(details, argv, envp); exec_pty(details);
cstat.type = CMD_ERRNO; cstat.type = CMD_ERRNO;
cstat.val = errno; cstat.val = errno;
if (write(errpipe[1], &cstat, sizeof(cstat)) == -1) if (write(errpipe[1], &cstat, sizeof(cstat)) == -1)
@@ -1258,7 +1254,7 @@ flush_output(void)
* Returns only if execve() fails. * Returns only if execve() fails.
*/ */
static void static void
exec_pty(struct command_details *details, char *argv[], char *envp[]) exec_pty(struct command_details *details)
{ {
pid_t self = getpid(); pid_t self = getpid();
@@ -1291,10 +1287,10 @@ exec_pty(struct command_details *details, char *argv[], char *envp[])
closefrom(details->closefrom); closefrom(details->closefrom);
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
if (ISSET(details->flags, CD_RBAC_ENABLED)) if (ISSET(details->flags, CD_RBAC_ENABLED))
selinux_execve(details->command, argv, envp); selinux_execve(details->command, details->argv, details->envp);
else else
#endif #endif
my_execve(details->command, argv, envp); my_execve(details->command, details->argv, details->envp);
} }
/* /*

View File

@@ -86,6 +86,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 HAVE_PRIV_SET
# include <priv.h>
#endif
#include "sudo.h" #include "sudo.h"
#include "sudo_plugin.h" #include "sudo_plugin.h"
@@ -271,6 +274,8 @@ main(int argc, char *argv[], char *envp[])
} }
} }
command_info_to_details(command_info, &command_details); command_info_to_details(command_info, &command_details);
command_details.argv = argv_out;
command_details.envp = user_env_out;
if (ISSET(sudo_mode, MODE_BACKGROUND)) if (ISSET(sudo_mode, MODE_BACKGROUND))
SET(command_details.flags, CD_BACKGROUND); SET(command_details.flags, CD_BACKGROUND);
/* Restore coredumpsize resource limit before running. */ /* Restore coredumpsize resource limit before running. */
@@ -278,7 +283,7 @@ main(int argc, char *argv[], char *envp[])
(void) setrlimit(RLIMIT_CORE, &corelimit); (void) setrlimit(RLIMIT_CORE, &corelimit);
#endif /* RLIMIT_CORE && !SUDO_DEVEL */ #endif /* RLIMIT_CORE && !SUDO_DEVEL */
if (ISSET(command_details.flags, CD_SUDOEDIT)) { if (ISSET(command_details.flags, CD_SUDOEDIT)) {
exitcode = sudo_edit(&command_details, argv_out, user_env_out); exitcode = sudo_edit(&command_details);
} else { } else {
if (ISSET(sudo_mode, MODE_SHELL)) { if (ISSET(sudo_mode, MODE_SHELL)) {
/* Escape meta chars if running a shell with args. */ /* Escape meta chars if running a shell with args. */
@@ -286,7 +291,7 @@ main(int argc, char *argv[], char *envp[])
argv_out[2] != NULL && argv_out[3] == NULL) argv_out[2] != NULL && argv_out[3] == NULL)
argv_out[2] = escape_cmnd(argv_out[2]); argv_out[2] = escape_cmnd(argv_out[2]);
} }
exitcode = run_command(&command_details, argv_out, user_env_out); exitcode = run_command(&command_details);
} }
/* The close method was called by sudo_edit/run_command. */ /* The close method was called by sudo_edit/run_command. */
break; break;
@@ -860,6 +865,14 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
} }
} }
/* XXX - should do env-based noexec here too */
#ifdef HAVE_PRIV_SET
if (ISSET(details->flags, CD_NOEXEC)) {
if (priv_set(PRIV_OFF, PRIV_LIMIT, "PRIV_PROC_EXEC", NULL) == -1)
warning("unable to remove PRIV_PROC_EXEC from PRIV_LIMIT");
}
#endif /* HAVE_PRIV_SET */
#ifdef HAVE_SETRESUID #ifdef HAVE_SETRESUID
if (setresuid(details->uid, details->euid, details->euid) != 0) { if (setresuid(details->uid, details->euid, details->euid) != 0) {
warning("unable to change to runas uid (%u, %u)", details->uid, warning("unable to change to runas uid (%u, %u)", details->uid,
@@ -943,7 +956,7 @@ escape_cmnd(const char *src)
* Run the command and wait for it to complete. * Run the command and wait for it to complete.
*/ */
int int
run_command(struct command_details *details, char *argv[], char *envp[]) run_command(struct command_details *details)
{ {
struct plugin_container *plugin; struct plugin_container *plugin;
struct command_status cstat; struct command_status cstat;
@@ -952,7 +965,7 @@ run_command(struct command_details *details, char *argv[], char *envp[])
cstat.type = CMD_INVALID; cstat.type = CMD_INVALID;
cstat.val = 0; cstat.val = 0;
sudo_execve(details, argv, envp, &cstat); sudo_execve(details, &cstat);
switch (cstat.type) { switch (cstat.type) {
case CMD_ERRNO: case CMD_ERRNO:

View File

@@ -139,6 +139,8 @@ struct command_details {
const char *chroot; const char *chroot;
const char *selinux_role; const char *selinux_role;
const char *selinux_type; const char *selinux_type;
char **argv;
char **envp;
}; };
/* Status passed between parent and child via socketpair */ /* Status passed between parent and child via socketpair */
@@ -165,8 +167,7 @@ extern const char *askpass_path;
void zero_bytes(volatile void *, size_t); void zero_bytes(volatile void *, size_t);
/* exec.c */ /* exec.c */
int sudo_execve(struct command_details *details, char *argv[], char *envp[], int sudo_execve(struct command_details *details, struct command_status *cstat);
struct command_status *cstat);
void save_signals(void); void save_signals(void);
void restore_signals(void); void restore_signals(void);
@@ -196,15 +197,14 @@ void get_ttysize(int *rowp, int *colp);
/* sudo.c */ /* sudo.c */
int exec_setup(struct command_details *details, const char *ptyname, int ptyfd); int exec_setup(struct command_details *details, const char *ptyname, int ptyfd);
int run_command(struct command_details *details, char *argv[], int run_command(struct command_details *details);
char *envp[]);
void sudo_debug(int level, const char *format, ...) __printflike(2, 3); void sudo_debug(int level, const char *format, ...) __printflike(2, 3);
extern int debug_level; extern int debug_level;
extern const char *list_user, *runas_user, *runas_group; extern const char *list_user, *runas_user, *runas_group;
extern struct user_details user_details; extern struct user_details user_details;
/* sudo_edit.c */ /* sudo_edit.c */
int sudo_edit(struct command_details *details, char *argv[], char *envp[]); int sudo_edit(struct command_details *details);
/* parse_args.c */ /* parse_args.c */
void usage(int); void usage(int);

View File

@@ -82,7 +82,7 @@ switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
* Wrapper to allow users to edit privileged files with their own uid. * Wrapper to allow users to edit privileged files with their own uid.
*/ */
int int
sudo_edit(struct command_details *command_details, char *argv[], char *envp[]) sudo_edit(struct command_details *command_details)
{ {
struct command_details editor_details; struct command_details editor_details;
ssize_t nread, nwritten; ssize_t nread, nwritten;
@@ -128,7 +128,7 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
* The user's editor must be separated from the files to be * The user's editor must be separated from the files to be
* edited by a "--" option. * edited by a "--" option.
*/ */
for (ap = argv; *ap != NULL; ap++) { for (ap = command_details->argv; *ap != NULL; ap++) {
if (files) if (files)
nfiles++; nfiles++;
else if (strcmp(*ap, "--") == 0) else if (strcmp(*ap, "--") == 0)
@@ -238,7 +238,7 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
nargc = editor_argc + nfiles; nargc = editor_argc + nfiles;
nargv = (char **) emalloc2(nargc + 1, sizeof(char *)); nargv = (char **) emalloc2(nargc + 1, sizeof(char *));
for (ac = 0; ac < editor_argc; ac++) for (ac = 0; ac < editor_argc; ac++)
nargv[ac] = argv[ac]; nargv[ac] = command_details->argv[ac];
for (i = 0; i < nfiles && ac < nargc; ) for (i = 0; i < nfiles && ac < nargc; )
nargv[ac++] = tf[i++].tfile; nargv[ac++] = tf[i++].tfile;
nargv[ac] = NULL; nargv[ac] = NULL;
@@ -255,7 +255,8 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
editor_details.egid = user_details.gid; editor_details.egid = user_details.gid;
editor_details.ngroups = user_details.ngroups; editor_details.ngroups = user_details.ngroups;
editor_details.groups = user_details.groups; editor_details.groups = user_details.groups;
rval = run_command(&editor_details, nargv, envp); editor_details.argv = nargv;
rval = run_command(&editor_details);
gettimeofday(&tv2, NULL); gettimeofday(&tv2, NULL);
/* Copy contents of temp files to real ones */ /* Copy contents of temp files to real ones */
@@ -345,7 +346,7 @@ cleanup:
* Must have the ability to change the effective uid to use sudoedit. * Must have the ability to change the effective uid to use sudoedit.
*/ */
int int
sudo_edit(struct command_details *command_details, char *argv[], char *envp[]) sudo_edit(struct command_details *command_details)
{ {
return 1; return 1;
} }

View File

@@ -32,8 +32,7 @@ int my_execve(const char *path, char *const argv[], char *const envp[]);
int pipe_nonblock(int fds[2]); int pipe_nonblock(int fds[2]);
/* exec_pty.c */ /* exec_pty.c */
int fork_pty(struct command_details *details, char *argv[], char *envp[], int fork_pty(struct command_details *details, int sv[], int *maxfd);
int sv[], int *maxfd);
int perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat); int perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat);
int suspend_parent(int signo); int suspend_parent(int signo);
void fd_set_iobs(fd_set *fdsr, fd_set *fdsw); void fd_set_iobs(fd_set *fdsr, fd_set *fdsw);