]> granicus.if.org Git - sudo/commitdiff
Add selinux_enabled flag into struct command_details and
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 8 Jun 2010 21:59:18 +0000 (17:59 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 8 Jun 2010 21:59:18 +0000 (17:59 -0400)
set it in command_info_to_details().
Return an error from selinux_setup() instead of exiting.
Call selinux_setup() from exec_setup().

src/exec.c
src/exec_pty.c
src/selinux.c
src/sudo.c
src/sudo.h

index c704abe7a4cc103fa22ed4570ab3187eb500d227..2e8cc932d16c01e33b28e6992a8ed9a79980118a 100644 (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");
index 8e3f35644103b4783ec0a9ec4ae8dc6526226a84..242e842c050abbbd64bdedcf599798f110c8cf2b 100644 (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
index 54b839fea34ff29abedb01f8f1527ca3d2c56700..0c70710eab1efaf32470274fdadfb7b2c2f0dc09 100644 (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
index d500d84eb965eead8e3bdcd02725b82445c295ef..fae86227147b23ba3c8c511f4cbf4d5236036d90 100644 (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);
index f0112a20a42cf1bd76c8eb0ca86a58498128493e..dbda4f60116781b0d0c4e3444661914ab9ed271a 100644 (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;