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:
@@ -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
11
configure
vendored
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
14
src/exec.c
14
src/exec.c
@@ -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. */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
21
src/sudo.c
21
src/sudo.c
@@ -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:
|
||||
|
10
src/sudo.h
10
src/sudo.h
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user