Sophie

Sophie

distrib > Mageia > 7 > x86_64 > by-pkgid > a9bab87e35404ee0a7bf089686bf7c40 > files > 3

sudo-1.8.28-1.1.mga7.src.rpm

From fa8ffeb17523494f0e8bb49a25e53635f4509078 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Wed, 29 Jan 2020 20:15:21 -0700
Subject: [PATCH] Fix a buffer overflow when pwfeedback is enabled and input is
 a not a tty. In getln() if the user enters ^U (erase line) and the write(2)
 fails, the remaining buffer size is reset but the current pointer is not.
 While here, fix an incorrect break for erase when write(2) fails. Also
 disable pwfeedback when input is not a tty as it cannot work. CVE-2019-18634
 Credit: Joe Vennix from Apple Information Security.

---
 src/tgetpass.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/tgetpass.c b/src/tgetpass.c
index 8f400a34c..8b2303df0 100644
--- a/src/tgetpass.c
+++ b/src/tgetpass.c
@@ -61,7 +61,7 @@ enum tgetpass_errval {
 static volatile sig_atomic_t signo[NSIG];
 
 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
@@ -125,6 +125,7 @@ tgetpass(const char *prompt, int timeout, int flags,
     static char buf[SUDO_CONV_REPL_MAX + 1];
     int i, input, output, save_errno, ttyfd;
     bool need_restart, neednl = false;
+    bool feedback = ISSET(flags, TGP_MASK);
     enum tgetpass_errval errval;
     debug_decl(tgetpass, SUDO_DEBUG_CONV)
 
@@ -180,7 +181,7 @@ tgetpass(const char *prompt, int timeout, int flags,
      */
     if (!ISSET(flags, TGP_ECHO)) {
 	for (;;) {
-	    if (ISSET(flags, TGP_MASK))
+	    if (feedback)
 		neednl = sudo_term_cbreak(input);
 	    else
 		neednl = sudo_term_noecho(input);
@@ -194,6 +195,9 @@ tgetpass(const char *prompt, int timeout, int flags,
 	    }
 	}
     }
+    /* Only use feedback mode when we can disable echo. */
+    if (!neednl)
+	feedback = false;
 
     /*
      * Catch signals that would otherwise cause the user to end
@@ -224,7 +228,7 @@ tgetpass(const char *prompt, int timeout, int flags,
 
     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;
 
@@ -366,7 +370,7 @@ sudo_askpass(const char *askpass, const char *prompt)
 extern int sudo_term_eof, 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;
@@ -395,15 +399,15 @@ getln(int fd, char *buf, size_t bufsiz, int feedback,
 		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;