diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h index 8d4d8b75f..457f519dc 100644 --- a/include/sudo_eventlog.h +++ b/include/sudo_eventlog.h @@ -129,7 +129,7 @@ struct json_container; typedef bool (*eventlog_json_callback_t)(struct json_container *, void *); bool eventlog_accept(const struct eventlog *evlog, int flags, eventlog_json_callback_t info_cb, void *info); -bool eventlog_exit(const struct eventlog *evlog, int flags, struct timespec *run_time, int exit_value, const char *signal_name, bool core_dumped); +bool eventlog_exit(const struct eventlog *evlog, int flags); bool eventlog_alert(const struct eventlog *evlog, int flags, struct timespec *alert_time, const char *reason, const char *errstr); bool eventlog_reject(const struct eventlog *evlog, int flags, const char *reason, eventlog_json_callback_t info_cb, void *info); bool eventlog_store_json(struct json_container *json, const struct eventlog *evlog); diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c index 9f47c999e..794e23a71 100644 --- a/lib/eventlog/eventlog.c +++ b/lib/eventlog/eventlog.c @@ -80,10 +80,7 @@ struct eventlog_args { const char *reason; const char *errstr; - const char *signal_name; const struct timespec *event_time; - int exit_value; - bool core_dumped; eventlog_json_callback_t json_info_cb; void *json_info; }; @@ -201,10 +198,12 @@ new_logline(int event_type, int flags, struct eventlog_args *args, len += strlen(evlog->argv[i]) + 1; } if (event_type == EVLOG_EXIT) { - if (args->signal_name != NULL) - len += sizeof(LL_SIGNAL_STR) + 2 + strlen(args->signal_name); - (void)snprintf(exit_str, sizeof(exit_str), "%d", args->exit_value); - len += sizeof(LL_EXIT_STR) + 2 + strlen(exit_str); + if (evlog->signal_name != NULL) + len += sizeof(LL_SIGNAL_STR) + 2 + strlen(evlog->signal_name); + if (evlog->exit_value != -1) { + (void)snprintf(exit_str, sizeof(exit_str), "%d", evlog->exit_value); + len += sizeof(LL_EXIT_STR) + 2 + strlen(exit_str); + } } } @@ -289,16 +288,18 @@ new_logline(int event_type, int flags, struct eventlog_args *args, } } if (event_type == EVLOG_EXIT) { - if (args->signal_name != NULL) { + if (evlog->signal_name != NULL) { if (strlcat(line, " ; ", len) >= len || strlcat(line, LL_SIGNAL_STR, len) >= len || - strlcat(line, args->signal_name, len) >= len) + strlcat(line, evlog->signal_name, len) >= len) + goto toobig; + } + if (evlog->exit_value != -1) { + if (strlcat(line, " ; ", len) >= len || + strlcat(line, LL_EXIT_STR, len) >= len || + strlcat(line, exit_str, len) >= len) goto toobig; } - if (strlcat(line, " ; ", len) >= len || - strlcat(line, LL_EXIT_STR, len) >= len || - strlcat(line, exit_str, len) >= len) - goto toobig; } } @@ -819,7 +820,6 @@ format_json(int event_type, struct eventlog_args *args, struct json_container json = { 0 }; struct json_value json_value; const char *time_str, *type_str; - bool format_timestamp = true; struct timespec now; debug_decl(format_json, SUDO_DEBUG_UTIL); @@ -849,8 +849,7 @@ format_json(int event_type, struct eventlog_args *args, break; case EVLOG_EXIT: type_str = "exit"; - time_str = "run_time"; - format_timestamp = false; + time_str = "exit_time"; break; default: sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, @@ -901,7 +900,7 @@ format_json(int event_type, struct eventlog_args *args, /* Log event time from client */ if (args->event_time != NULL) { - if (!json_add_timestamp(&json, time_str, args->event_time, format_timestamp)) { + if (!json_add_timestamp(&json, time_str, args->event_time, true)) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "unable format timestamp"); goto bad; @@ -915,19 +914,26 @@ format_json(int event_type, struct eventlog_args *args, info = NULL; } - if (args->signal_name != NULL) { + if (sudo_timespecisset(&evlog->run_time)) { + if (!json_add_timestamp(&json, "run_time", &evlog->run_time, false)) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "unable format timestamp"); + goto bad; + } + } + if (evlog->signal_name != NULL) { json_value.type = JSON_STRING; - json_value.u.string = args->signal_name; + json_value.u.string = evlog->signal_name; if (!sudo_json_add_value(&json, "signal", &json_value)) goto bad; json_value.type = JSON_BOOL; - json_value.u.boolean = args->core_dumped; + json_value.u.boolean = evlog->dumped_core; if (!sudo_json_add_value(&json, "dumped_core", &json_value)) goto bad; } json_value.type = JSON_NUMBER; - json_value.u.number = args->exit_value; + json_value.u.number = evlog->exit_value; if (!sudo_json_add_value(&json, "exit_value", &json_value)) goto bad; } @@ -1369,20 +1375,19 @@ eventlog_alert(const struct eventlog *evlog, int flags, } bool -eventlog_exit(const struct eventlog *evlog, int flags, - struct timespec *run_time, int exit_value, const char *signal_name, - bool core_dumped) +eventlog_exit(const struct eventlog *evlog, int flags) { const struct eventlog_config *evl_conf = eventlog_getconf(); const int log_type = evl_conf->type; struct eventlog_args args = { NULL }; + struct timespec exit_time; bool ret = true; debug_decl(eventlog_exit, SUDO_DEBUG_UTIL); - args.signal_name = signal_name; - args.core_dumped = core_dumped; - args.exit_value = exit_value; - args.event_time = run_time; + if (sudo_timespecisset(&evlog->run_time)) { + sudo_timespecadd(&evlog->submit_time, &evlog->run_time, &exit_time); + args.event_time = &exit_time; + } if (ISSET(log_type, EVLOG_SYSLOG)) { if (!do_syslog(EVLOG_EXIT, flags, &args, evlog)) diff --git a/logsrvd/logsrvd_local.c b/logsrvd/logsrvd_local.c index 6c7bc2fcf..8fc90d274 100644 --- a/logsrvd/logsrvd_local.c +++ b/logsrvd/logsrvd_local.c @@ -262,9 +262,7 @@ done: } static bool -store_exit_info_json(int dfd, struct timespec *run_time, int exit_value, - const char *signal_name, bool core_dumped, - struct connection_closure *closure) +store_exit_info_json(int dfd, struct eventlog *evlog) { struct json_container json = { 0 }; struct json_value json_value; @@ -280,7 +278,7 @@ store_exit_info_json(int dfd, struct timespec *run_time, int exit_value, fd = openat(dfd, "log.json", O_RDWR); if (fd == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, - "unable to open to %s/log.json", closure->evlog->iolog_path); + "unable to open to %s/log.json", evlog->iolog_path); if (errno == ENOENT) { /* Ignore missing log.json file. */ ret = true; @@ -288,17 +286,17 @@ store_exit_info_json(int dfd, struct timespec *run_time, int exit_value, goto done; } - if (run_time != NULL) { + if (sudo_timespecisset(&evlog->run_time)) { if (!sudo_json_open_object(&json, "run_time")) goto done; json_value.type = JSON_NUMBER; - json_value.u.number = run_time->tv_sec; + json_value.u.number = evlog->run_time.tv_sec; if (!sudo_json_add_value(&json, "seconds", &json_value)) goto done; json_value.type = JSON_NUMBER; - json_value.u.number = run_time->tv_nsec; + json_value.u.number = evlog->run_time.tv_nsec; if (!sudo_json_add_value(&json, "nanoseconds", &json_value)) goto done; @@ -306,20 +304,20 @@ store_exit_info_json(int dfd, struct timespec *run_time, int exit_value, goto done; } - if (signal_name != NULL) { + if (evlog->signal_name != NULL) { json_value.type = JSON_STRING; - json_value.u.string = signal_name; + json_value.u.string = evlog->signal_name; if (!sudo_json_add_value(&json, "signal", &json_value)) goto done; json_value.type = JSON_BOOL; - json_value.u.boolean = core_dumped; + json_value.u.boolean = evlog->dumped_core; if (!sudo_json_add_value(&json, "dumped_core", &json_value)) goto done; } json_value.type = JSON_NUMBER; - json_value.u.number = exit_value; + json_value.u.number = evlog->exit_value; if (!sudo_json_add_value(&json, "exit_value", &json_value)) goto done; @@ -327,7 +325,7 @@ store_exit_info_json(int dfd, struct timespec *run_time, int exit_value, pos = lseek(fd, -3, SEEK_END); if (pos == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, - "unable to rewind %s/log.json 3 bytes", closure->evlog->iolog_path); + "unable to rewind %s/log.json 3 bytes", evlog->iolog_path); goto done; } @@ -340,7 +338,7 @@ store_exit_info_json(int dfd, struct timespec *run_time, int exit_value, iov[2].iov_len = 3; if (writev(fd, iov, 3) == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, - "unable to write %s/log.json", closure->evlog->iolog_path); + "unable to write %s/log.json", evlog->iolog_path); /* Back up and try to restore to original state. */ if (lseek(fd, pos, SEEK_SET) != -1) { ignore_result(write(fd, "\n}\n", 3)); @@ -361,28 +359,31 @@ bool store_exit_local(ExitMessage *msg, uint8_t *buf, size_t len, struct connection_closure *closure) { - struct timespec ts, *run_time = NULL; - const char *signame = NULL; + struct eventlog *evlog = closure->evlog; int flags = 0; debug_decl(store_exit_local, SUDO_DEBUG_UTIL); if (msg->run_time != NULL) { - ts.tv_sec = msg->run_time->tv_sec; - ts.tv_nsec = msg->run_time->tv_nsec; - run_time = &ts; + evlog->run_time.tv_sec = msg->run_time->tv_sec; + evlog->run_time.tv_nsec = msg->run_time->tv_nsec; } + evlog->exit_value = msg->exit_value; if (msg->signal != NULL && msg->signal[0] != '\0') { - signame = msg->signal; sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "command was killed by SIG%s%s", msg->signal, msg->dumped_core ? " (core dumped)" : ""); + evlog->signal_name = strdup(msg->signal); + if (evlog->signal_name == NULL) { + closure->errstr = _("unable to allocate memory"); + debug_return_bool(false); + } + evlog->dumped_core = msg->dumped_core; } else { sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "command exited with %d", msg->exit_value); } if (logsrvd_conf_log_exit()) { - if (!eventlog_exit(closure->evlog, flags, run_time, msg->exit_value, - signame, msg->dumped_core)) { + if (!eventlog_exit(closure->evlog, flags)) { closure->errstr = _("error logging exit event"); debug_return_bool(false); } @@ -390,8 +391,7 @@ store_exit_local(ExitMessage *msg, uint8_t *buf, size_t len, if (closure->log_io) { /* Store the run time and exit status in log.json. */ - if (!store_exit_info_json(closure->iolog_dir_fd, run_time, - msg->exit_value, signame, msg->dumped_core, closure)) { + if (!store_exit_info_json(closure->iolog_dir_fd, evlog)) { closure->errstr = _("error logging exit event"); debug_return_bool(false); } diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index b410113ff..7d1a36241 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -575,8 +575,11 @@ log_exit_status(int exit_status) if (!def_log_exit_status) SET(evl_flags, EVLOG_MAIL_ONLY); } - if (!eventlog_exit(&evlog, evl_flags, &run_time, ecode, signame, - dumped_core)) + evlog.run_time = run_time; + evlog.exit_value = ecode; + evlog.signal_name = signame; + evlog.dumped_core = dumped_core; + if (!eventlog_exit(&evlog, evl_flags)) ret = false; sudoers_setlocale(oldlocale, NULL);