Blame SOURCES/sudo-1.8.19p2-CVE-2017-1000368.patch

f48767
diff --git a/src/ttyname.c b/src/ttyname.c
0e1944
index ff2cacc..013be95 100644
f48767
--- a/src/ttyname.c
f48767
+++ b/src/ttyname.c
0e1944
@@ -477,26 +477,38 @@ done:
f48767
 char *
0e1944
 get_process_ttyname(char *name, size_t namelen)
f48767
 {
0e1944
-    char path[PATH_MAX], *line = NULL;
f48767
+    const char path[] = "/proc/self/stat";
f48767
+    char *cp, buf[1024];
0e1944
     char *ret = NULL;
0e1944
-    size_t linesize = 0;
0e1944
     int serrno = errno;
0e1944
-    ssize_t len;
0e1944
-    FILE *fp;
f48767
+    ssize_t nread;
f48767
+    int fd;
f48767
     debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
f48767
 
f48767
-    /* Try to determine the tty from tty_nr in /proc/pid/stat. */
0e1944
-    snprintf(path, sizeof(path), "/proc/%u/stat", (unsigned int)getpid());
0e1944
-    if ((fp = fopen(path, "r")) != NULL) {
f48767
-	len = getline(&line, &linesize, fp);
f48767
-	fclose(fp);
f48767
-	if (len != -1) {
f48767
+    /*
f48767
+     * Try to determine the tty from tty_nr in /proc/self/stat.
f48767
+     * Ignore /proc/self/stat if it contains embedded NUL bytes.
f48767
+     */
f48767
+    if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) {
f48767
+	cp = buf;
f48767
+	while ((nread = read(fd, cp, buf + sizeof(buf) - cp)) != 0) {
f48767
+	    if (nread == -1) {
f48767
+		if (errno == EAGAIN || errno == EINTR)
f48767
+		    continue;
f48767
+		break;
f48767
+	    }
f48767
+	    cp += nread;
f48767
+	    if (cp >= buf + sizeof(buf))
f48767
+		break;
f48767
+	}
f48767
+	if (nread == 0 && memchr(buf, '\0', cp - buf) == NULL) {
f48767
 	    /*
f48767
 	     * Field 7 is the tty dev (0 if no tty).
f48767
-	     * Since the process name at field 2 "(comm)" may include spaces,
f48767
-	     * start at the last ')' found.
f48767
+	     * Since the process name at field 2 "(comm)" may include
f48767
+	     * whitespace (including newlines), start at the last ')' found.
f48767
 	     */
f48767
-	    char *cp = strrchr(line, ')');
f48767
+	    *cp = '\0';
f48767
+	    cp = strrchr(buf, ')');
0e1944
 	    if (cp != NULL) {
0e1944
 		char *ep = cp;
0e1944
 		const char *errstr;
0e1944
@@ -527,7 +539,8 @@ get_process_ttyname(char *name, size_t namelen)
0e1944
     errno = ENOENT;
f48767
 
0e1944
 done:
0e1944
-    free(line);
f48767
+    if (fd != -1)
f48767
+	close(fd);
0e1944
     if (ret == NULL)
0e1944
 	sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
0e1944
 	    "unable to resolve tty via %s", path);