]> granicus.if.org Git - sudo/commitdiff
Add support for disabling exec via solaris privileges.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 10 Mar 2011 19:24:10 +0000 (14:24 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 10 Mar 2011 19:24:10 +0000 (14:24 -0500)
Includes preparation for moving noexec support out of sudoers
and into front end as documented.

config.h.in
configure
configure.in
plugins/sudoers/sudoers.c
src/exec.c
src/exec_pty.c
src/sudo.c
src/sudo.h
src/sudo_edit.c
src/sudo_exec.h

index 0b81e44da82494546b38052069fbb4e389f2c464..68066a8431eb08983223e220ee18a77f878dc94e 100644 (file)
 /* Define to 1 if you have the `posix_openpt' function. */
 #undef HAVE_POSIX_OPENPT
 
+/* Define to 1 if you have the `priv_set' function. */
+#undef HAVE_PRIV_SET
+
 /* Define to 1 if you have the <project.h> header file. */
 #undef HAVE_PROJECT_H
 
index e832f79439fd76c519747a51f78c86c0c4eda0df..f75e285d4ef051dc0501f3ebaa86f2c810001d61 100755 (executable)
--- a/configure
+++ b/configure
@@ -12974,6 +12974,17 @@ case "$host" in
                : ${mansectform='4'}
                : ${with_rpath='yes'}
                test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+               for ac_func in priv_set
+do :
+  ac_fn_c_check_func "$LINENO" "priv_set" "ac_cv_func_priv_set"
+if test "x$ac_cv_func_priv_set" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PRIV_SET 1
+_ACEOF
+
+fi
+done
+
                ;;
     *-*-aix*)
                # To get all prototypes (so we pass -Wall)
index 90f2da5cd67f5165e9a6eb9ca4c9cd1ab4cbd03c..6d85742d6ee218ac75a91d10fb23cb76526bf092 100644 (file)
@@ -1462,6 +1462,7 @@ case "$host" in
                : ${mansectform='4'}
                : ${with_rpath='yes'}
                test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+               AC_CHECK_FUNCS(priv_set)
                ;;
     *-*-aix*)
                # To get all prototypes (so we pass -Wall)
index a190da0082a7e36ca56d31ff99549d85aeca4707..0a67f1ac7d9088e7a1f14341529c366ddd35dad2 100644 (file)
@@ -433,7 +433,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
        def_env_reset = FALSE;
 
     /* Build a new environment that avoids any nasty bits. */
-    rebuild_env(def_noexec);
+    rebuild_env(def_noexec); /* XXX - move noexec bits */
 
     /* Require a password if sudoers says so.  */
     if (def_authenticate) {
@@ -533,6 +533,9 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
            command_info[info_len++] = estrdup("iolog_compress=true");
     }
 
+    if (def_noexec)
+           command_info[info_len++] = estrdup("noexec=true");
+
     log_allowed(validated);
     if (ISSET(sudo_mode, MODE_CHECK))
        rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
index baa4e3f02f4341629c07644278adf344d8acf75e..b1ea79b10f5ca365a93ae3e15152fb02c02bc85b 100644 (file)
@@ -107,8 +107,7 @@ my_execve(const char *path, char *const argv[], char *const envp[])
  * Fork and execute a command, returns the child's pid.
  * Sends errno back on sv[1] if execve() fails.
  */
-static int fork_cmnd(struct command_details *details, char *argv[],
-    char *envp[], int sv[2])
+static int fork_cmnd(struct command_details *details, int sv[2])
 {
     struct command_status cstat;
     sigaction_t sa;
@@ -138,10 +137,10 @@ static int fork_cmnd(struct command_details *details, char *argv[],
                closefrom(details->closefrom);
 #ifdef HAVE_SELINUX
            if (ISSET(details->flags, CD_RBAC_ENABLED))
-               selinux_execve(details->command, argv, envp);
+               selinux_execve(details->command, details->argv, details->envp);
            else
 #endif
-               my_execve(details->command, argv, envp);
+               my_execve(details->command, details->argv, details->envp);
        }
        cstat.type = CMD_ERRNO;
        cstat.val = errno;
@@ -201,8 +200,7 @@ restore_signals(void)
  * we fact that we have two different controlling terminals to deal with.
  */
 int
-sudo_execve(struct command_details *details, char *argv[], char *envp[],
-    struct command_status *cstat)
+sudo_execve(struct command_details *details, struct command_status *cstat)
 {
     int maxfd, n, nready, sv[2], log_io = FALSE;
     fd_set *fdsr, *fdsw;
@@ -279,9 +277,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, &maxfd);
+       child = fork_pty(details, sv, &maxfd);
     else
-       child = fork_cmnd(details, argv, envp, sv);
+       child = fork_cmnd(details, sv);
     close(sv[1]);
 
     /* Set command timeout if specified. */
index be45d4bb16b1dac6e72a90d78a2d876cbb1cad53..1b3077c7f67e3ce1a40195629e4002cfe12152f0 100644 (file)
@@ -108,10 +108,8 @@ static sigset_t ttyblock;
 static struct io_buffer *iobufs;
 
 static void flush_output(void);
-static int exec_monitor(struct command_details *details, char *argv[],
-    char *envp[], int backchannel);
-static void exec_pty(struct command_details *detail, char *argv[],
-    char *envp[]);
+static int exec_monitor(struct command_details *details, int backchannel);
+static void exec_pty(struct command_details *detail);
 static void sigwinch(int s);
 static void sync_ttysize(int src, int dst);
 static void deliver_signal(pid_t pid, int signo);
@@ -640,8 +638,7 @@ perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat)
  * Returns the child pid.
  */
 int
-fork_pty(struct command_details *details, char *argv[], char *envp[],
-    int sv[], int *maxfd)
+fork_pty(struct command_details *details, int sv[], int *maxfd)
 {
     struct command_status cstat;
     struct io_buffer *iob;
@@ -758,7 +755,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]);
+           exec_monitor(details, sv[1]);
        }
        cstat.type = CMD_ERRNO;
        cstat.val = errno;
@@ -973,8 +970,7 @@ handle_sigchld(int backchannel, struct command_status *cstat)
  * Returns an error if fork(2) fails, else calls _exit(2).
  */
 static int
-exec_monitor(struct command_details *details, char *argv[], char *envp[],
-    int backchannel)
+exec_monitor(struct command_details *details, int backchannel)
 {
     struct command_status cstat;
     struct timeval tv;
@@ -1062,7 +1058,7 @@ exec_monitor(struct command_details *details, char *argv[], char *envp[],
        restore_signals();
 
        /* setup tty and exec command */
-       exec_pty(details, argv, envp);
+       exec_pty(details);
        cstat.type = CMD_ERRNO;
        cstat.val = errno;
        if (write(errpipe[1], &cstat, sizeof(cstat)) == -1)
@@ -1258,7 +1254,7 @@ flush_output(void)
  * Returns only if execve() fails.
  */
 static void
-exec_pty(struct command_details *details, char *argv[], char *envp[])
+exec_pty(struct command_details *details)
 {
     pid_t self = getpid();
 
@@ -1291,10 +1287,10 @@ exec_pty(struct command_details *details, char *argv[], char *envp[])
        closefrom(details->closefrom);
 #ifdef HAVE_SELINUX
     if (ISSET(details->flags, CD_RBAC_ENABLED))
-       selinux_execve(details->command, argv, envp);
+       selinux_execve(details->command, details->argv, details->envp);
     else
 #endif
-       my_execve(details->command, argv, envp);
+       my_execve(details->command, details->argv, details->envp);
 }
 
 /*
index 34b09c180b14963d4429f5422010568c3f0db862..9c9c8c1988e126cee299f9a2a67ff588c16fc9a6 100644 (file)
@@ -86,6 +86,9 @@
 # endif /* __hpux */
 # include <prot.h>
 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
+#ifdef HAVE_PRIV_SET
+# include <priv.h>
+#endif
 
 #include "sudo.h"
 #include "sudo_plugin.h"
@@ -271,6 +274,8 @@ main(int argc, char *argv[], char *envp[])
                }
            }
            command_info_to_details(command_info, &command_details);
+           command_details.argv = argv_out;
+           command_details.envp = user_env_out;
            if (ISSET(sudo_mode, MODE_BACKGROUND))
                SET(command_details.flags, CD_BACKGROUND);
            /* Restore coredumpsize resource limit before running. */
@@ -278,7 +283,7 @@ main(int argc, char *argv[], char *envp[])
            (void) setrlimit(RLIMIT_CORE, &corelimit);
 #endif /* RLIMIT_CORE && !SUDO_DEVEL */
            if (ISSET(command_details.flags, CD_SUDOEDIT)) {
-               exitcode = sudo_edit(&command_details, argv_out, user_env_out);
+               exitcode = sudo_edit(&command_details);
            } else {
                if (ISSET(sudo_mode, MODE_SHELL)) {
                    /* Escape meta chars if running a shell with args. */
@@ -286,7 +291,7 @@ main(int argc, char *argv[], char *envp[])
                        argv_out[2] != NULL && argv_out[3] == NULL)
                        argv_out[2] = escape_cmnd(argv_out[2]);
                }
-               exitcode = run_command(&command_details, argv_out, user_env_out);
+               exitcode = run_command(&command_details);
            }
            /* The close method was called by sudo_edit/run_command. */
            break;
@@ -860,6 +865,14 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
        }
     }
 
+    /* XXX - should do env-based noexec here too */
+#ifdef HAVE_PRIV_SET
+    if (ISSET(details->flags, CD_NOEXEC)) {
+       if (priv_set(PRIV_OFF, PRIV_LIMIT, "PRIV_PROC_EXEC", NULL) == -1)
+           warning("unable to remove PRIV_PROC_EXEC from PRIV_LIMIT");
+    }
+#endif /* HAVE_PRIV_SET */
+
 #ifdef HAVE_SETRESUID
     if (setresuid(details->uid, details->euid, details->euid) != 0) {
        warning("unable to change to runas uid (%u, %u)", details->uid,
@@ -943,7 +956,7 @@ escape_cmnd(const char *src)
  * Run the command and wait for it to complete.
  */
 int
-run_command(struct command_details *details, char *argv[], char *envp[])
+run_command(struct command_details *details)
 {
     struct plugin_container *plugin;
     struct command_status cstat;
@@ -952,7 +965,7 @@ run_command(struct command_details *details, char *argv[], char *envp[])
     cstat.type = CMD_INVALID;
     cstat.val = 0;
 
-    sudo_execve(details, argv, envp, &cstat);
+    sudo_execve(details, &cstat);
 
     switch (cstat.type) {
     case CMD_ERRNO:
index e6190c16c3c8a7f79fc3b6443ac9ff16b69b821e..8c21934b89fab01741a75ab370b8379139a00495 100644 (file)
@@ -139,6 +139,8 @@ struct command_details {
     const char *chroot;
     const char *selinux_role;
     const char *selinux_type;
+    char **argv;
+    char **envp;
 };
 
 /* Status passed between parent and child via socketpair */
@@ -165,8 +167,7 @@ extern const char *askpass_path;
 void zero_bytes(volatile void *, size_t);
 
 /* exec.c */
-int sudo_execve(struct command_details *details, char *argv[], char *envp[],
-    struct command_status *cstat);
+int sudo_execve(struct command_details *details, struct command_status *cstat);
 void save_signals(void);
 void restore_signals(void);
 
@@ -196,15 +197,14 @@ void get_ttysize(int *rowp, int *colp);
 
 /* sudo.c */
 int exec_setup(struct command_details *details, const char *ptyname, int ptyfd);
-int run_command(struct command_details *details, char *argv[],   
-    char *envp[]);
+int run_command(struct command_details *details);
 void sudo_debug(int level, const char *format, ...) __printflike(2, 3);
 extern int debug_level;
 extern const char *list_user, *runas_user, *runas_group;
 extern struct user_details user_details;
 
 /* sudo_edit.c */
-int sudo_edit(struct command_details *details, char *argv[], char *envp[]);
+int sudo_edit(struct command_details *details);
 
 /* parse_args.c */
 void usage(int);
index a08e9435a2c12c5c7089c059f65ba439aefd0acf..dd485d346b660f15d49852163b2cce41482a82e1 100644 (file)
@@ -82,7 +82,7 @@ switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
  * Wrapper to allow users to edit privileged files with their own uid.
  */
 int
-sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
+sudo_edit(struct command_details *command_details)
 {
     struct command_details editor_details;
     ssize_t nread, nwritten;
@@ -128,7 +128,7 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
      * The user's editor must be separated from the files to be
      * edited by a "--" option.
      */
-    for (ap = argv; *ap != NULL; ap++) {
+    for (ap = command_details->argv; *ap != NULL; ap++) {
        if (files)
            nfiles++;
        else if (strcmp(*ap, "--") == 0)
@@ -238,7 +238,7 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
     nargc = editor_argc + nfiles;
     nargv = (char **) emalloc2(nargc + 1, sizeof(char *));
     for (ac = 0; ac < editor_argc; ac++)
-       nargv[ac] = argv[ac];
+       nargv[ac] = command_details->argv[ac];
     for (i = 0; i < nfiles && ac < nargc; )
        nargv[ac++] = tf[i++].tfile;
     nargv[ac] = NULL;
@@ -255,7 +255,8 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
     editor_details.egid = user_details.gid;
     editor_details.ngroups = user_details.ngroups;
     editor_details.groups = user_details.groups;
-    rval = run_command(&editor_details, nargv, envp);
+    editor_details.argv = nargv;
+    rval = run_command(&editor_details);
     gettimeofday(&tv2, NULL);
 
     /* Copy contents of temp files to real ones */
@@ -345,7 +346,7 @@ cleanup:
  * Must have the ability to change the effective uid to use sudoedit.
  */
 int
-sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
+sudo_edit(struct command_details *command_details)
 {
     return 1;
 }
index 7bc3d52ecf3cdda35c3e90b08d995be57ea4a17d..d447634b98f682f7907b0515c8037f9af1b15a3b 100644 (file)
@@ -32,8 +32,7 @@ int my_execve(const char *path, char *const argv[], char *const envp[]);
 int pipe_nonblock(int fds[2]);
 
 /* exec_pty.c */
-int fork_pty(struct command_details *details, char *argv[], char *envp[],
-    int sv[], int *maxfd);
+int fork_pty(struct command_details *details, 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);