]> granicus.if.org Git - sudo/commitdiff
Don't allow sudo_ev_loopcont() to override sudo_ev_loopexit()
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 29 Aug 2014 15:47:08 +0000 (09:47 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 29 Aug 2014 15:47:08 +0000 (09:47 -0600)
include/sudo_event.h
lib/util/event.c
src/exec_pty.c

index 8dad43ba1f9d9085a57dbb6ed41464caab684c40..a05016f0d1353c015da50398654623dea72a2c5c 100644 (file)
 #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
index 232216182f13970b0aa164ee470e6fe7a0c47ba9..7a17b52894f9372702e8eded778a6f6648a252d5 100644 (file)
@@ -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;
 }
 
index 21f2935efd0838dcac1d841454fa3f206deb2562..b4b21963d07fe188677e8d2a0d8a7ef7bad89fb4 100644 (file)
@@ -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);
 }