Add support for intercepting the system(3) function.
This also means we can log system(3) with log_subcmds.
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.nr SL @SEMAN@
|
.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
|
.nh
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
@@ -296,8 +296,9 @@ The fully-qualified path to a shared library containing a wrappers for the
|
|||||||
\fBexecv\fR(),
|
\fBexecv\fR(),
|
||||||
\fBexecve\fR(),
|
\fBexecve\fR(),
|
||||||
\fBexecvp\fR(),
|
\fBexecvp\fR(),
|
||||||
|
\fBexecvpe\fR(),
|
||||||
and
|
and
|
||||||
\fBexecvpe\fR()
|
\fBsystem\fR()
|
||||||
library functions that intercepts attempts to run further commands and
|
library functions that intercepts attempts to run further commands and
|
||||||
performs a policy check before allowing them to be executed.
|
performs a policy check before allowing them to be executed.
|
||||||
This is used to implement the
|
This is used to implement the
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.nr SL @SEMAN@
|
.nr SL @SEMAN@
|
||||||
.Dd April 28, 2022
|
.Dd May 31, 2022
|
||||||
.Dt SUDO.CONF @mansectform@
|
.Dt SUDO.CONF @mansectform@
|
||||||
.Os Sudo @PACKAGE_VERSION@
|
.Os Sudo @PACKAGE_VERSION@
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -271,8 +271,9 @@ The fully-qualified path to a shared library containing a wrappers for the
|
|||||||
.Fn execv ,
|
.Fn execv ,
|
||||||
.Fn execve ,
|
.Fn execve ,
|
||||||
.Fn execvp ,
|
.Fn execvp ,
|
||||||
|
.Fn execvpe ,
|
||||||
and
|
and
|
||||||
.Fn execvpe
|
.Fn system
|
||||||
library functions that intercepts attempts to run further commands and
|
library functions that intercepts attempts to run further commands and
|
||||||
performs a policy check before allowing them to be executed.
|
performs a policy check before allowing them to be executed.
|
||||||
This is used to implement the
|
This is used to implement the
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.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
|
.nh
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
@@ -3151,8 +3151,9 @@ using the
|
|||||||
\fBexecv\fR(),
|
\fBexecv\fR(),
|
||||||
\fBexecve\fR(),
|
\fBexecve\fR(),
|
||||||
\fBexecvp\fR(),
|
\fBexecvp\fR(),
|
||||||
|
\fBexecvpe\fR(),
|
||||||
or
|
or
|
||||||
\fBexecvpe\fR()
|
\fBsystem\fR()
|
||||||
library functions.
|
library functions.
|
||||||
For example, if a shell is run by
|
For example, if a shell is run by
|
||||||
\fBsudo\fR,
|
\fBsudo\fR,
|
||||||
@@ -4305,8 +4306,9 @@ Preload a dynamic shared object (shared library) that intercepts the
|
|||||||
\fBexecv\fR(),
|
\fBexecv\fR(),
|
||||||
\fBexecve\fR(),
|
\fBexecve\fR(),
|
||||||
\fBexecvp\fR(),
|
\fBexecvp\fR(),
|
||||||
|
\fBexecvpe\fR(),
|
||||||
and
|
and
|
||||||
\fBexecvpe\fR()
|
\fBsystem\fR()
|
||||||
library functions.
|
library functions.
|
||||||
A value of
|
A value of
|
||||||
\fIdso\fR
|
\fIdso\fR
|
||||||
@@ -6929,8 +6931,9 @@ functionality only works for programs that use the
|
|||||||
\fBexecv\fR(),
|
\fBexecv\fR(),
|
||||||
\fBexecve\fR(),
|
\fBexecve\fR(),
|
||||||
\fBexecvp\fR(),
|
\fBexecvp\fR(),
|
||||||
|
\fBexecvpe\fR(),
|
||||||
or
|
or
|
||||||
\fBexecvpe\fR()
|
\fBsystem\fR()
|
||||||
library functions to run the new command.
|
library functions to run the new command.
|
||||||
This may be expanded in a future release of
|
This may be expanded in a future release of
|
||||||
\fBsudo\fR.
|
\fBsudo\fR.
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.nr PS @PSMAN@
|
||||||
.Dd May 24, 2022
|
.Dd May 31, 2022
|
||||||
.Dt SUDOERS @mansectform@
|
.Dt SUDOERS @mansectform@
|
||||||
.Os Sudo @PACKAGE_VERSION@
|
.Os Sudo @PACKAGE_VERSION@
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -2985,8 +2985,9 @@ using the
|
|||||||
.Fn execv ,
|
.Fn execv ,
|
||||||
.Fn execve ,
|
.Fn execve ,
|
||||||
.Fn execvp ,
|
.Fn execvp ,
|
||||||
|
.Fn execvpe ,
|
||||||
or
|
or
|
||||||
.Fn execvpe
|
.Fn system
|
||||||
library functions.
|
library functions.
|
||||||
For example, if a shell is run by
|
For example, if a shell is run by
|
||||||
.Nm sudo ,
|
.Nm sudo ,
|
||||||
@@ -4077,8 +4078,9 @@ Preload a dynamic shared object (shared library) that intercepts the
|
|||||||
.Fn execv ,
|
.Fn execv ,
|
||||||
.Fn execve ,
|
.Fn execve ,
|
||||||
.Fn execvp ,
|
.Fn execvp ,
|
||||||
|
.Fn execvpe ,
|
||||||
and
|
and
|
||||||
.Fn execvpe
|
.Fn system
|
||||||
library functions.
|
library functions.
|
||||||
A value of
|
A value of
|
||||||
.Em dso
|
.Em dso
|
||||||
@@ -6420,8 +6422,9 @@ functionality only works for programs that use the
|
|||||||
.Fn execv ,
|
.Fn execv ,
|
||||||
.Fn execve ,
|
.Fn execve ,
|
||||||
.Fn execvp ,
|
.Fn execvp ,
|
||||||
|
.Fn execvpe ,
|
||||||
or
|
or
|
||||||
.Fn execvpe
|
.Fn system
|
||||||
library functions to run the new command.
|
library functions to run the new command.
|
||||||
This may be expanded in a future release of
|
This may be expanded in a future release of
|
||||||
.Nm sudo .
|
.Nm sudo .
|
||||||
|
@@ -4,3 +4,4 @@ execlp
|
|||||||
execv
|
execv
|
||||||
execve
|
execve
|
||||||
execvp
|
execvp
|
||||||
|
system
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#ifdef HAVE_STDBOOL_H
|
#ifdef HAVE_STDBOOL_H
|
||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
#else
|
#else
|
||||||
@@ -193,7 +195,8 @@ exec_wrapper(const char *cmnd, char * const argv[], char * const envp[],
|
|||||||
static int
|
static int
|
||||||
execl_wrapper(int type, const char *name, const char *arg, va_list ap)
|
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;
|
int argc = 1;
|
||||||
va_list ap2;
|
va_list ap2;
|
||||||
debug_decl(execl_wrapper, SUDO_DEBUG_EXEC);
|
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);
|
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
|
#ifdef HAVE___INTERPOSE
|
||||||
/*
|
/*
|
||||||
* Mac OS X 10.4 and above has support for library symbol interposition.
|
* Mac OS X 10.4 and above has support for library symbol interposition.
|
||||||
@@ -229,6 +298,12 @@ typedef struct interpose_s {
|
|||||||
void *orig_func;
|
void *orig_func;
|
||||||
} interpose_t;
|
} interpose_t;
|
||||||
|
|
||||||
|
static int
|
||||||
|
my_system(const char *cmnd)
|
||||||
|
{
|
||||||
|
return system_wrapper(cmnd);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
my_execve(const char *cmnd, char * const argv[], char * const envp[])
|
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
|
static int
|
||||||
my_execv(const char *cmnd, char * const argv[])
|
my_execv(const char *cmnd, char * const argv[])
|
||||||
{
|
{
|
||||||
return execve(cmnd, argv, environ);
|
return exec_wrapper(cmnd, argv, environ, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_EXECVPE
|
#ifdef HAVE_EXECVPE
|
||||||
@@ -294,6 +369,7 @@ my_execlp(const char *name, const char *arg, ...)
|
|||||||
/* Magic to tell dyld to do symbol interposition. */
|
/* Magic to tell dyld to do symbol interposition. */
|
||||||
__attribute__((__used__)) static const interpose_t interposers[]
|
__attribute__((__used__)) static const interpose_t interposers[]
|
||||||
__attribute__((__section__("__DATA,__interpose"))) = {
|
__attribute__((__section__("__DATA,__interpose"))) = {
|
||||||
|
{ (void *)my_system, (void *)system },
|
||||||
{ (void *)my_execl, (void *)execl },
|
{ (void *)my_execl, (void *)execl },
|
||||||
{ (void *)my_execle, (void *)execle },
|
{ (void *)my_execle, (void *)execle },
|
||||||
{ (void *)my_execlp, (void *)execlp },
|
{ (void *)my_execlp, (void *)execlp },
|
||||||
@@ -332,6 +408,12 @@ sudo_shl_get_next(const char *symbol, short type)
|
|||||||
}
|
}
|
||||||
# endif /* HAVE_SHL_LOAD */
|
# endif /* HAVE_SHL_LOAD */
|
||||||
|
|
||||||
|
sudo_dso_public int
|
||||||
|
system(const char *cmnd)
|
||||||
|
{
|
||||||
|
return system_wrapper(cmnd);
|
||||||
|
}
|
||||||
|
|
||||||
sudo_dso_public int
|
sudo_dso_public int
|
||||||
execve(const char *cmnd, char * const argv[], char * const envp[])
|
execve(const char *cmnd, char * const argv[], char * const envp[])
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user