set it in command_info_to_details().
Return an error from selinux_setup() instead of exiting.
Call selinux_setup() from exec_setup().
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#ifdef HAVE_SELINUX
-# include <selinux/selinux.h>
-#endif
/* XXX - move to compat */
#if !defined(NSIG)
* 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;
/* 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
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;
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.
* 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. */
}
#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");
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);
*/
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;
/* 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]);
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;
*/
int
exec_monitor(struct command_details *details, char *argv[], char *envp[],
- int backchannel, int rbac)
+ int backchannel)
{
struct command_status cstat;
struct timeval tv;
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));
* 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();
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
/* 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;
* 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;
}
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;
}
* 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) {
}
#endif
+ rval = 0;
+
+done:
+ return rval;
}
void
#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"
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
}
/*
* 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;
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);
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;
/* 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);
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);
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;