diff -Nru sudo-1.8.9p5/debian/changelog sudo-1.8.9p5/debian/changelog --- sudo-1.8.9p5/debian/changelog 2016-10-10 08:11:34.000000000 +0000 +++ sudo-1.8.9p5/debian/changelog 2017-05-29 09:57:53.000000000 +0000 @@ -1,3 +1,12 @@ +sudo (1.8.9p5-1ubuntu1.4) trusty-security; urgency=medium + + * SECURITY UPDATE: /proc/self/stat parsing confusion + - debian/patches/CVE-2017-1000367.patch: adjust parsing to + find ttyname + - CVE-2017-1000367 + + -- Steve Beattie Mon, 29 May 2017 01:05:33 -0700 + sudo (1.8.9p5-1ubuntu1.3) trusty-proposed; urgency=medium * debian/sudoers: diff -Nru sudo-1.8.9p5/debian/patches/CVE-2017-1000367.patch sudo-1.8.9p5/debian/patches/CVE-2017-1000367.patch --- sudo-1.8.9p5/debian/patches/CVE-2017-1000367.patch 1970-01-01 00:00:00.000000000 +0000 +++ sudo-1.8.9p5/debian/patches/CVE-2017-1000367.patch 2017-05-29 08:44:50.000000000 +0000 @@ -0,0 +1,251 @@ +From: "Todd C. Miller" +Subject: fix /proc/self/stat parsing, reduce /dev walking looking for tty + +CVE-2017-1000367 + +--- + src/ttyname.c | 130 +++++++++++++++++++++++++++++----------------------------- + 1 file changed, 65 insertions(+), 65 deletions(-) + +Index: b/src/ttyname.c +=================================================================== +--- a/src/ttyname.c ++++ b/src/ttyname.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2014 Todd C. Miller ++ * Copyright (c) 2012-2017 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -162,20 +162,22 @@ sudo_ttyname_dev(dev_t tdev) + } + #elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__) + /* +- * Devices to search before doing a breadth-first scan. ++ * Device nodes and directories to search before searching all of /dev + */ + static char *search_devs[] = { + "/dev/console", +- "/dev/wscons", +- "/dev/pts/", +- "/dev/vt/", +- "/dev/term/", +- "/dev/zcons/", ++ "/dev/pts/", /* POSIX pty */ ++ "/dev/vt/", /* Solaris virtual console */ ++ "/dev/term/", /* Solaris serial ports */ ++ "/dev/zcons/", /* Solaris zone console */ ++ "/dev/pty/", /* HP-UX old-style pty */ + NULL + }; + ++/* ++ * Device nodes to ignore when searching all of /dev ++ */ + static char *ignore_devs[] = { +- "/dev/fd/", + "/dev/stdin", + "/dev/stdout", + "/dev/stderr", +@@ -183,14 +185,15 @@ static char *ignore_devs[] = { + }; + + /* +- * Do a breadth-first scan of dir looking for the specified device. ++ * Do a scan of a directory looking for the specified device. ++ * Does not descend into subdirectories. + */ + static char * +-sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin) ++sudo_ttyname_scan(const char *dir, dev_t rdev) + { + DIR *d = NULL; +- char pathbuf[PATH_MAX], **subdirs = NULL, *devname = NULL; +- size_t sdlen, d_len, len, num_subdirs = 0, max_subdirs = 0; ++ size_t sdlen, d_len, len; ++ char pathbuf[PATH_MAX], *devname = NULL;; + struct dirent *dp; + struct stat sb; + unsigned int i; +@@ -199,6 +202,18 @@ sudo_ttyname_scan(const char *dir, dev_t + if (dir[0] == '\0' || (d = opendir(dir)) == NULL) + goto done; + ++ if (fstat(dirfd(d), &sb) == -1) { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, ++ "unable to fstat %s", dir); ++ goto done; ++ } ++ if ((sb.st_mode & S_IWOTH) != 0) { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, ++ "ignoring world-writable directory %s", dir); ++ errno = ENOENT; ++ goto done; ++ } ++ + sudo_debug_printf(SUDO_DEBUG_INFO, "scanning for dev %u in %s", + (unsigned int)rdev, dir); + +@@ -234,18 +249,6 @@ sudo_ttyname_scan(const char *dir, dev_t + } + if (ignore_devs[i] != NULL) + continue; +- if (!builtin) { +- /* Skip entries in search_devs; we already checked them. */ +- for (i = 0; search_devs[i] != NULL; i++) { +- len = strlen(search_devs[i]); +- if (search_devs[i][len - 1] == '/') +- len--; +- if (d_len == len && strncmp(pathbuf, search_devs[i], len) == 0) +- break; +- } +- if (search_devs[i] != NULL) +- continue; +- } + # if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(DTTOIF) + /* + * Convert dp->d_type to sb.st_mode to avoid a stat(2) if possible. +@@ -253,22 +256,11 @@ sudo_ttyname_scan(const char *dir, dev_t + * char devs (since we need st_rdev to compare the device number). + */ + if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK && dp->d_type != DT_CHR) +- sb.st_mode = DTTOIF(dp->d_type); ++ continue; + else + # endif + if (stat(pathbuf, &sb) == -1) + continue; +- if (S_ISDIR(sb.st_mode)) { +- if (!builtin) { +- /* Add to list of subdirs to search. */ +- if (num_subdirs + 1 > max_subdirs) { +- max_subdirs += 64; +- subdirs = erealloc3(subdirs, max_subdirs, sizeof(char *)); +- } +- subdirs[num_subdirs++] = estrdup(pathbuf); +- } +- continue; +- } + if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) { + devname = estrdup(pathbuf); + sudo_debug_printf(SUDO_DEBUG_INFO, "resolved dev %u as %s", +@@ -277,16 +269,9 @@ sudo_ttyname_scan(const char *dir, dev_t + } + } + +- /* Search subdirs if we didn't find it in the root level. */ +- for (i = 0; devname == NULL && i < num_subdirs; i++) +- devname = sudo_ttyname_scan(subdirs[i], rdev, false); +- + done: + if (d != NULL) + closedir(d); +- for (i = 0; i < num_subdirs; i++) +- efree(subdirs[i]); +- efree(subdirs); + debug_return_str(devname); + } + +@@ -304,7 +289,7 @@ sudo_ttyname_dev(dev_t rdev) + debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL) + + /* +- * First check search_devs for common tty devices. ++ * First check search_devs[] for common tty devices. + */ + for (sd = search_devs; tty == NULL && (devname = *sd) != NULL; sd++) { + len = strlen(devname); +@@ -321,7 +306,7 @@ sudo_ttyname_dev(dev_t rdev) + (unsigned int)rdev, buf, tty ? "yes" : "no"); + } else { + /* Traverse directory */ +- tty = sudo_ttyname_scan(devname, rdev, true); ++ tty = sudo_ttyname_scan(devname, rdev); + } + } else { + if (stat(devname, &sb) == 0) { +@@ -332,10 +317,10 @@ sudo_ttyname_dev(dev_t rdev) + } + + /* +- * Not found? Do a breadth-first traversal of /dev/. ++ * Not found? Check all device nodes in /dev. + */ + if (tty == NULL) +- tty = sudo_ttyname_scan(_PATH_DEV, rdev, false); ++ tty = sudo_ttyname_scan(_PATH_DEV, rdev); + + debug_return_str(tty); + } +@@ -429,6 +414,7 @@ get_process_ttyname(void) + { + char path[PATH_MAX], *line = NULL, *tty = NULL; + size_t linesize = 0; ++ int serrno = errno; + ssize_t len; + FILE *fp; + debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL) +@@ -439,30 +425,44 @@ get_process_ttyname(void) + len = getline(&line, &linesize, fp); + fclose(fp); + if (len != -1) { +- /* Field 7 is the tty dev (0 if no tty) */ +- char *cp = line; +- char *ep = line; +- const char *errstr; +- int field = 0; +- while (*++ep != '\0') { +- if (*ep == ' ') { +- *ep = '\0'; +- if (++field == 7) { +- dev_t tdev = strtonum(cp, INT_MIN, INT_MAX, &errstr); +- if (errstr) { +- sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, +- "%s: tty device %s: %s", path, cp, errstr); ++ /* 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. ++ */ ++ char *cp = strrchr(line, ')'); ++ if (cp != NULL) { ++ char *ep = cp; ++ const char *errstr; ++ int field = 1; ++ while (*++ep != '\0') { ++ if (*ep == ' ') { ++ *ep = '\0'; ++ if (++field == 7) { ++ dev_t tdev = strtonum(cp, INT_MIN, INT_MAX, &errstr); ++ if (errstr) { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, ++ "%s: tty device %s: %s", path, cp, errstr); ++ } ++ if (tdev > 0) { ++ errno = serrno; ++ tty = sudo_ttyname_dev(tdev); ++ goto done; ++ } ++ break; + } +- if (tdev > 0) +- tty = sudo_ttyname_dev(tdev); +- break; ++ cp = ep + 1; + } +- cp = ep + 1; + } + } + } +- efree(line); + } ++ errno = ENOENT; ++ ++done: ++ efree(line); ++ if (tty == NULL) ++ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, ++ "unable to resolve tty via %s", path); + + debug_return_str(tty); + } diff -Nru sudo-1.8.9p5/debian/patches/series sudo-1.8.9p5/debian/patches/series --- sudo-1.8.9p5/debian/patches/series 2015-08-26 23:56:55.000000000 +0000 +++ sudo-1.8.9p5/debian/patches/series 2017-05-23 01:17:27.000000000 +0000 @@ -5,3 +5,4 @@ add_probe_interfaces_setting.diff CVE-2014-9680.patch bug-1319403.patch +CVE-2017-1000367.patch