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:
26
src/exec.c
26
src/exec.c
@@ -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");
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
18
src/sudo.c
18
src/sudo.c
@@ -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);
|
||||
|
13
src/sudo.h
13
src/sudo.h
@@ -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;
|
||||
|
Reference in New Issue
Block a user