Add log_exit_status sudoers option to log when a command exits.

This option defaults to off.
This commit is contained in:
Todd C. Miller
2021-07-09 11:08:44 -06:00
parent b54a16e174
commit 17a415ae77
9 changed files with 101 additions and 5 deletions

View File

@@ -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 7, 2021" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .TH "SUDOERS" "@mansectform@" "July 9, 2021" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh .nh
.if n .ad l .if n .ad l
.SH "NAME" .SH "NAME"
@@ -2728,6 +2728,17 @@ by default.
.sp .sp
This setting is only supported by version 1.8.29 or higher. This setting is only supported by version 1.8.29 or higher.
.TP 18n .TP 18n
log_exit_status
If set,
\fBsudoers\fR
will log the exit value of commands that are run to syslog and/or a log file.
If a command was terminated by a signal, the signal name is logged as well.
This flag is
\fIoff\fR
by default.
.sp
This setting is only supported by version 1.9.8 or higher.
.TP 18n
log_host log_host
If set, the host name will be included in log entries written to If set, the host name will be included in log entries written to
the file configured by the the file configured by the

View File

@@ -24,7 +24,7 @@
.nr BA @BAMAN@ .nr BA @BAMAN@
.nr LC @LCMAN@ .nr LC @LCMAN@
.nr PS @PSMAN@ .nr PS @PSMAN@
.Dd May 7, 2021 .Dd July 9, 2021
.Dt SUDOERS @mansectform@ .Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@ .Os Sudo @PACKAGE_VERSION@
.Sh NAME .Sh NAME
@@ -2573,6 +2573,16 @@ This flag is
by default. by default.
.Pp .Pp
This setting is only supported by version 1.8.29 or higher. This setting is only supported by version 1.8.29 or higher.
.It log_exit_status
If set,
.Nm
will log the exit value of commands that are run to syslog and/or a log file.
If a command was terminated by a signal, the signal name is logged as well.
This flag is
.Em off
by default.
.Pp
This setting is only supported by version 1.9.8 or higher.
.It log_host .It log_host
If set, the host name will be included in log entries written to If set, the host name will be included in log entries written to
the file configured by the the file configured by the

View File

@@ -577,6 +577,10 @@ struct sudo_defs_types sudo_defs_table[] = {
"admin_flag", T_STR|T_BOOL|T_CHPATH, "admin_flag", T_STR|T_BOOL|T_CHPATH,
N_("Path to the file that is created the first time sudo is run: %s"), N_("Path to the file that is created the first time sudo is run: %s"),
NULL, NULL,
}, {
"log_exit_status", T_FLAG,
N_("Log the exit status of commands"),
NULL,
}, { }, {
NULL, 0, NULL NULL, 0, NULL
} }

View File

@@ -266,6 +266,8 @@
#define def_selinux (sudo_defs_table[I_SELINUX].sd_un.flag) #define def_selinux (sudo_defs_table[I_SELINUX].sd_un.flag)
#define I_ADMIN_FLAG 132 #define I_ADMIN_FLAG 132
#define def_admin_flag (sudo_defs_table[I_ADMIN_FLAG].sd_un.str) #define def_admin_flag (sudo_defs_table[I_ADMIN_FLAG].sd_un.str)
#define I_LOG_EXIT_STATUS 133
#define def_log_exit_status (sudo_defs_table[I_LOG_EXIT_STATUS].sd_un.flag)
enum def_tuple { enum def_tuple {
never, never,

View File

@@ -415,3 +415,6 @@ selinux
admin_flag admin_flag
T_STR|T_BOOL|T_CHPATH T_STR|T_BOOL|T_CHPATH
"Path to the file that is created the first time sudo is run: %s" "Path to the file that is created the first time sudo is run: %s"
log_exit_status
T_FLAG
"Log the exit status of commands"

View File

@@ -492,6 +492,63 @@ log_allowed(void)
debug_return_bool(ret); debug_return_bool(ret);
} }
bool
log_exit_status(int exit_status)
{
struct eventlog evlog;
int evl_flags = 0;
int ecode = 0;
int oldlocale;
struct timespec run_time;
char sigbuf[SIG2STR_MAX];
char *signame = NULL;
bool dumped_core = false;
bool ret = true;
debug_decl(log_exit_status, SUDOERS_DEBUG_LOGGING);
if (def_log_exit_status || def_mail_always) {
if (sudo_gettime_real(&run_time) == -1) {
sudo_warn("%s", U_("unable to get time of day"));
ret = false;
goto done;
}
sudo_timespecsub(&run_time, &sudo_user.submit_time, &run_time);
if (WIFEXITED(exit_status)) {
ecode = WEXITSTATUS(exit_status);
} else if (WIFSIGNALED(exit_status)) {
int signo = WTERMSIG(exit_status);
if (signo <= 0 || sig2str(signo, sigbuf) == -1)
(void)snprintf(sigbuf, sizeof(sigbuf), "%d", signo);
signame = sigbuf;
ecode = signo | 128;
dumped_core = WCOREDUMP(exit_status);
} else {
sudo_warnx("invalid exit status 0x%x", exit_status);
ret = false;
goto done;
}
/* Log and mail messages should be in the sudoers locale. */
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
sudoers_to_eventlog(&evlog, NewArgv, env_get());
if (def_mail_always) {
SET(evl_flags, EVLOG_MAIL);
if (!def_log_exit_status)
SET(evl_flags, EVLOG_MAIL_ONLY);
}
if (!eventlog_exit(&evlog, evl_flags, &run_time, ecode, signame,
dumped_core, NULL, NULL))
ret = false;
sudoers_setlocale(oldlocale, NULL);
}
done:
debug_return_bool(ret);
}
/* /*
* Perform logging for log_warning()/log_warningx(). * Perform logging for log_warning()/log_warningx().
*/ */

View File

@@ -57,6 +57,7 @@ int sudoers_getlocale(void);
int audit_failure(char *const argv[], char const *const fmt, ...) __printflike(2, 3); int audit_failure(char *const argv[], char const *const fmt, ...) __printflike(2, 3);
int vaudit_failure(char *const argv[], char const *const fmt, va_list ap) __printflike(2, 0); int vaudit_failure(char *const argv[], char const *const fmt, va_list ap) __printflike(2, 0);
bool log_allowed(void); bool log_allowed(void);
bool log_exit_status(int exit_status);
bool log_auth_failure(int status, unsigned int tries); bool log_auth_failure(int status, unsigned int tries);
bool log_denial(int status, bool inform_user); bool log_denial(int status, bool inform_user);
bool log_failure(int status, int flags); bool log_failure(int status, int flags);

View File

@@ -961,10 +961,11 @@ sudoers_policy_close(int exit_status, int error_code)
/* Close the session we opened in sudoers_policy_init_session(). */ /* Close the session we opened in sudoers_policy_init_session(). */
(void)sudo_auth_end_session(runas_pw); (void)sudo_auth_end_session(runas_pw);
/* We do not currently log the exit status. */
if (error_code) { if (error_code) {
errno = error_code; errno = error_code;
sudo_warn(U_("unable to execute %s"), safe_cmnd); sudo_warn(U_("unable to execute %s"), safe_cmnd);
} else {
log_exit_status(exit_status);
} }
} }
@@ -1044,8 +1045,8 @@ sudoers_policy_check(int argc, char * const argv[], char *env_add[],
#ifndef NO_LEAKS #ifndef NO_LEAKS
if (ret == true && sudo_version >= SUDO_API_MKVERSION(1, 3)) { if (ret == true && sudo_version >= SUDO_API_MKVERSION(1, 3)) {
/* Unset close function if we don't need it to avoid extra process. */ /* Unset close function if we don't need it to avoid extra process. */
if (!def_log_input && !def_log_output && !def_use_pty && if (!def_log_input && !def_log_output && !def_log_exit_status &&
!sudo_auth_needs_end_session()) !def_use_pty && !sudo_auth_needs_end_session())
sudoers_policy.close = NULL; sudoers_policy.close = NULL;
} }
#endif #endif

View File

@@ -704,6 +704,13 @@ log_failure(int status, int flags)
return true; return true;
} }
/* STUB */
bool
log_exit_status(int exit_status)
{
return true;
}
/* STUB */ /* STUB */
int int
audit_failure(char *const argv[], char const *const fmt, ...) audit_failure(char *const argv[], char const *const fmt, ...)