diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2017-06-21 14:19:45 +0300 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2017-06-21 14:19:45 +0300 |
commit | 546742e5e8544fb42aa65744d719100b5e32dee4 (patch) | |
tree | 2d3ccd186b8ccb02cd134af845cc41aa04e1ff00 /debian/patches | |
download | sudo-debian/1.8.19p1-2.1.tar.gz |
Imported sudo 1.8.19p1-2.1debian/1.8.19p1-2.1debian
Diffstat (limited to 'debian/patches')
-rw-r--r-- | debian/patches/CVE-2017-1000367.patch | 246 | ||||
-rw-r--r-- | debian/patches/CVE-2017-1000368.diff | 78 | ||||
-rw-r--r-- | debian/patches/paths-in-samples.diff | 42 | ||||
-rw-r--r-- | debian/patches/series | 5 | ||||
-rw-r--r-- | debian/patches/skip-noedit.diff | 12 | ||||
-rw-r--r-- | debian/patches/typo-in-classic-insults.diff | 11 | ||||
-rw-r--r-- | debian/patches/use-flock-on-hurd.diff | 15 | ||||
-rw-r--r-- | debian/patches/use-proc-self-consistently-on-linux.diff | 33 |
8 files changed, 442 insertions, 0 deletions
diff --git a/debian/patches/CVE-2017-1000367.patch b/debian/patches/CVE-2017-1000367.patch new file mode 100644 index 0000000..8d26c7c --- /dev/null +++ b/debian/patches/CVE-2017-1000367.patch @@ -0,0 +1,246 @@ +diff --git a/src/ttyname.c b/src/ttyname.c +index 9b94ba8..ab0f2d3 100644 +--- a/src/ttyname.c ++++ b/src/ttyname.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2016 Todd C. Miller <Todd.Miller@courtesan.com> ++ * Copyright (c) 2012-2017 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -145,20 +145,22 @@ sudo_ttyname_dev(dev_t tdev, char *name, size_t namelen) + } + #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", +@@ -166,16 +168,18 @@ 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. + * Returns name on success and NULL on failure, setting errno. + */ + static char * +-sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t namelen) ++sudo_ttyname_scan(const char *dir, dev_t rdev, char *name, size_t namelen) + { +- size_t sdlen, num_subdirs = 0, max_subdirs = 0; +- char pathbuf[PATH_MAX], **subdirs = NULL; ++ size_t sdlen; ++ char pathbuf[PATH_MAX]; + char *ret = NULL; + struct dirent *dp; ++ struct stat sb; + unsigned int i; + DIR *d = NULL; + debug_decl(sudo_ttyname_scan, SUDO_DEBUG_UTIL) +@@ -183,6 +187,18 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_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|SUDO_DEBUG_LINENO, + "scanning for dev %u in %s", (unsigned int)rdev, dir); + +@@ -220,18 +236,6 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_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) + /* + * Avoid excessive stat() calls by checking dp->d_type. +@@ -244,39 +248,14 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t + if (stat(pathbuf, &sb) == -1) + continue; + break; +- case DT_DIR: +- /* Directory, no need to stat() it. */ +- sb.st_mode = DTTOIF(dp->d_type); +- sb.st_rdev = 0; /* quiet ccc-analyzer false positive */ +- break; + default: +- /* Not a character device, link or directory, skip it. */ ++ /* Not a character device or link, skip it. */ + continue; + } + # else + if (stat(pathbuf, &sb) == -1) + continue; + # endif +- if (S_ISDIR(sb.st_mode)) { +- if (!builtin) { +- /* Add to list of subdirs to search. */ +- if (num_subdirs + 1 > max_subdirs) { +- char **new_subdirs; +- +- new_subdirs = reallocarray(subdirs, max_subdirs + 64, +- sizeof(char *)); +- if (new_subdirs == NULL) +- goto done; +- subdirs = new_subdirs; +- max_subdirs += 64; +- } +- subdirs[num_subdirs] = strdup(pathbuf); +- if (subdirs[num_subdirs] == NULL) +- goto done; +- num_subdirs++; +- } +- continue; +- } + if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) { + sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, + "resolved dev %u as %s", (unsigned int)rdev, pathbuf); +@@ -292,16 +271,9 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t + } + } + +- /* Search subdirs if we didn't find it in the root level. */ +- for (i = 0; ret == NULL && i < num_subdirs; i++) +- ret = sudo_ttyname_scan(subdirs[i], rdev, false, name, namelen); +- + done: + if (d != NULL) + closedir(d); +- for (i = 0; i < num_subdirs; i++) +- free(subdirs[i]); +- free(subdirs); + debug_return_str(ret); + } + +@@ -320,7 +292,7 @@ sudo_ttyname_dev(dev_t rdev, char *name, size_t namelen) + 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; (devname = *sd) != NULL; sd++) { + len = strlen(devname); +@@ -345,7 +317,7 @@ sudo_ttyname_dev(dev_t rdev, char *name, size_t namelen) + "comparing dev %u to %s: no", (unsigned int)rdev, buf); + } else { + /* Traverse directory */ +- ret = sudo_ttyname_scan(devname, rdev, true, name, namelen); ++ ret = sudo_ttyname_scan(devname, rdev, name, namelen); + if (ret != NULL || errno == ENOMEM) + goto done; + } +@@ -363,9 +335,9 @@ sudo_ttyname_dev(dev_t rdev, char *name, size_t namelen) + } + + /* +- * Not found? Do a breadth-first traversal of /dev/. ++ * Not found? Check all device nodes in /dev. + */ +- ret = sudo_ttyname_scan(_PATH_DEV, rdev, false, name, namelen); ++ ret = sudo_ttyname_scan(_PATH_DEV, rdev, name, namelen); + + done: + debug_return_str(ret); +@@ -489,28 +461,35 @@ get_process_ttyname(char *name, size_t namelen) + 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); +- } +- if (tdev > 0) { +- errno = serrno; +- ret = sudo_ttyname_dev(tdev, name, namelen); +- goto done; ++ /* ++ * 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; ++ ret = sudo_ttyname_dev(tdev, name, namelen); ++ goto done; ++ } ++ break; + } +- break; ++ cp = ep + 1; + } +- cp = ep + 1; + } + } + } diff --git a/debian/patches/CVE-2017-1000368.diff b/debian/patches/CVE-2017-1000368.diff new file mode 100644 index 0000000..593dea3 --- /dev/null +++ b/debian/patches/CVE-2017-1000368.diff @@ -0,0 +1,78 @@ + +# HG changeset patch +# User Todd C. Miller <Todd.Miller@courtesan.com> +# Date 1496243671 21600 +# Node ID 15a46f4007dde8e819dd2c70e670a529bbb9d312 +# Parent 6f3d9816541ba84055ae5aec6ff9d9523c2a96f3 +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!). + +diff -r 6f3d9816541b -r 15a46f4007dd src/ttyname.c +--- a/src/ttyname.c Tue May 30 10:44:11 2017 -0600 ++++ b/src/ttyname.c Wed May 31 09:14:31 2017 -0600 +@@ -452,25 +452,37 @@ + get_process_ttyname(char *name, size_t namelen) + { + const char path[] = "/proc/self/stat"; +- char *line = NULL; ++ 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/self/stat. */ +- 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); + diff --git a/debian/patches/paths-in-samples.diff b/debian/patches/paths-in-samples.diff new file mode 100644 index 0000000..42788a8 --- /dev/null +++ b/debian/patches/paths-in-samples.diff @@ -0,0 +1,42 @@ +diff --git a/examples/sudoers b/examples/sudoers +index 9946008..cd4c796 100644 +--- a/examples/sudoers ++++ b/examples/sudoers +@@ -44,10 +44,10 @@ Host_Alias CDROM = orion, perseus, hercules + # Cmnd alias specification + ## + Cmnd_Alias DUMPS = /usr/sbin/dump, /usr/sbin/rdump, /usr/sbin/restore, \ +- /usr/sbin/rrestore, /usr/bin/mt, \ ++ /usr/sbin/rrestore, /bin/mt, \ + sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \ + /home/operator/bin/start_backups +-Cmnd_Alias KILL = /usr/bin/kill ++Cmnd_Alias KILL = /bin/kill + Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm + Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown + Cmnd_Alias HALT = /usr/sbin/halt +@@ -85,7 +85,7 @@ operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\ + sudoedit /etc/printcap, /usr/oper/bin/ + + # joe may su only to operator +-joe ALL = /usr/bin/su operator ++joe ALL = /bin/su operator + + # pete may change passwords for anyone but root on the hp snakes + pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root +@@ -99,13 +99,13 @@ jim +biglab = ALL + + # users in the secretaries netgroup need to help manage the printers + # as well as add and remove users +-+secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser +++secretaries ALL = PRINTING, /usr/sbin/adduser + + # fred can run commands as oracle or sybase without a password + fred ALL = (DB) NOPASSWD: ALL + + # on the alphas, john may su to anyone but root and flags are not allowed +-john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* ++john ALPHA = /bin/su [!-]*, !/bin/su *root* + + # jen can run anything on all machines except the ones + # in the "SERVERS" Host_Alias diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..3fd503a --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,5 @@ +typo-in-classic-insults.diff +paths-in-samples.diff +CVE-2017-1000367.patch +use-proc-self-consistently-on-linux.diff +CVE-2017-1000368.diff diff --git a/debian/patches/skip-noedit.diff b/debian/patches/skip-noedit.diff new file mode 100644 index 0000000..569bc13 --- /dev/null +++ b/debian/patches/skip-noedit.diff @@ -0,0 +1,12 @@ +Skip installing/unlinking files without doedit set +--- a/plugins/sudoers/visudo.c ++++ b/plugins/sudoers/visudo.c +@@ -247,6 +247,8 @@ + + /* Install the sudoers temp files. */ + tq_foreach_fwd(&sudoerslist, sp) { ++ if (!sp->doedit) ++ continue; + if (!sp->modified) + (void) unlink(sp->tpath); + else diff --git a/debian/patches/typo-in-classic-insults.diff b/debian/patches/typo-in-classic-insults.diff new file mode 100644 index 0000000..57e78c6 --- /dev/null +++ b/debian/patches/typo-in-classic-insults.diff @@ -0,0 +1,11 @@ +--- a/plugins/sudoers/ins_classic.h ++++ b/plugins/sudoers/ins_classic.h +@@ -30,7 +30,7 @@ + "Where did you learn to type?", + "Are you on drugs?", + "My pet ferret can type better than you!", +- "You type like i drive.", ++ "You type like I drive.", + "Do you think like you type?", + "Your mind just hasn't been the same since the electro-shock, has it?", + diff --git a/debian/patches/use-flock-on-hurd.diff b/debian/patches/use-flock-on-hurd.diff new file mode 100644 index 0000000..fb0b81c --- /dev/null +++ b/debian/patches/use-flock-on-hurd.diff @@ -0,0 +1,15 @@ +Use flock instead of lockf for visudo on hurd +Index: sudo-1.8.3p1/configure.in +=================================================================== +--- sudo-1.8.3p1.orig/configure.in 2011-10-25 14:11:40.000000000 +0000 ++++ sudo-1.8.3p1/configure.in 2012-01-08 04:05:23.000000000 +0000 +@@ -1864,6 +1864,9 @@ + ;; + *-gnu*) + OSDEFS="${OSDEFS} -D_GNU_SOURCE" ++ # lockf() isn't implemented on the Hurd -- use flock instead ++ ac_cv_func_lockf=no ++ ac_cv_func_flock=yes + ;; + esac + diff --git a/debian/patches/use-proc-self-consistently-on-linux.diff b/debian/patches/use-proc-self-consistently-on-linux.diff new file mode 100644 index 0000000..944830f --- /dev/null +++ b/debian/patches/use-proc-self-consistently-on-linux.diff @@ -0,0 +1,33 @@ + +# HG changeset patch +# User Todd C. Miller <Todd.Miller@courtesan.com> +# Date 1496162651 21600 +# Node ID 6f3d9816541ba84055ae5aec6ff9d9523c2a96f3 +# Parent 98ef2ef47aba10f6b83904dca4d446c4b8f24987 +Use /proc/self consistently on Linux. As far as I know, only AIX +doesn't support /proc/self. + +diff -r 98ef2ef47aba -r 6f3d9816541b src/ttyname.c +--- a/src/ttyname.c Mon May 29 14:36:35 2017 -0600 ++++ b/src/ttyname.c Tue May 30 10:44:11 2017 -0600 +@@ -451,7 +451,8 @@ + char * + get_process_ttyname(char *name, size_t namelen) + { +- char path[PATH_MAX], *line = NULL; ++ const char path[] = "/proc/self/stat"; ++ char *line = NULL; + char *ret = NULL; + size_t linesize = 0; + int serrno = errno; +@@ -459,8 +460,7 @@ + FILE *fp; + 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()); ++ /* Try to determine the tty from tty_nr in /proc/self/stat. */ + if ((fp = fopen(path, "r")) != NULL) { + len = getline(&line, &linesize, fp); + fclose(fp); + |