This patch will upgrade Sudo version 1.8.20 patchlevel 1 to Sudo version 1.8.20 patchlevel 2. To apply: $ cd sudo-1.8.20p1 $ patch -p1 < sudo-1.8.20p2.patch diff -urN sudo-1.8.20p1/ChangeLog sudo-1.8.20p2/ChangeLog --- sudo-1.8.20p1/ChangeLog Mon May 29 14:38:48 2017 +++ sudo-1.8.20p2/ChangeLog Wed May 31 09:17:29 2017 @@ -1,8 +1,32 @@ +2017-05-31 Todd C. Miller + + * NEWS, configure, configure.ac: + Sudo 1.8.20p2 + [47836f4c9834] + + * src/ttyname.c: + A command name may also contain newline characters so read + /proc/self/stat until EOF. It is not legal for /proc/self/stat to + contain embedded NUL bytes so treat the file as corrupt if we see + any. With help from Qualys. + + This is not exploitable due to the /dev traversal changes in sudo + 1.8.20p1 (thanks Solar!). + [15a46f4007dd] + +2017-05-30 Todd C. Miller + + * src/ttyname.c: + Use /proc/self consistently on Linux. As far as I know, only AIX + doesn't support /proc/self. + [6f3d9816541b] + + 2017-05-29 Todd C. Miller * NEWS, configure, configure.ac: Sudo 1.8.20p1 - [94d010e2bb50] [SUDO_1_8_20p1] <1.8> + [94d010e2bb50] * src/ttyname.c: Fix for CVE-2017-1000367, parsing of /proc/pid/stat on Linux when @@ -14,13 +38,13 @@ Also stop performing a breadth-first traversal of /dev when looking for the device. Only the directories specified in search_devs[] are checked. - [d5dd22356194] <1.8> + [d5dd22356194] 2017-05-11 Todd C. Miller * plugins/sudoers/Makefile.in: Fix "make check" when openssl or gcrypt is used. Bug #787 - [fd76c0bd8b80] <1.8> + [fd76c0bd8b80] 2017-05-10 Todd C. Miller diff -urN sudo-1.8.20p1/NEWS sudo-1.8.20p2/NEWS --- sudo-1.8.20p1/NEWS Mon May 29 14:36:13 2017 +++ sudo-1.8.20p2/NEWS Wed May 31 09:14:31 2017 @@ -1,3 +1,9 @@ +What's new in Sudo 1.8.20p2 + + * Fixed a bug parsing /proc/pid/stat on Linux when the process + name contains newlines. This is not exploitable due to the /dev + traversal changes in sudo 1.8.20p1. + What's new in Sudo 1.8.20p1 * Fixed "make check" when using OpenSSL or GNU crypt. diff -urN sudo-1.8.20p1/configure sudo-1.8.20p2/configure --- sudo-1.8.20p1/configure Mon May 29 14:33:06 2017 +++ sudo-1.8.20p2/configure Wed May 31 09:14:31 2017 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sudo 1.8.20p1. +# Generated by GNU Autoconf 2.69 for sudo 1.8.20p2. # # Report bugs to . # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='sudo' PACKAGE_TARNAME='sudo' -PACKAGE_VERSION='1.8.20p1' -PACKAGE_STRING='sudo 1.8.20p1' +PACKAGE_VERSION='1.8.20p2' +PACKAGE_STRING='sudo 1.8.20p2' PACKAGE_BUGREPORT='https://bugzilla.sudo.ws/' PACKAGE_URL='' @@ -1534,7 +1534,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sudo 1.8.20p1 to adapt to many kinds of systems. +\`configure' configures sudo 1.8.20p2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1599,7 +1599,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sudo 1.8.20p1:";; + short | recursive ) echo "Configuration of sudo 1.8.20p2:";; esac cat <<\_ACEOF @@ -1852,7 +1852,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sudo configure 1.8.20p1 +sudo configure 1.8.20p2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2561,7 +2561,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sudo $as_me 1.8.20p1, which was +It was created by sudo $as_me 1.8.20p2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -26943,7 +26943,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sudo $as_me 1.8.20p1, which was +This file was extended by sudo $as_me 1.8.20p2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -27009,7 +27009,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sudo config.status 1.8.20p1 +sudo config.status 1.8.20p2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN sudo-1.8.20p1/configure.ac sudo-1.8.20p2/configure.ac --- sudo-1.8.20p1/configure.ac Mon May 29 14:33:06 2017 +++ sudo-1.8.20p2/configure.ac Wed May 31 09:14:31 2017 @@ -4,7 +4,7 @@ dnl Copyright (c) 1994-1996,1998-2017 Todd C. Miller dnl AC_PREREQ([2.59]) -AC_INIT([sudo], [1.8.20p1], [https://bugzilla.sudo.ws/], [sudo]) +AC_INIT([sudo], [1.8.20p2], [https://bugzilla.sudo.ws/], [sudo]) AC_CONFIG_HEADER([config.h pathnames.h]) AC_CONFIG_SRCDIR([src/sudo.c]) dnl diff -urN sudo-1.8.20p1/src/ttyname.c sudo-1.8.20p2/src/ttyname.c --- sudo-1.8.20p1/src/ttyname.c Mon May 29 14:32:53 2017 +++ sudo-1.8.20p2/src/ttyname.c Wed May 31 09:14:31 2017 @@ -451,26 +451,38 @@ char * get_process_ttyname(char *name, size_t namelen) { - char path[PATH_MAX], *line = NULL; + const char path[] = "/proc/self/stat"; + char *cp, buf[1024]; char *ret = NULL; - size_t linesize = 0; int serrno = errno; - ssize_t len; - FILE *fp; + ssize_t nread; + int fd; debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL) - /* Try to determine the tty from tty_nr in /proc/pid/stat. */ - snprintf(path, sizeof(path), "/proc/%u/stat", (unsigned int)getpid()); - if ((fp = fopen(path, "r")) != NULL) { - len = getline(&line, &linesize, fp); - fclose(fp); - if (len != -1) { + /* + * Try to determine the tty from tty_nr in /proc/self/stat. + * Ignore /proc/self/stat if it contains embedded NUL bytes. + */ + if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) { + cp = buf; + while ((nread = read(fd, cp, buf + sizeof(buf) - cp)) != 0) { + if (nread == -1) { + if (errno == EAGAIN || errno == EINTR) + continue; + break; + } + cp += nread; + if (cp >= buf + sizeof(buf)) + break; + } + if (nread == 0 && memchr(buf, '\0', cp - buf) == NULL) { /* * Field 7 is the tty dev (0 if no tty). - * Since the process name at field 2 "(comm)" may include spaces, - * start at the last ')' found. + * Since the process name at field 2 "(comm)" may include + * whitespace (including newlines), start at the last ')' found. */ - char *cp = strrchr(line, ')'); + *cp = '\0'; + cp = strrchr(buf, ')'); if (cp != NULL) { char *ep = cp; const char *errstr; @@ -501,7 +513,8 @@ errno = ENOENT; done: - free(line); + if (fd != -1) + close(fd); if (ret == NULL) sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, "unable to resolve tty via %s", path);