diff -up ./src/tgetpass.c.CVE-2019-18634 ./src/tgetpass.c --- ./src/tgetpass.c.CVE-2019-18634 2020-02-05 17:16:07.601420697 +0100 +++ ./src/tgetpass.c 2020-02-05 17:22:34.206301510 +0100 @@ -55,7 +55,7 @@ static volatile sig_atomic_t signo[NSIG] static bool tty_present(void); static void tgetpass_handler(int); -static char *getln(int, char *, size_t, int, enum tgetpass_errval *); +static char *getln(int, char *, size_t, bool, enum tgetpass_errval *); static char *sudo_askpass(const char *, const char *); static int @@ -118,6 +118,7 @@ tgetpass(const char *prompt, int timeout static const char *askpass; static char buf[SUDO_CONV_REPL_MAX + 1]; int i, input, output, save_errno, neednl = 0, need_restart; + bool feedback = ISSET(flags, TGP_MASK); enum tgetpass_errval errval; debug_decl(tgetpass, SUDO_DEBUG_CONV) @@ -165,7 +166,7 @@ restart: */ if (!ISSET(flags, TGP_ECHO)) { for (;;) { - if (ISSET(flags, TGP_MASK)) + if (feedback) neednl = sudo_term_cbreak(input); else neednl = sudo_term_noecho(input); @@ -179,6 +180,9 @@ restart: } } } + /* Only use feedback mode when we can disable echo. */ + if (!neednl) + feedback = false; /* * Catch signals that would otherwise cause the user to end @@ -204,7 +208,7 @@ restart: if (timeout > 0) alarm(timeout); - pass = getln(input, buf, sizeof(buf), ISSET(flags, TGP_MASK), &errval); + pass = getln(input, buf, sizeof(buf), feedback, &errval); alarm(0); save_errno = errno; @@ -340,7 +344,7 @@ sudo_askpass(const char *askpass, const extern int sudo_term_erase, sudo_term_kill; static char * -getln(int fd, char *buf, size_t bufsiz, int feedback, +getln(int fd, char *buf, size_t bufsiz, bool feedback, enum tgetpass_errval *errval) { size_t left = bufsiz; @@ -366,15 +370,15 @@ getln(int fd, char *buf, size_t bufsiz, while (cp > buf) { if (write(fd, "\b \b", 3) == -1) break; - --cp; + cp--; } + cp = buf; left = bufsiz; continue; } else if (c == sudo_term_erase) { if (cp > buf) { - if (write(fd, "\b \b", 3) == -1) - break; - --cp; + ignore_result(write(fd, "\b \b", 3)); + cp--; left++; } continue;