From 65ebe04508a08ccd44a178a5d02f1146766bb603 Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Feb 01 2017 10:46:51 +0000 Subject: Fix for CVE-2017-5495.patch Resolves: #1416017 --- diff --git a/0005-lib-limit-size-of-vty-buffer-to-4096-bytes.patch b/0005-lib-limit-size-of-vty-buffer-to-4096-bytes.patch new file mode 100644 index 0000000..547a08c --- /dev/null +++ b/0005-lib-limit-size-of-vty-buffer-to-4096-bytes.patch @@ -0,0 +1,175 @@ +From edb8d6dc015b7316bdb1a70507d78fdeeecb17b3 Mon Sep 17 00:00:00 2001 +From: Quentin Young +Date: Tue, 10 Jan 2017 23:33:50 +0000 +Subject: [PATCH] lib: limit size of vty buffer to 4096 bytes + +This removes the automatic resizing of the vty input buffer and places a +hard size cap of 4096 bytes. It also fixes a potentially unsafe strcpy. + +[Edits by Paul Jakma, paul@jakma.org] + +(cherry-picked from commit b7ceefea77a246fe5c1dcd1b91bf6079d1b97c02) +--- + lib/command.c | 2 +- + lib/vty.c | 58 ++++++++++++++++++++++++++++++++-------------------------- + lib/vty.h | 1 - + vtysh/vtysh.c | 2 +- + 4 files changed, 34 insertions(+), 29 deletions(-) + +diff --git a/lib/command.c b/lib/command.c +index 8317789..cf616d4 100644 +--- a/lib/command.c ++++ b/lib/command.c +@@ -2769,7 +2769,7 @@ config_from_file (struct vty *vty, FILE *fp, unsigned int *line_num) + *line_num = 0; + vector vline; + +- while (fgets (vty->buf, VTY_BUFSIZ, fp)) ++ while (fgets (vty->buf, vty->max, fp)) + { + ++(*line_num); + vline = cmd_make_strvec (vty->buf); +diff --git a/lib/vty.c b/lib/vty.c +index 750f885..cda72a0 100644 +--- a/lib/vty.c ++++ b/lib/vty.c +@@ -39,6 +39,8 @@ + + #include + ++#define VTY_BUFSIZ 4096 ++ + /* Vty events */ + enum event + { +@@ -470,17 +472,6 @@ vty_write (struct vty *vty, const char *buf, size_t nbytes) + buffer_put (vty->obuf, buf, nbytes); + } + +-/* Ensure length of input buffer. Is buffer is short, double it. */ +-static void +-vty_ensure (struct vty *vty, int length) +-{ +- if (vty->max <= length) +- { +- vty->max *= 2; +- vty->buf = XREALLOC (MTYPE_VTY, vty->buf, vty->max); +- } +-} +- + /* Basic function to insert character into vty. */ + static void + vty_self_insert (struct vty *vty, char c) +@@ -488,7 +479,9 @@ vty_self_insert (struct vty *vty, char c) + int i; + int length; + +- vty_ensure (vty, vty->length + 1); ++ if (vty->length + 1 > VTY_BUFSIZ) ++ return; ++ + length = vty->length - vty->cp; + memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length); + vty->buf[vty->cp] = c; +@@ -505,26 +498,29 @@ vty_self_insert (struct vty *vty, char c) + static void + vty_self_insert_overwrite (struct vty *vty, char c) + { +- vty_ensure (vty, vty->length + 1); +- vty->buf[vty->cp++] = c; +- +- if (vty->cp > vty->length) +- vty->length++; +- +- if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE)) +- return; ++ if (vty->cp == vty->length) ++ { ++ vty_self_insert (vty, c); ++ return; ++ } + ++ vty->buf[vty->cp++] = c; + vty_write (vty, &c, 1); + } + +-/* Insert a word into vty interface with overwrite mode. */ ++/** ++ * Insert a string into vty->buf at the current cursor position. ++ * ++ * If the resultant string would be larger than VTY_BUFSIZ it is ++ * truncated to fit. ++ */ + static void + vty_insert_word_overwrite (struct vty *vty, char *str) + { +- int len = strlen (str); +- vty_write (vty, str, len); +- strcpy (&vty->buf[vty->cp], str); +- vty->cp += len; ++ size_t nwrite = MIN ((int) strlen (str), VTY_BUFSIZ - vty->cp); ++ vty_write (vty, str, nwrite); ++ strncpy (&vty->buf[vty->cp], str, nwrite); ++ vty->cp += nwrite; + vty->length = vty->cp; + } + +@@ -2091,12 +2087,21 @@ vtysh_read (struct thread *thread) + printf ("line: %.*s\n", nbytes, buf); + #endif /* VTYSH_DEBUG */ + ++ if (vty->length + nbytes > VTY_BUFSIZ) ++ { ++ /* Clear command line buffer. */ ++ vty->cp = vty->length = 0; ++ vty_clear_buf (vty); ++ vty_out (vty, "%% Command is too long.%s", VTY_NEWLINE); ++ goto out; ++ } ++ + for (p = buf; p < buf+nbytes; p++) + { +- vty_ensure(vty, vty->length+1); + vty->buf[vty->length++] = *p; + if (*p == '\0') + { ++ + /* Pass this line to parser. */ + ret = vty_execute (vty); + /* Note that vty_execute clears the command buffer and resets +@@ -2117,6 +2122,7 @@ vtysh_read (struct thread *thread) + } + } + ++out: + vty_event (VTYSH_READ, sock, vty); + + return 0; +diff --git a/lib/vty.h b/lib/vty.h +index f31f4b5..86eef17 100644 +--- a/lib/vty.h ++++ b/lib/vty.h +@@ -25,7 +25,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + #include "log.h" + #include "sockunion.h" + +-#define VTY_BUFSIZ 512 + #define VTY_MAXHIST 20 + + /* VTY struct. */ +diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c +index 984f8d3..a673eaa 100644 +--- a/vtysh/vtysh.c ++++ b/vtysh/vtysh.c +@@ -460,7 +460,7 @@ vtysh_config_from_file (struct vty *vty, FILE *fp) + vector vline; + struct cmd_element *cmd; + +- while (fgets (vty->buf, VTY_BUFSIZ, fp)) ++ while (fgets (vty->buf, vty->max, fp)) + { + if (vty->buf[0] == '!' || vty->buf[1] == '#') + continue; +-- +2.9.3 + diff --git a/quagga.spec b/quagga.spec index 8817dba..e6935f3 100644 --- a/quagga.spec +++ b/quagga.spec @@ -7,7 +7,7 @@ Name: quagga Version: 0.99.24.1 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Routing daemon License: GPLv2+ Group: System Environment/Daemons @@ -32,6 +32,7 @@ Patch0: 0001-systemd-various-service-file-improvements.patch Patch1: 0002-bgpd-Fix-VU-270232-VPNv4-NLRI-parser-memcpys-to-stac.patch Patch2: 0003-bgpd-Fix-buffer-overflow-error-in-bgp_dump_routes_fu.patch Patch3: 0004-zebra-stack-overrun-in-IPv6-RA-receive-code-CVE-2016.patch +Patch4: 0005-lib-limit-size-of-vty-buffer-to-4096-bytes.patch %define __perl_requires %{SOURCE1} @@ -228,6 +229,9 @@ fi %{_includedir}/quagga/ospfd/*.h %changelog +* Wed Feb 01 2017 Michal Sekletar - 0.99.24.1-5 +- fix for CVE-2017-5495 (#1416017) + * Fri Oct 21 2016 Michal Sekletar - 0.99.24.1-4 - make routing daemons pull network.target into the boot transaction (#1387654) - fix for CVE-2016-2342 (#1316572)