summaryrefslogtreecommitdiff
path: root/debian/patches
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2017-06-21 14:19:45 +0300
committerIgor Pashev <pashev.igor@gmail.com>2017-06-21 14:19:45 +0300
commit546742e5e8544fb42aa65744d719100b5e32dee4 (patch)
tree2d3ccd186b8ccb02cd134af845cc41aa04e1ff00 /debian/patches
downloadsudo-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.patch246
-rw-r--r--debian/patches/CVE-2017-1000368.diff78
-rw-r--r--debian/patches/paths-in-samples.diff42
-rw-r--r--debian/patches/series5
-rw-r--r--debian/patches/skip-noedit.diff12
-rw-r--r--debian/patches/typo-in-classic-insults.diff11
-rw-r--r--debian/patches/use-flock-on-hurd.diff15
-rw-r--r--debian/patches/use-proc-self-consistently-on-linux.diff33
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);
+