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. */
#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. */
#undef HAVE_PROJECT_H

11
configure vendored
View File

@@ -12974,6 +12974,17 @@ case "$host" in
: ${mansectform='4'}
: ${with_rpath='yes'}
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*)
# To get all prototypes (so we pass -Wall)

View File

@@ -1462,6 +1462,7 @@ case "$host" in
: ${mansectform='4'}
: ${with_rpath='yes'}
test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
AC_CHECK_FUNCS(priv_set)
;;
*-*-aix*)
# 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;
/* 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. */
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");
}
if (def_noexec)
command_info[info_len++] = estrdup("noexec=true");
log_allowed(validated);
if (ISSET(sudo_mode, MODE_CHECK))
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.
* Sends errno back on sv[1] if execve() fails.
*/
static int fork_cmnd(struct command_details *details, char *argv[],
char *envp[], int sv[2])
static int fork_cmnd(struct command_details *details, int sv[2])
{
struct command_status cstat;
sigaction_t sa;
@@ -138,10 +137,10 @@ static int fork_cmnd(struct command_details *details, char *argv[],
closefrom(details->closefrom);
#ifdef HAVE_SELINUX
if (ISSET(details->flags, CD_RBAC_ENABLED))
selinux_execve(details->command, argv, envp);
selinux_execve(details->command, details->argv, details->envp);
else
#endif
my_execve(details->command, argv, envp);
my_execve(details->command, details->argv, details->envp);
}
cstat.type = CMD_ERRNO;
cstat.val = errno;
@@ -201,8 +200,7 @@ restore_signals(void)
* we fact that we have two different controlling terminals to deal with.
*/
int
sudo_execve(struct command_details *details, char *argv[], char *envp[],
struct command_status *cstat)
sudo_execve(struct command_details *details, struct command_status *cstat)
{
int maxfd, n, nready, sv[2], log_io = FALSE;
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.
*/
if (log_io)
child = fork_pty(details, argv, envp, sv, &maxfd);
child = fork_pty(details, sv, &maxfd);
else
child = fork_cmnd(details, argv, envp, sv);
child = fork_cmnd(details, sv);
close(sv[1]);
/* Set command timeout if specified. */

View File

@@ -108,10 +108,8 @@ static sigset_t ttyblock;
static struct io_buffer *iobufs;
static void flush_output(void);
static int exec_monitor(struct command_details *details, char *argv[],
char *envp[], int backchannel);
static void exec_pty(struct command_details *detail, char *argv[],
char *envp[]);
static int exec_monitor(struct command_details *details, int backchannel);
static void exec_pty(struct command_details *detail);
static void sigwinch(int s);
static void sync_ttysize(int src, int dst);
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.
*/
int
fork_pty(struct command_details *details, char *argv[], char *envp[],
int sv[], int *maxfd)
fork_pty(struct command_details *details, int sv[], int *maxfd)
{
struct command_status cstat;
struct io_buffer *iob;
@@ -758,7 +755,7 @@ fork_pty(struct command_details *details, char *argv[], char *envp[],
close(io_pipe[STDOUT_FILENO][0]);
if (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.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).
*/
static int
exec_monitor(struct command_details *details, char *argv[], char *envp[],
int backchannel)
exec_monitor(struct command_details *details, int backchannel)
{
struct command_status cstat;
struct timeval tv;
@@ -1062,7 +1058,7 @@ exec_monitor(struct command_details *details, char *argv[], char *envp[],
restore_signals();
/* setup tty and exec command */
exec_pty(details, argv, envp);
exec_pty(details);
cstat.type = CMD_ERRNO;
cstat.val = errno;
if (write(errpipe[1], &cstat, sizeof(cstat)) == -1)
@@ -1258,7 +1254,7 @@ flush_output(void)
* Returns only if execve() fails.
*/
static void
exec_pty(struct command_details *details, char *argv[], char *envp[])
exec_pty(struct command_details *details)
{
pid_t self = getpid();
@@ -1291,10 +1287,10 @@ exec_pty(struct command_details *details, char *argv[], char *envp[])
closefrom(details->closefrom);
#ifdef HAVE_SELINUX
if (ISSET(details->flags, CD_RBAC_ENABLED))
selinux_execve(details->command, argv, envp);
selinux_execve(details->command, details->argv, details->envp);
else
#endif
my_execve(details->command, argv, envp);
my_execve(details->command, details->argv, details->envp);
}
/*

View File

@@ -86,6 +86,9 @@
# endif /* __hpux */
# include <prot.h>
#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
#ifdef HAVE_PRIV_SET
# include <priv.h>
#endif
#include "sudo.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_details.argv = argv_out;
command_details.envp = user_env_out;
if (ISSET(sudo_mode, MODE_BACKGROUND))
SET(command_details.flags, CD_BACKGROUND);
/* Restore coredumpsize resource limit before running. */
@@ -278,7 +283,7 @@ main(int argc, char *argv[], char *envp[])
(void) setrlimit(RLIMIT_CORE, &corelimit);
#endif /* RLIMIT_CORE && !SUDO_DEVEL */
if (ISSET(command_details.flags, CD_SUDOEDIT)) {
exitcode = sudo_edit(&command_details, argv_out, user_env_out);
exitcode = sudo_edit(&command_details);
} else {
if (ISSET(sudo_mode, MODE_SHELL)) {
/* 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] = 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. */
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
if (setresuid(details->uid, details->euid, details->euid) != 0) {
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.
*/
int
run_command(struct command_details *details, char *argv[], char *envp[])
run_command(struct command_details *details)
{
struct plugin_container *plugin;
struct command_status cstat;
@@ -952,7 +965,7 @@ run_command(struct command_details *details, char *argv[], char *envp[])
cstat.type = CMD_INVALID;
cstat.val = 0;
sudo_execve(details, argv, envp, &cstat);
sudo_execve(details, &cstat);
switch (cstat.type) {
case CMD_ERRNO:

View File

@@ -139,6 +139,8 @@ struct command_details {
const char *chroot;
const char *selinux_role;
const char *selinux_type;
char **argv;
char **envp;
};
/* Status passed between parent and child via socketpair */
@@ -165,8 +167,7 @@ extern const char *askpass_path;
void zero_bytes(volatile void *, size_t);
/* exec.c */
int sudo_execve(struct command_details *details, char *argv[], char *envp[],
struct command_status *cstat);
int sudo_execve(struct command_details *details, struct command_status *cstat);
void save_signals(void);
void restore_signals(void);
@@ -196,15 +197,14 @@ void get_ttysize(int *rowp, int *colp);
/* sudo.c */
int exec_setup(struct command_details *details, const char *ptyname, int ptyfd);
int run_command(struct command_details *details, char *argv[],
char *envp[]);
int run_command(struct command_details *details);
void sudo_debug(int level, const char *format, ...) __printflike(2, 3);
extern int debug_level;
extern const char *list_user, *runas_user, *runas_group;
extern struct user_details user_details;
/* sudo_edit.c */
int sudo_edit(struct command_details *details, char *argv[], char *envp[]);
int sudo_edit(struct command_details *details);
/* parse_args.c */
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.
*/
int
sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
sudo_edit(struct command_details *command_details)
{
struct command_details editor_details;
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
* edited by a "--" option.
*/
for (ap = argv; *ap != NULL; ap++) {
for (ap = command_details->argv; *ap != NULL; ap++) {
if (files)
nfiles++;
else if (strcmp(*ap, "--") == 0)
@@ -238,7 +238,7 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
nargc = editor_argc + nfiles;
nargv = (char **) emalloc2(nargc + 1, sizeof(char *));
for (ac = 0; ac < editor_argc; ac++)
nargv[ac] = argv[ac];
nargv[ac] = command_details->argv[ac];
for (i = 0; i < nfiles && ac < nargc; )
nargv[ac++] = tf[i++].tfile;
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.ngroups = user_details.ngroups;
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);
/* 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.
*/
int
sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
sudo_edit(struct command_details *command_details)
{
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]);
/* exec_pty.c */
int fork_pty(struct command_details *details, char *argv[], char *envp[],
int sv[], int *maxfd);
int fork_pty(struct command_details *details, int sv[], int *maxfd);
int perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat);
int suspend_parent(int signo);
void fd_set_iobs(fd_set *fdsr, fd_set *fdsw);