Add selinux_enabled flag into struct command_details and

set it in command_info_to_details().
Return an error from selinux_setup() instead of exiting.
Call selinux_setup() from exec_setup().
This commit is contained in:
Todd C. Miller
2010-06-08 17:59:18 -04:00
parent ecfb70b056
commit edd34a2d7e
5 changed files with 67 additions and 55 deletions

View File

@@ -59,9 +59,6 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#ifdef HAVE_SELINUX
# include <selinux/selinux.h>
#endif
/* XXX - move to compat */
#if !defined(NSIG)
@@ -113,7 +110,7 @@ my_execve(const char *path, char *const argv[], char *const envp[])
* Sends errno back on sv[1] if execve() fails.
*/
static int fork_cmnd(struct command_details *details, char *argv[],
char *envp[], int sv[2], int rbac_enabled)
char *envp[], int sv[2])
{
struct command_status cstat;
int pid;
@@ -127,18 +124,12 @@ static int fork_cmnd(struct command_details *details, char *argv[],
/* child */
close(sv[0]);
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
#ifdef HAVE_SELINUX
if (rbac_enabled) {
selinux_setup(details->selinux_role, details->selinux_type,
user_details.tty, -1);
}
#endif
if (exec_setup(details) == TRUE) {
if (exec_setup(details, NULL, -1) == TRUE) {
/* headed for execve() */
if (details->closefrom >= 0)
closefrom(details->closefrom);
#ifdef HAVE_SELINUX
if (rbac_enabled)
if (details->selinux_enabled)
selinux_execve(details->command, argv, envp);
else
#endif
@@ -164,7 +155,6 @@ sudo_execve(struct command_details *details, char *argv[], char *envp[],
sigaction_t sa;
fd_set *fdsr, *fdsw;
int maxfd, n, nready, status, sv[2];
int rbac_enabled = 0;
int log_io = 0;
pid_t child;
@@ -176,10 +166,6 @@ sudo_execve(struct command_details *details, char *argv[], char *envp[],
pty_setup(details->euid);
}
#ifdef HAVE_SELINUX
rbac_enabled = is_selinux_enabled() > 0 && details->selinux_role != NULL;
#endif
/*
* We communicate with the child over a bi-directional pair of sockets.
* Parent sends signal info to child and child sends back wait status.
@@ -209,9 +195,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, rbac_enabled, &maxfd);
child = fork_pty(details, argv, envp, sv, &maxfd);
else
child = fork_cmnd(details, argv, envp, sv, rbac_enabled);
child = fork_cmnd(details, argv, envp, sv);
close(sv[1]);
/* Set command timeout if specified. */
@@ -343,7 +329,7 @@ sudo_execve(struct command_details *details, char *argv[], char *envp[],
}
#ifdef HAVE_SELINUX
if (rbac_enabled) {
if (details->selinux_enabled) {
/* This is probably not needed in log_io mode. */
if (selinux_restore_tty() != 0)
warningx("unable to restore tty label");

View File

@@ -118,9 +118,9 @@ static struct io_buffer *iobufs;
static void flush_output(void);
static int exec_monitor(struct command_details *details, char *argv[],
char *envp[], int, int);
char *envp[], int backchannel);
static void exec_pty(struct command_details *detail, char *argv[],
char *envp[], int);
char *envp[]);
static void sigwinch(int s);
static void sync_ttysize(int src, int dst);
static void deliver_signal(pid_t pid, int signo);
@@ -470,7 +470,7 @@ perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat)
*/
int
fork_pty(struct command_details *details, char *argv[], char *envp[],
int sv[], int rbac_enabled, int *maxfd)
int sv[], int *maxfd)
{
struct command_status cstat;
struct io_buffer *iob;
@@ -581,13 +581,7 @@ fork_pty(struct command_details *details, char *argv[], char *envp[],
/* child */
close(sv[0]);
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
#ifdef HAVE_SELINUX
if (rbac_enabled) {
selinux_setup(details->selinux_role, details->selinux_type,
slavename, io_fds[SFD_SLAVE]);
}
#endif
if (exec_setup(details) == TRUE) {
if (exec_setup(details, slavename, io_fds[SFD_SLAVE]) == TRUE) {
/* Close the other end of the stdin/stdout/stderr pipes and exec. */
if (io_pipe[STDIN_FILENO][1])
close(io_pipe[STDIN_FILENO][1]);
@@ -595,7 +589,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], rbac_enabled);
exec_monitor(details, argv, envp, sv[1]);
}
cstat.type = CMD_ERRNO;
cstat.val = errno;
@@ -814,7 +808,7 @@ handle_sigchld(int backchannel, struct command_status *cstat)
*/
int
exec_monitor(struct command_details *details, char *argv[], char *envp[],
int backchannel, int rbac)
int backchannel)
{
struct command_status cstat;
struct timeval tv;
@@ -904,7 +898,7 @@ exec_monitor(struct command_details *details, char *argv[], char *envp[],
fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
/* setup tty and exec command */
exec_pty(details, argv, envp, rbac);
exec_pty(details, argv, envp);
cstat.type = CMD_ERRNO;
cstat.val = errno;
write(errpipe[1], &cstat, sizeof(cstat));
@@ -1088,8 +1082,7 @@ flush_output(void)
* Returns only if execve() fails.
*/
static void
exec_pty(struct command_details *details, char *argv[], char *envp[],
int rbac_enabled)
exec_pty(struct command_details *details, char *argv[], char *envp[])
{
sigaction_t sa;
pid_t self = getpid();
@@ -1137,7 +1130,7 @@ exec_pty(struct command_details *details, char *argv[], char *envp[],
if (details->closefrom >= 0)
closefrom(details->closefrom);
#ifdef HAVE_SELINUX
if (rbac_enabled)
if (details->selinux_enabled)
selinux_execve(details->command, argv, envp);
else
#endif

View File

@@ -205,12 +205,14 @@ get_exec_context(security_context_t old_context, const char *role, const char *t
/* We must have a role, the type is optional (we can use the default). */
if (!role) {
warningx("you must specify a role.");
warningx("you must specify a role for type %s", type);
errno = EINVAL;
return NULL;
}
if (!type) {
if (get_default_type(role, &typebuf)) {
warningx("unable to get default type");
warningx("unable to get default type for role %s", role);
errno = EINVAL;
return NULL;
}
type = typebuf;
@@ -227,11 +229,11 @@ get_exec_context(security_context_t old_context, const char *role, const char *t
* type we will be running the command as.
*/
if (context_role_set(context, role)) {
warningx("failed to set new role %s", role);
warning("failed to set new role %s", role);
goto bad;
}
if (context_type_set(context, type)) {
warningx("failed to set new type %s", type);
warning("failed to set new type %s", type);
goto bad;
}
@@ -241,6 +243,7 @@ get_exec_context(security_context_t old_context, const char *role, const char *t
new_context = estrdup(context_str(context));
if (security_check_context(new_context) < 0) {
warningx("%s is not a valid context", new_context);
errno = EINVAL;
goto bad;
}
@@ -263,28 +266,37 @@ bad:
* Must run as root, before the uid change.
* If ptyfd is not -1, it indicates we are running
* in a pty and do not need to reset std{in,out,err}.
* Returns 0 on success and -1 on failure.
*/
void
int
selinux_setup(const char *role, const char *type, const char *ttyn,
int ptyfd)
{
int rval = -1;
/* Store the caller's SID in old_context. */
if (getprevcon(&se_state.old_context))
error(EXIT_FAILURE, "failed to get old_context");
if (getprevcon(&se_state.old_context)) {
warning("failed to get old_context");
goto done;
}
se_state.enforcing = security_getenforce();
if (se_state.enforcing < 0)
error(EXIT_FAILURE, "unable to determine enforcing mode.");
if (se_state.enforcing < 0) {
warning("unable to determine enforcing mode.");
goto done;
}
#ifdef DEBUG
warningx("your old context was %s", se_state.old_context);
#endif
se_state.new_context = get_exec_context(se_state.old_context, role, type);
if (!se_state.new_context)
error(EXIT_FAILURE, "unable to get exec context");
goto done;
if (relabel_tty(ttyn, ptyfd) < 0)
error(EXIT_FAILURE, "unable to setup tty context for %s", se_state.new_context);
if (relabel_tty(ttyn, ptyfd) < 0) {
warning("unable to setup tty context for %s", se_state.new_context);
goto done;
}
#ifdef DEBUG
if (se_state.ttyfd != -1) {
@@ -293,6 +305,10 @@ selinux_setup(const char *role, const char *type, const char *ttyn,
}
#endif
rval = 0;
done:
return rval;
}
void

View File

@@ -69,6 +69,9 @@
#ifdef HAVE_LOGIN_CAP_H
# include <login_cap.h>
#endif
#ifdef HAVE_SELINUX
# include <selinux/selinux.h>
#endif
#include "sudo.h"
#include "sudo_plugin.h"
@@ -586,6 +589,11 @@ command_info_to_details(char * const info[], struct command_details *details)
if (!ISSET(details->flags, CD_SET_EUID))
details->euid = details->uid;
#ifdef HAVE_SELINUX
if (details->selinux_role != NULL && is_selinux_enabled() > 0)
details->selinux_enabled = TRUE;
#endif
}
/*
@@ -630,7 +638,7 @@ disable_coredumps(void)
* Returns TRUE on success and FALSE on failure.
*/
int
exec_setup(struct command_details *details)
exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
{
int rval = FALSE;
struct passwd *pw;
@@ -644,6 +652,14 @@ exec_setup(struct command_details *details)
goto done;
}
#ifdef HAVE_SELINUX
if (details->selinux_enabled) {
if (selinux_setup(details->selinux_role, details->selinux_type,
ptyname ? ptyname : user_details.tty, ptyfd) == -1)
goto done;
}
#endif
if (pw != NULL) {
#ifdef HAVE_GETUSERATTR
aix_setlimits(pw->pw_name);

View File

@@ -123,11 +123,12 @@ struct command_details {
gid_t gid;
gid_t egid;
mode_t umask;
int flags;
int priority;
int timeout;
int ngroups;
int closefrom;
short flags;
short selinux_enabled;
GETGROUPS_T *groups;
const char *command;
const char *cwd;
@@ -164,7 +165,7 @@ int my_execve(const char *path, char *const argv[], char *const envp[]);
/* exec_pty.c */
int fork_pty(struct command_details *details, char *argv[], char *envp[],
int sv[], int rbac_enabled, int *maxfd);
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);
@@ -196,7 +197,7 @@ int get_pty(int *master, int *slave, char *name, size_t namesz, uid_t uid);
void get_ttysize(int *linep, int *colp);
/* sudo.c */
int exec_setup(struct command_details *details);
int exec_setup(struct command_details *details, const char *ptyname, int ptyfd);
int run_command(struct command_details *details, char *argv[],
char *envp[]);
void sudo_debug(int level, const char *format, ...) __printflike(2, 3);
@@ -213,10 +214,10 @@ void usage(int) __attribute__((__noreturn__));
int gettime(struct timeval *);
/* selinux.c */
void selinux_execve(const char *path, char *argv[], char *envp[]);
void selinux_setup(const char *role, const char *type, const char *ttyn,
int ttyfd);
int selinux_restore_tty(void);
int selinux_setup(const char *role, const char *type, const char *ttyn,
int ttyfd);
void selinux_execve(const char *path, char *argv[], char *envp[]);
#ifndef errno
extern int errno;