Add support for intercepting the system(3) function.

This also means we can log system(3) with log_subcmds.
This commit is contained in:
Todd C. Miller
2022-05-31 14:45:00 -06:00
parent 436deda08d
commit f52342031d
6 changed files with 105 additions and 14 deletions

View File

@@ -17,7 +17,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.nr SL @SEMAN@
.TH "SUDO.CONF" "@mansectform@" "April 28, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDO.CONF" "@mansectform@" "May 31, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -296,8 +296,9 @@ The fully-qualified path to a shared library containing a wrappers for the
\fBexecv\fR(),
\fBexecve\fR(),
\fBexecvp\fR(),
\fBexecvpe\fR(),
and
\fBexecvpe\fR()
\fBsystem\fR()
library functions that intercepts attempts to run further commands and
performs a policy check before allowing them to be executed.
This is used to implement the

View File

@@ -16,7 +16,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.nr SL @SEMAN@
.Dd April 28, 2022
.Dd May 31, 2022
.Dt SUDO.CONF @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@@ -271,8 +271,9 @@ The fully-qualified path to a shared library containing a wrappers for the
.Fn execv ,
.Fn execve ,
.Fn execvp ,
.Fn execvpe ,
and
.Fn execvpe
.Fn system
library functions that intercepts attempts to run further commands and
performs a policy check before allowing them to be executed.
This is used to implement the

View File

@@ -25,7 +25,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.nr PS @PSMAN@
.TH "SUDOERS" "@mansectform@" "May 24, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDOERS" "@mansectform@" "May 31, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -3151,8 +3151,9 @@ using the
\fBexecv\fR(),
\fBexecve\fR(),
\fBexecvp\fR(),
\fBexecvpe\fR(),
or
\fBexecvpe\fR()
\fBsystem\fR()
library functions.
For example, if a shell is run by
\fBsudo\fR,
@@ -4305,8 +4306,9 @@ Preload a dynamic shared object (shared library) that intercepts the
\fBexecv\fR(),
\fBexecve\fR(),
\fBexecvp\fR(),
\fBexecvpe\fR(),
and
\fBexecvpe\fR()
\fBsystem\fR()
library functions.
A value of
\fIdso\fR
@@ -6929,8 +6931,9 @@ functionality only works for programs that use the
\fBexecv\fR(),
\fBexecve\fR(),
\fBexecvp\fR(),
\fBexecvpe\fR(),
or
\fBexecvpe\fR()
\fBsystem\fR()
library functions to run the new command.
This may be expanded in a future release of
\fBsudo\fR.

View File

@@ -25,7 +25,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.nr PS @PSMAN@
.Dd May 24, 2022
.Dd May 31, 2022
.Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@@ -2985,8 +2985,9 @@ using the
.Fn execv ,
.Fn execve ,
.Fn execvp ,
.Fn execvpe ,
or
.Fn execvpe
.Fn system
library functions.
For example, if a shell is run by
.Nm sudo ,
@@ -4077,8 +4078,9 @@ Preload a dynamic shared object (shared library) that intercepts the
.Fn execv ,
.Fn execve ,
.Fn execvp ,
.Fn execvpe ,
and
.Fn execvpe
.Fn system
library functions.
A value of
.Em dso
@@ -6420,8 +6422,9 @@ functionality only works for programs that use the
.Fn execv ,
.Fn execve ,
.Fn execvp ,
.Fn execvpe ,
or
.Fn execvpe
.Fn system
library functions to run the new command.
This may be expanded in a future release of
.Nm sudo .

View File

@@ -4,3 +4,4 @@ execlp
execv
execve
execvp
system

View File

@@ -25,6 +25,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdarg.h>
@@ -34,6 +35,7 @@
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <signal.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
@@ -193,7 +195,8 @@ exec_wrapper(const char *cmnd, char * const argv[], char * const envp[],
static int
execl_wrapper(int type, const char *name, const char *arg, va_list ap)
{
char **argv, **envp = environ;
char * const *envp = environ;
char **argv;
int argc = 1;
va_list ap2;
debug_decl(execl_wrapper, SUDO_DEBUG_EXEC);
@@ -219,6 +222,72 @@ execl_wrapper(int type, const char *name, const char *arg, va_list ap)
debug_return_int(-1);
}
static int
system_wrapper(const char *cmnd)
{
char * const argv[] = { "sh", "-c", (char *)cmnd, NULL };
const char shell[] = _PATH_SUDO_BSHELL;
struct sigaction saveint, savequit, sa;
sigset_t mask, omask;
pid_t child;
int status;
debug_decl(system_wrapper, SUDO_DEBUG_EXEC);
/* Special case for NULL command, just check whether shell exists. */
if (cmnd == NULL)
debug_return_int(access(shell, X_OK) == 0);
/* First, block signals to avoid potential race conditions. */
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
if (sigprocmask(SIG_BLOCK, &mask, &omask) == -1)
debug_return_int(-1);
switch (child = vfork()) {
case -1:
/* error */
(void)sigprocmask(SIG_SETMASK, &omask, NULL);
debug_return_int(-1);
case 0:
/* child */
if (sigprocmask(SIG_SETMASK, &omask, NULL) != -1)
exec_wrapper(shell, argv, environ, false);
_exit(127);
default:
/* parent */
break;
}
/* We must ignore SIGINT and SIGQUIT until the command finishes. */
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
(void)sigaction(SIGINT, &sa, &saveint);
(void)sigaction(SIGQUIT, &sa, &savequit);
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
(void)sigprocmask(SIG_UNBLOCK, &mask, NULL);
for (;;) {
if (waitpid(child, &status, 0) == -1) {
if (errno == EINTR)
continue;
status = -1;
}
break;
}
/* Restore signal mask and handlers. */
(void)sigprocmask(SIG_SETMASK, &omask, NULL);
(void)sigaction(SIGINT, &saveint, NULL);
(void)sigaction(SIGQUIT, &savequit, NULL);
debug_return_int(status);
}
#ifdef HAVE___INTERPOSE
/*
* Mac OS X 10.4 and above has support for library symbol interposition.
@@ -229,6 +298,12 @@ typedef struct interpose_s {
void *orig_func;
} interpose_t;
static int
my_system(const char *cmnd)
{
return system_wrapper(cmnd);
}
static int
my_execve(const char *cmnd, char * const argv[], char * const envp[])
{
@@ -238,7 +313,7 @@ my_execve(const char *cmnd, char * const argv[], char * const envp[])
static int
my_execv(const char *cmnd, char * const argv[])
{
return execve(cmnd, argv, environ);
return exec_wrapper(cmnd, argv, environ, false);
}
#ifdef HAVE_EXECVPE
@@ -294,6 +369,7 @@ my_execlp(const char *name, const char *arg, ...)
/* Magic to tell dyld to do symbol interposition. */
__attribute__((__used__)) static const interpose_t interposers[]
__attribute__((__section__("__DATA,__interpose"))) = {
{ (void *)my_system, (void *)system },
{ (void *)my_execl, (void *)execl },
{ (void *)my_execle, (void *)execle },
{ (void *)my_execlp, (void *)execlp },
@@ -332,6 +408,12 @@ sudo_shl_get_next(const char *symbol, short type)
}
# endif /* HAVE_SHL_LOAD */
sudo_dso_public int
system(const char *cmnd)
{
return system_wrapper(cmnd);
}
sudo_dso_public int
execve(const char *cmnd, char * const argv[], char * const envp[])
{