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 <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#ifdef HAVE_SELINUX
|
|
||||||
# include <selinux/selinux.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* XXX - move to compat */
|
/* XXX - move to compat */
|
||||||
#if !defined(NSIG)
|
#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.
|
* 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, char *argv[],
|
||||||
char *envp[], int sv[2], int rbac_enabled)
|
char *envp[], int sv[2])
|
||||||
{
|
{
|
||||||
struct command_status cstat;
|
struct command_status cstat;
|
||||||
int pid;
|
int pid;
|
||||||
@@ -127,18 +124,12 @@ static int fork_cmnd(struct command_details *details, char *argv[],
|
|||||||
/* child */
|
/* child */
|
||||||
close(sv[0]);
|
close(sv[0]);
|
||||||
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
||||||
#ifdef HAVE_SELINUX
|
if (exec_setup(details, NULL, -1) == TRUE) {
|
||||||
if (rbac_enabled) {
|
|
||||||
selinux_setup(details->selinux_role, details->selinux_type,
|
|
||||||
user_details.tty, -1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (exec_setup(details) == TRUE) {
|
|
||||||
/* headed for execve() */
|
/* headed for execve() */
|
||||||
if (details->closefrom >= 0)
|
if (details->closefrom >= 0)
|
||||||
closefrom(details->closefrom);
|
closefrom(details->closefrom);
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
if (rbac_enabled)
|
if (details->selinux_enabled)
|
||||||
selinux_execve(details->command, argv, envp);
|
selinux_execve(details->command, argv, envp);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -164,7 +155,6 @@ sudo_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
sigaction_t sa;
|
sigaction_t sa;
|
||||||
fd_set *fdsr, *fdsw;
|
fd_set *fdsr, *fdsw;
|
||||||
int maxfd, n, nready, status, sv[2];
|
int maxfd, n, nready, status, sv[2];
|
||||||
int rbac_enabled = 0;
|
|
||||||
int log_io = 0;
|
int log_io = 0;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
|
|
||||||
@@ -176,10 +166,6 @@ sudo_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
pty_setup(details->euid);
|
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.
|
* We communicate with the child over a bi-directional pair of sockets.
|
||||||
* Parent sends signal info to child and child sends back wait status.
|
* 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.
|
* to and from pty. Adjusts maxfd as needed.
|
||||||
*/
|
*/
|
||||||
if (log_io)
|
if (log_io)
|
||||||
child = fork_pty(details, argv, envp, sv, rbac_enabled, &maxfd);
|
child = fork_pty(details, argv, envp, sv, &maxfd);
|
||||||
else
|
else
|
||||||
child = fork_cmnd(details, argv, envp, sv, rbac_enabled);
|
child = fork_cmnd(details, argv, envp, sv);
|
||||||
close(sv[1]);
|
close(sv[1]);
|
||||||
|
|
||||||
/* Set command timeout if specified. */
|
/* Set command timeout if specified. */
|
||||||
@@ -343,7 +329,7 @@ sudo_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
if (rbac_enabled) {
|
if (details->selinux_enabled) {
|
||||||
/* This is probably not needed in log_io mode. */
|
/* This is probably not needed in log_io mode. */
|
||||||
if (selinux_restore_tty() != 0)
|
if (selinux_restore_tty() != 0)
|
||||||
warningx("unable to restore tty label");
|
warningx("unable to restore tty label");
|
||||||
|
@@ -118,9 +118,9 @@ 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, char *argv[],
|
||||||
char *envp[], int, int);
|
char *envp[], int backchannel);
|
||||||
static void exec_pty(struct command_details *detail, char *argv[],
|
static void exec_pty(struct command_details *detail, char *argv[],
|
||||||
char *envp[], int);
|
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);
|
||||||
@@ -470,7 +470,7 @@ perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fork_pty(struct command_details *details, char *argv[], char *envp[],
|
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 command_status cstat;
|
||||||
struct io_buffer *iob;
|
struct io_buffer *iob;
|
||||||
@@ -581,13 +581,7 @@ fork_pty(struct command_details *details, char *argv[], char *envp[],
|
|||||||
/* child */
|
/* child */
|
||||||
close(sv[0]);
|
close(sv[0]);
|
||||||
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
||||||
#ifdef HAVE_SELINUX
|
if (exec_setup(details, slavename, io_fds[SFD_SLAVE]) == TRUE) {
|
||||||
if (rbac_enabled) {
|
|
||||||
selinux_setup(details->selinux_role, details->selinux_type,
|
|
||||||
slavename, io_fds[SFD_SLAVE]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (exec_setup(details) == TRUE) {
|
|
||||||
/* Close the other end of the stdin/stdout/stderr pipes and exec. */
|
/* Close the other end of the stdin/stdout/stderr pipes and exec. */
|
||||||
if (io_pipe[STDIN_FILENO][1])
|
if (io_pipe[STDIN_FILENO][1])
|
||||||
close(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]);
|
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], rbac_enabled);
|
exec_monitor(details, argv, envp, sv[1]);
|
||||||
}
|
}
|
||||||
cstat.type = CMD_ERRNO;
|
cstat.type = CMD_ERRNO;
|
||||||
cstat.val = errno;
|
cstat.val = errno;
|
||||||
@@ -814,7 +808,7 @@ handle_sigchld(int backchannel, struct command_status *cstat)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
exec_monitor(struct command_details *details, char *argv[], char *envp[],
|
exec_monitor(struct command_details *details, char *argv[], char *envp[],
|
||||||
int backchannel, int rbac)
|
int backchannel)
|
||||||
{
|
{
|
||||||
struct command_status cstat;
|
struct command_status cstat;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -904,7 +898,7 @@ exec_monitor(struct command_details *details, char *argv[], char *envp[],
|
|||||||
fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
|
fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
/* setup tty and exec command */
|
/* setup tty and exec command */
|
||||||
exec_pty(details, argv, envp, rbac);
|
exec_pty(details, argv, envp);
|
||||||
cstat.type = CMD_ERRNO;
|
cstat.type = CMD_ERRNO;
|
||||||
cstat.val = errno;
|
cstat.val = errno;
|
||||||
write(errpipe[1], &cstat, sizeof(cstat));
|
write(errpipe[1], &cstat, sizeof(cstat));
|
||||||
@@ -1088,8 +1082,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, char *argv[], char *envp[])
|
||||||
int rbac_enabled)
|
|
||||||
{
|
{
|
||||||
sigaction_t sa;
|
sigaction_t sa;
|
||||||
pid_t self = getpid();
|
pid_t self = getpid();
|
||||||
@@ -1137,7 +1130,7 @@ exec_pty(struct command_details *details, char *argv[], char *envp[],
|
|||||||
if (details->closefrom >= 0)
|
if (details->closefrom >= 0)
|
||||||
closefrom(details->closefrom);
|
closefrom(details->closefrom);
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
if (rbac_enabled)
|
if (details->selinux_enabled)
|
||||||
selinux_execve(details->command, argv, envp);
|
selinux_execve(details->command, argv, envp);
|
||||||
else
|
else
|
||||||
#endif
|
#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). */
|
/* We must have a role, the type is optional (we can use the default). */
|
||||||
if (!role) {
|
if (!role) {
|
||||||
warningx("you must specify a role.");
|
warningx("you must specify a role for type %s", type);
|
||||||
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!type) {
|
if (!type) {
|
||||||
if (get_default_type(role, &typebuf)) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
type = typebuf;
|
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.
|
* type we will be running the command as.
|
||||||
*/
|
*/
|
||||||
if (context_role_set(context, role)) {
|
if (context_role_set(context, role)) {
|
||||||
warningx("failed to set new role %s", role);
|
warning("failed to set new role %s", role);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (context_type_set(context, type)) {
|
if (context_type_set(context, type)) {
|
||||||
warningx("failed to set new type %s", type);
|
warning("failed to set new type %s", type);
|
||||||
goto bad;
|
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));
|
new_context = estrdup(context_str(context));
|
||||||
if (security_check_context(new_context) < 0) {
|
if (security_check_context(new_context) < 0) {
|
||||||
warningx("%s is not a valid context", new_context);
|
warningx("%s is not a valid context", new_context);
|
||||||
|
errno = EINVAL;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,28 +266,37 @@ bad:
|
|||||||
* Must run as root, before the uid change.
|
* Must run as root, before the uid change.
|
||||||
* If ptyfd is not -1, it indicates we are running
|
* If ptyfd is not -1, it indicates we are running
|
||||||
* in a pty and do not need to reset std{in,out,err}.
|
* 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,
|
selinux_setup(const char *role, const char *type, const char *ttyn,
|
||||||
int ptyfd)
|
int ptyfd)
|
||||||
{
|
{
|
||||||
|
int rval = -1;
|
||||||
|
|
||||||
/* Store the caller's SID in old_context. */
|
/* Store the caller's SID in old_context. */
|
||||||
if (getprevcon(&se_state.old_context))
|
if (getprevcon(&se_state.old_context)) {
|
||||||
error(EXIT_FAILURE, "failed to get old_context");
|
warning("failed to get old_context");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
se_state.enforcing = security_getenforce();
|
se_state.enforcing = security_getenforce();
|
||||||
if (se_state.enforcing < 0)
|
if (se_state.enforcing < 0) {
|
||||||
error(EXIT_FAILURE, "unable to determine enforcing mode.");
|
warning("unable to determine enforcing mode.");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
warningx("your old context was %s", se_state.old_context);
|
warningx("your old context was %s", se_state.old_context);
|
||||||
#endif
|
#endif
|
||||||
se_state.new_context = get_exec_context(se_state.old_context, role, type);
|
se_state.new_context = get_exec_context(se_state.old_context, role, type);
|
||||||
if (!se_state.new_context)
|
if (!se_state.new_context)
|
||||||
error(EXIT_FAILURE, "unable to get exec context");
|
goto done;
|
||||||
|
|
||||||
if (relabel_tty(ttyn, ptyfd) < 0)
|
if (relabel_tty(ttyn, ptyfd) < 0) {
|
||||||
error(EXIT_FAILURE, "unable to setup tty context for %s", se_state.new_context);
|
warning("unable to setup tty context for %s", se_state.new_context);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (se_state.ttyfd != -1) {
|
if (se_state.ttyfd != -1) {
|
||||||
@@ -293,6 +305,10 @@ selinux_setup(const char *role, const char *type, const char *ttyn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
rval = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
18
src/sudo.c
18
src/sudo.c
@@ -69,6 +69,9 @@
|
|||||||
#ifdef HAVE_LOGIN_CAP_H
|
#ifdef HAVE_LOGIN_CAP_H
|
||||||
# include <login_cap.h>
|
# include <login_cap.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
# include <selinux/selinux.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "sudo.h"
|
#include "sudo.h"
|
||||||
#include "sudo_plugin.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))
|
if (!ISSET(details->flags, CD_SET_EUID))
|
||||||
details->euid = details->uid;
|
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.
|
* Returns TRUE on success and FALSE on failure.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
exec_setup(struct command_details *details)
|
exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
|
||||||
{
|
{
|
||||||
int rval = FALSE;
|
int rval = FALSE;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
@@ -644,6 +652,14 @@ exec_setup(struct command_details *details)
|
|||||||
goto done;
|
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) {
|
if (pw != NULL) {
|
||||||
#ifdef HAVE_GETUSERATTR
|
#ifdef HAVE_GETUSERATTR
|
||||||
aix_setlimits(pw->pw_name);
|
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 gid;
|
||||||
gid_t egid;
|
gid_t egid;
|
||||||
mode_t umask;
|
mode_t umask;
|
||||||
int flags;
|
|
||||||
int priority;
|
int priority;
|
||||||
int timeout;
|
int timeout;
|
||||||
int ngroups;
|
int ngroups;
|
||||||
int closefrom;
|
int closefrom;
|
||||||
|
short flags;
|
||||||
|
short selinux_enabled;
|
||||||
GETGROUPS_T *groups;
|
GETGROUPS_T *groups;
|
||||||
const char *command;
|
const char *command;
|
||||||
const char *cwd;
|
const char *cwd;
|
||||||
@@ -164,7 +165,7 @@ int my_execve(const char *path, char *const argv[], char *const envp[]);
|
|||||||
|
|
||||||
/* exec_pty.c */
|
/* exec_pty.c */
|
||||||
int fork_pty(struct command_details *details, char *argv[], char *envp[],
|
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 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);
|
||||||
@@ -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);
|
void get_ttysize(int *linep, int *colp);
|
||||||
|
|
||||||
/* sudo.c */
|
/* 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[],
|
int run_command(struct command_details *details, char *argv[],
|
||||||
char *envp[]);
|
char *envp[]);
|
||||||
void sudo_debug(int level, const char *format, ...) __printflike(2, 3);
|
void sudo_debug(int level, const char *format, ...) __printflike(2, 3);
|
||||||
@@ -213,10 +214,10 @@ void usage(int) __attribute__((__noreturn__));
|
|||||||
int gettime(struct timeval *);
|
int gettime(struct timeval *);
|
||||||
|
|
||||||
/* selinux.c */
|
/* 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_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
|
#ifndef errno
|
||||||
extern int errno;
|
extern int errno;
|
||||||
|
Reference in New Issue
Block a user