Save the initial command run via sudo and use it when logging exit status.

Otherwise, if we are in intercept mode or logging sub-commands the
exit status will be logged with the wrong command.
This commit is contained in:
Todd C. Miller
2022-06-30 11:10:43 -06:00
parent 3badff39ca
commit 885abf48d7
5 changed files with 33 additions and 12 deletions

View File

@@ -208,7 +208,7 @@ audit_to_eventlog(struct eventlog *evlog, char * const command_info[],
debug_decl(audit_to_eventlog, SUDOERS_DEBUG_PLUGIN); debug_decl(audit_to_eventlog, SUDOERS_DEBUG_PLUGIN);
/* Fill in evlog from sudoers Defaults, run_argv and run_envp. */ /* Fill in evlog from sudoers Defaults, run_argv and run_envp. */
sudoers_to_eventlog(evlog, run_argv, run_envp, uuid_str); sudoers_to_eventlog(evlog, NULL, run_argv, run_envp, uuid_str);
/* Update iolog and execution environment from command_info[]. */ /* Update iolog and execution environment from command_info[]. */
if (command_info != NULL) { if (command_info != NULL) {

View File

@@ -263,7 +263,7 @@ log_reject(const char *message, bool logit, bool mailit)
if (!logit) if (!logit)
SET(evl_flags, EVLOG_MAIL_ONLY); SET(evl_flags, EVLOG_MAIL_ONLY);
} }
sudoers_to_eventlog(&evlog, NewArgv, env_get(), uuid_str); sudoers_to_eventlog(&evlog, safe_cmnd, NewArgv, env_get(), uuid_str);
ret = eventlog_reject(&evlog, evl_flags, message, NULL, NULL); ret = eventlog_reject(&evlog, evl_flags, message, NULL, NULL);
if (!log_server_reject(&evlog, message)) if (!log_server_reject(&evlog, message))
ret = false; ret = false;
@@ -612,7 +612,8 @@ log_exit_status(int status)
/* Log and mail messages should be in the sudoers locale. */ /* Log and mail messages should be in the sudoers locale. */
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
sudoers_to_eventlog(&evlog, NewArgv, env_get(), sudo_user.uuid_str); sudoers_to_eventlog(&evlog, saved_cmnd, saved_argv, env_get(),
sudo_user.uuid_str);
if (def_mail_always) { if (def_mail_always) {
SET(evl_flags, EVLOG_MAIL); SET(evl_flags, EVLOG_MAIL);
if (!def_log_exit_status) if (!def_log_exit_status)
@@ -695,7 +696,8 @@ vlog_warning(int flags, int errnum, const char *fmt, va_list ap)
if (ISSET(flags, SLOG_NO_LOG)) if (ISSET(flags, SLOG_NO_LOG))
SET(evl_flags, EVLOG_MAIL_ONLY); SET(evl_flags, EVLOG_MAIL_ONLY);
} }
sudoers_to_eventlog(&evlog, NewArgv, env_get(), sudo_user.uuid_str); sudoers_to_eventlog(&evlog, safe_cmnd, NewArgv, env_get(),
sudo_user.uuid_str);
eventlog_alert(&evlog, evl_flags, &now, message, errstr); eventlog_alert(&evlog, evl_flags, &now, message, errstr);
log_server_alert(&evlog, &now, message, errstr); log_server_alert(&evlog, &now, message, errstr);
} }
@@ -791,7 +793,8 @@ mail_parse_errors(void)
ret = false; ret = false;
goto done; goto done;
} }
sudoers_to_eventlog(&evlog, NewArgv, env_get(), sudo_user.uuid_str); sudoers_to_eventlog(&evlog, safe_cmnd, NewArgv, env_get(),
sudo_user.uuid_str);
len = strlen(_("problem parsing sudoers")) + 1; len = strlen(_("problem parsing sudoers")) + 1;
STAILQ_FOREACH(pe, &parse_error_list, entries) { STAILQ_FOREACH(pe, &parse_error_list, entries) {
@@ -916,8 +919,8 @@ should_mail(int status)
* The values in the resulting eventlog struct should not be freed. * The values in the resulting eventlog struct should not be freed.
*/ */
void void
sudoers_to_eventlog(struct eventlog *evlog, char * const argv[], sudoers_to_eventlog(struct eventlog *evlog, const char *cmnd,
char * const envp[], const char *uuid_str) char * const argv[], char * const envp[], const char *uuid_str)
{ {
struct group *grp; struct group *grp;
debug_decl(sudoers_to_eventlog, SUDOERS_DEBUG_LOGGING); debug_decl(sudoers_to_eventlog, SUDOERS_DEBUG_LOGGING);
@@ -929,7 +932,7 @@ sudoers_to_eventlog(struct eventlog *evlog, char * const argv[],
memset(evlog, 0, sizeof(*evlog)); memset(evlog, 0, sizeof(*evlog));
evlog->iolog_file = sudo_user.iolog_file; evlog->iolog_file = sudo_user.iolog_file;
evlog->iolog_path = sudo_user.iolog_path; evlog->iolog_path = sudo_user.iolog_path;
evlog->command = safe_cmnd ? safe_cmnd : (argv ? argv[0] : NULL); evlog->command = cmnd ? (char *)cmnd : (argv ? argv[0] : NULL);
evlog->cwd = user_cwd; evlog->cwd = user_cwd;
if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) { if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) {
evlog->runchroot = def_runchroot; evlog->runchroot = def_runchroot;

View File

@@ -62,6 +62,7 @@ typedef bool (*sudoers_logger_t)(const char *file, int line, int column, const c
/* XXX - needed for auditing */ /* XXX - needed for auditing */
extern int NewArgc; extern int NewArgc;
extern char **NewArgv; extern char **NewArgv;
extern char **saved_argv;
extern char *audit_msg; extern char *audit_msg;
union sudo_defs_val; union sudo_defs_val;
@@ -85,7 +86,7 @@ bool log_warningx(int flags, const char *fmt, ...) __printflike(2, 3);
bool gai_log_warning(int flags, int errnum, const char *fmt, ...) __printflike(3, 4); bool gai_log_warning(int flags, int errnum, const char *fmt, ...) __printflike(3, 4);
bool sudoers_initlocale(const char *ulocale, const char *slocale); bool sudoers_initlocale(const char *ulocale, const char *slocale);
bool sudoers_locale_callback(const char *file, int line, int column, const union sudo_defs_val *sd_un, int op); bool sudoers_locale_callback(const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
void sudoers_to_eventlog(struct eventlog *evlog, char * const argv[], char *const envp[], const char *uuid_str); void sudoers_to_eventlog(struct eventlog *evlog, const char *cmnd, char * const argv[], char *const envp[], const char *uuid_str);
void init_eventlog_config(void); void init_eventlog_config(void);
bool init_log_details(struct log_details *details, struct eventlog *evlog); bool init_log_details(struct log_details *details, struct eventlog *evlog);
bool log_parse_error(const char *file, int line, int column, const char *fmt, va_list ap) __printflike(4, 0); bool log_parse_error(const char *file, int line, int column, const char *fmt, va_list ap) __printflike(4, 0);

View File

@@ -102,6 +102,7 @@ static struct rlimit nproclimit;
/* XXX - must be extern for audit bits of sudo_auth.c */ /* XXX - must be extern for audit bits of sudo_auth.c */
int NewArgc; int NewArgc;
char **NewArgv; char **NewArgv;
char **saved_argv;
#ifdef SUDOERS_LOG_CLIENT #ifdef SUDOERS_LOG_CLIENT
# define remote_iologs (!SLIST_EMPTY(&def_log_servers)) # define remote_iologs (!SLIST_EMPTY(&def_log_servers))
@@ -433,7 +434,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
* Make a local copy of argc/argv, with special handling for the * Make a local copy of argc/argv, with special handling for the
* '-i' option. We also allocate an extra slot for bash's --login. * '-i' option. We also allocate an extra slot for bash's --login.
*/ */
if (NewArgv != NULL) { if (NewArgv != NULL && NewArgv != saved_argv) {
sudoers_gc_remove(GC_PTR, NewArgv); sudoers_gc_remove(GC_PTR, NewArgv);
free(NewArgv); free(NewArgv);
} }
@@ -803,8 +804,10 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
goto bad; goto bad;
} }
/* find_editor() already g/c'd edit_argv[] */ /* find_editor() already g/c'd edit_argv[] */
sudoers_gc_remove(GC_PTR, NewArgv); if (NewArgv != saved_argv) {
free(NewArgv); sudoers_gc_remove(GC_PTR, NewArgv);
free(NewArgv);
}
NewArgv = edit_argv; NewArgv = edit_argv;
NewArgc = edit_argc; NewArgc = edit_argc;
@@ -812,6 +815,16 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
env_swap_old(); env_swap_old();
} }
/* Save the initial command and argv so we have it for exit logging. */
if (saved_cmnd == NULL) {
saved_cmnd = strdup(safe_cmnd);
if (saved_cmnd == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto done;
}
saved_argv = NewArgv;
}
goto done; goto done;
bad: bad:
@@ -1764,6 +1777,7 @@ sudoers_cleanup(void)
/* Clear globals */ /* Clear globals */
list_pw = NULL; list_pw = NULL;
saved_argv = NULL;
NewArgv = NULL; NewArgv = NULL;
NewArgc = 0; NewArgc = 0;
prev_user = NULL; prev_user = NULL;
@@ -1820,6 +1834,7 @@ sudo_user_free(void)
free(user_cmnd); free(user_cmnd);
free(user_args); free(user_args);
free(safe_cmnd); free(safe_cmnd);
free(saved_cmnd);
free(user_stat); free(user_stat);
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
free(user_role); free(user_role);

View File

@@ -103,6 +103,7 @@ struct sudo_user {
char *cmnd_args; char *cmnd_args;
char *cmnd_base; char *cmnd_base;
char *cmnd_safe; char *cmnd_safe;
char *cmnd_saved;
char *class_name; char *class_name;
char *krb5_ccname; char *krb5_ccname;
struct gid_list *gid_list; struct gid_list *gid_list;
@@ -245,6 +246,7 @@ struct sudo_user {
#define user_srunhost (sudo_user.srunhost) #define user_srunhost (sudo_user.srunhost)
#define user_ccname (sudo_user.krb5_ccname) #define user_ccname (sudo_user.krb5_ccname)
#define safe_cmnd (sudo_user.cmnd_safe) #define safe_cmnd (sudo_user.cmnd_safe)
#define saved_cmnd (sudo_user.cmnd_saved)
#define cmnd_fd (sudo_user.execfd) #define cmnd_fd (sudo_user.execfd)
#define login_class (sudo_user.class_name) #define login_class (sudo_user.class_name)
#define runas_pw (sudo_user._runas_pw) #define runas_pw (sudo_user._runas_pw)