From 161750fc56f10e1df0332616decbda8cce5994c0 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 15 Jan 2020 14:47:42 -0700 Subject: [PATCH] Really fix flushing of data in client_close(). Now that we call fmt_exit_message() from client_close() we do not need to try to determine whether the read or write events were pending in the old base. We can't tell anyway because the active flag in the event was cleared when the old sudo event base was destroyed. It is correct to enable both the read and write events after formatting the ExitMessage. --- lib/util/event.c | 3 +++ plugins/sudoers/iolog_client.c | 48 ++++++++++++++++------------------ 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/lib/util/event.c b/lib/util/event.c index 03aa04972..a756bc770 100644 --- a/lib/util/event.c +++ b/lib/util/event.c @@ -845,6 +845,9 @@ sudo_ev_pending_v1(struct sudo_event *ev, short events, struct timespec *ts) int ret = 0; debug_decl(sudo_ev_pending, SUDO_DEBUG_EVENT); + sudo_debug_printf(SUDO_DEBUG_INFO, "%s: event %p, flags 0x%x, events 0x%x", + __func__, ev, ev->flags, ev->events); + if (!ISSET(ev->flags, SUDO_EVQ_INSERTED)) debug_return_int(0); diff --git a/plugins/sudoers/iolog_client.c b/plugins/sudoers/iolog_client.c index 9cd80db75..1ae450949 100644 --- a/plugins/sudoers/iolog_client.c +++ b/plugins/sudoers/iolog_client.c @@ -1396,13 +1396,16 @@ bool client_close(struct client_closure *closure, int exit_status, int error) { struct sudo_event_base *evbase = NULL; - short events; bool ret = false; debug_decl(client_close, SUDOERS_DEBUG_UTIL); if (closure->disabled) goto done; + /* Format and append an ExitMessage to the write queue. */ + if (!fmt_exit_message(closure, exit_status, error)) + goto done; + /* * Create private event base and reparent the read/write events. * We cannot use the main sudo event loop as it has already exited. @@ -1412,36 +1415,31 @@ client_close(struct client_closure *closure, int exit_status, int error) goto done; } - events = closure->read_ev->pending(closure->read_ev, SUDO_PLUGIN_EV_READ, - NULL); + /* Enable read event to receive server messages. */ closure->read_ev->setbase(closure->read_ev, evbase); - if (events == SUDO_PLUGIN_EV_READ) { - if (closure->read_ev->add(closure->read_ev, - &closure->log_details->server_timeout) == -1) { - sudo_warn(U_("unable to add event to queue")); - goto done; - } - } - - events = closure->write_ev->pending(closure->write_ev, SUDO_PLUGIN_EV_WRITE, - NULL); - closure->write_ev->setbase(closure->write_ev, evbase); - if (events == SUDO_PLUGIN_EV_WRITE) { - if (closure->write_ev->add(closure->write_ev, - &closure->log_details->server_timeout) == -1) { - sudo_warn(U_("unable to add event to queue")); - goto done; - } - } - - /* Format and append an ExitMessage to the write queue. */ - if (!fmt_exit_message(closure, exit_status, error)) + if (closure->read_ev->add(closure->read_ev, + &closure->log_details->server_timeout) == -1) { + sudo_warn(U_("unable to add event to queue")); goto done; + } + + /* Enable the write event to write the ExitMessage. */ + closure->write_ev->setbase(closure->write_ev, evbase); + if (closure->write_ev->add(closure->write_ev, + &closure->log_details->server_timeout) == -1) { + sudo_warn(U_("unable to add event to queue")); + goto done; + } /* Loop until queues are flushed and final commit point received. */ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "flushing buffers and waiting for final commit point"); - ret = sudo_ev_dispatch(evbase) == 0; + if (sudo_ev_dispatch(evbase) == -1 || sudo_ev_got_break(evbase)) { + sudo_warnx(U_("error in event loop")); + goto done; + } + + ret = true; done: sudo_ev_base_free(evbase);