diff --git a/plugins/sudoers/audit.c b/plugins/sudoers/audit.c index def7a3bff..6d7d2c630 100644 --- a/plugins/sudoers/audit.c +++ b/plugins/sudoers/audit.c @@ -208,7 +208,7 @@ audit_to_eventlog(struct eventlog *evlog, char * const command_info[], debug_decl(audit_to_eventlog, SUDOERS_DEBUG_PLUGIN); /* 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[]. */ if (command_info != NULL) { diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index 3f9aa7f32..b8f4c4fdc 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -263,7 +263,7 @@ log_reject(const char *message, bool logit, bool mailit) if (!logit) 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); if (!log_server_reject(&evlog, message)) ret = false; @@ -612,7 +612,8 @@ log_exit_status(int status) /* Log and mail messages should be in the sudoers locale. */ 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) { SET(evl_flags, EVLOG_MAIL); 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)) 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); log_server_alert(&evlog, &now, message, errstr); } @@ -791,7 +793,8 @@ mail_parse_errors(void) ret = false; 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; 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. */ void -sudoers_to_eventlog(struct eventlog *evlog, char * const argv[], - char * const envp[], const char *uuid_str) +sudoers_to_eventlog(struct eventlog *evlog, const char *cmnd, + char * const argv[], char * const envp[], const char *uuid_str) { struct group *grp; 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)); evlog->iolog_file = sudo_user.iolog_file; 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; if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) { evlog->runchroot = def_runchroot; diff --git a/plugins/sudoers/logging.h b/plugins/sudoers/logging.h index 887b91aaa..010920930 100644 --- a/plugins/sudoers/logging.h +++ b/plugins/sudoers/logging.h @@ -62,6 +62,7 @@ typedef bool (*sudoers_logger_t)(const char *file, int line, int column, const c /* XXX - needed for auditing */ extern int NewArgc; extern char **NewArgv; +extern char **saved_argv; extern char *audit_msg; 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 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); -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); 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); diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 66e429299..b48de3e1f 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -102,6 +102,7 @@ static struct rlimit nproclimit; /* XXX - must be extern for audit bits of sudo_auth.c */ int NewArgc; char **NewArgv; +char **saved_argv; #ifdef SUDOERS_LOG_CLIENT # 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 * '-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); free(NewArgv); } @@ -803,8 +804,10 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], goto bad; } /* find_editor() already g/c'd edit_argv[] */ - sudoers_gc_remove(GC_PTR, NewArgv); - free(NewArgv); + if (NewArgv != saved_argv) { + sudoers_gc_remove(GC_PTR, NewArgv); + free(NewArgv); + } NewArgv = edit_argv; NewArgc = edit_argc; @@ -812,6 +815,16 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], 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; bad: @@ -1764,6 +1777,7 @@ sudoers_cleanup(void) /* Clear globals */ list_pw = NULL; + saved_argv = NULL; NewArgv = NULL; NewArgc = 0; prev_user = NULL; @@ -1820,6 +1834,7 @@ sudo_user_free(void) free(user_cmnd); free(user_args); free(safe_cmnd); + free(saved_cmnd); free(user_stat); #ifdef HAVE_SELINUX free(user_role); diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 80226b43e..da6d8cde0 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -103,6 +103,7 @@ struct sudo_user { char *cmnd_args; char *cmnd_base; char *cmnd_safe; + char *cmnd_saved; char *class_name; char *krb5_ccname; struct gid_list *gid_list; @@ -245,6 +246,7 @@ struct sudo_user { #define user_srunhost (sudo_user.srunhost) #define user_ccname (sudo_user.krb5_ccname) #define safe_cmnd (sudo_user.cmnd_safe) +#define saved_cmnd (sudo_user.cmnd_saved) #define cmnd_fd (sudo_user.execfd) #define login_class (sudo_user.class_name) #define runas_pw (sudo_user._runas_pw)