From: Todd C. Miller Date: Fri, 29 Aug 2014 15:47:08 +0000 (-0600) Subject: Don't allow sudo_ev_loopcont() to override sudo_ev_loopexit() X-Git-Tag: SUDO_1_8_11^2~38 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2b849b26879f37f93f0d08e2e0a626ed9f2836c7;p=sudo Don't allow sudo_ev_loopcont() to override sudo_ev_loopexit() --- diff --git a/include/sudo_event.h b/include/sudo_event.h index 8dad43ba1..a05016f0d 100644 --- a/include/sudo_event.h +++ b/include/sudo_event.h @@ -35,9 +35,10 @@ #define SUDO_EVLOOP_NONBLOCK 0x02 /* Do not block in event loop */ /* Event base flags (internal) */ -#define SUDO_EVBASE_LOOPEXIT 0x01 -#define SUDO_EVBASE_LOOPBREAK 0x02 -#define SUDO_EVBASE_LOOPCONT 0x04 +#define SUDO_EVBASE_LOOPONCE SUDO_EVLOOP_ONCE +#define SUDO_EVBASE_LOOPEXIT 0x02 +#define SUDO_EVBASE_LOOPBREAK 0x04 +#define SUDO_EVBASE_LOOPCONT 0x08 #define SUDO_EVBASE_GOT_EXIT 0x10 #define SUDO_EVBASE_GOT_BREAK 0x20 #define SUDO_EVBASE_GOT_MASK 0xf0 diff --git a/lib/util/event.c b/lib/util/event.c index 232216182..7a17b5289 100644 --- a/lib/util/event.c +++ b/lib/util/event.c @@ -282,10 +282,10 @@ sudo_ev_loop_v1(struct sudo_event_base *base, int flags) * If sudo_ev_loopexit() was called when events were not running * the next invocation of sudo_ev_loop() only runs once. * All other base flags are ignored unless we are running events. + * Note that SUDO_EVLOOP_ONCE and SUDO_EVBASE_LOOPONCE are equivalent. */ - if (ISSET(base->flags, SUDO_EVBASE_LOOPEXIT)) - SET(flags, SUDO_EVLOOP_ONCE); - base->flags = 0; + base->flags |= (flags & SUDO_EVLOOP_ONCE); + base->flags &= (SUDO_EVBASE_LOOPEXIT|SUDO_EVBASE_LOOPONCE); for (;;) { rescan: @@ -352,19 +352,14 @@ rescan: if (ISSET(base->flags, SUDO_EVBASE_LOOPCONT)) { /* Rescan events and start polling again. */ CLR(base->flags, SUDO_EVBASE_LOOPCONT); - if (!ISSET(flags, SUDO_EVLOOP_ONCE)) { - sudo_ev_deactivate_all(base); - goto rescan; - } + sudo_ev_deactivate_all(base); + goto rescan; } } - if (ISSET(base->flags, SUDO_EVBASE_LOOPEXIT)) { - /* exit loop after once through */ - SET(base->flags, SUDO_EVBASE_GOT_EXIT); - sudo_ev_deactivate_all(base); - break; - } - if (ISSET(flags, SUDO_EVLOOP_ONCE)) { + if (ISSET(base->flags, SUDO_EVBASE_LOOPONCE)) { + /* SUDO_EVBASE_LOOPEXIT is always set w/ SUDO_EVBASE_LOOPONCE */ + if (ISSET(base->flags, SUDO_EVBASE_LOOPEXIT)) + SET(base->flags, SUDO_EVBASE_GOT_EXIT); sudo_ev_deactivate_all(base); break; } @@ -378,7 +373,12 @@ void sudo_ev_loopexit_v1(struct sudo_event_base *base) { debug_decl(sudo_ev_loopexit, SUDO_DEBUG_EVENT) - SET(base->flags, SUDO_EVBASE_LOOPEXIT); + /* SUDO_EVBASE_LOOPBREAK trumps SUDO_EVBASE_LOOPEXIT */ + if (!ISSET(base->flags, SUDO_EVBASE_LOOPBREAK)) { + /* SUDO_EVBASE_LOOPEXIT trumps SUDO_EVBASE_LOOPCONT */ + CLR(base->flags, SUDO_EVBASE_LOOPCONT); + SET(base->flags, (SUDO_EVBASE_LOOPEXIT|SUDO_EVBASE_LOOPONCE)); + } debug_return; } @@ -386,6 +386,8 @@ void sudo_ev_loopbreak_v1(struct sudo_event_base *base) { debug_decl(sudo_ev_loopbreak, SUDO_DEBUG_EVENT) + /* SUDO_EVBASE_LOOPBREAK trumps SUDO_EVBASE_LOOP{CONT,EXIT,ONCE}. */ + CLR(base->flags, (SUDO_EVBASE_LOOPCONT|SUDO_EVBASE_LOOPEXIT|SUDO_EVBASE_LOOPONCE)); SET(base->flags, SUDO_EVBASE_LOOPBREAK); debug_return; } @@ -394,7 +396,10 @@ void sudo_ev_loopcontinue_v1(struct sudo_event_base *base) { debug_decl(sudo_ev_loopcontinue, SUDO_DEBUG_EVENT) - SET(base->flags, SUDO_EVBASE_LOOPCONT); + /* SUDO_EVBASE_LOOP{BREAK,EXIT} trumps SUDO_EVBASE_LOOPCONT */ + if (!ISSET(base->flags, SUDO_EVBASE_LOOPONCE|SUDO_EVBASE_LOOPBREAK)) { + SET(base->flags, SUDO_EVBASE_LOOPCONT); + } debug_return; } diff --git a/src/exec_pty.c b/src/exec_pty.c index 21f2935ef..b4b21963d 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -1138,9 +1138,9 @@ handle_sigchld(int backchannel, struct command_status *cstat) sudo_debug_printf(SUDO_DEBUG_INFO, "command exited: %d", WEXITSTATUS(status)); } + if (!WIFSTOPPED(status)) + alive = false; } - if (!WIFSTOPPED(status)) - alive = false; } debug_return_bool(alive); }