# HG changeset patch # User Brian Utterback # Date 1487126322 28800 # Node ID 8e6af99ed7da303547d32ac6c516c31bfbffd852 # Parent 036be1e2dc005073b7e5759d0b2717f9479b04c3 25459915 problem in SERVICE/QUAGGA diff -r 036be1e2dc00 -r 8e6af99ed7da components/quagga/patches/37-cve-2017-5495.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/quagga/patches/37-cve-2017-5495.patch Tue Feb 14 18:38:42 2017 -0800 @@ -0,0 +1,397 @@ +This patch fixes CVE-2017-5495, which is in all versions of Quagga +prior to 1.1.0. After upgrading to a version later than that, this patch +may be removed. +See: +http://git.savannah.gnu.org/gitweb/?p=quagga.git;a=commit;h=b7ceefea77a246fe5c1dcd1b91bf6079d1b97c02 +http://git.savannah.gnu.org/gitweb/?p=quagga.git;a=commit;h=7d66284a5817a1613b1e4d64a0775ec04fdf8c01 + +*** lib/command.c +--- lib/command.c +*************** config_from_file (struct vty *vty, FILE +*** 2306,2312 **** + int ret; + vector vline; + +! while (fgets (vty->buf, VTY_BUFSIZ, fp)) + { + vline = cmd_make_strvec (vty->buf); + +--- 2306,2312 ---- + int ret; + vector vline; + +! while (fgets (vty->buf, vty->max, fp)) + { + vline = cmd_make_strvec (vty->buf); + +*** lib/vty.c +--- lib/vty.c +*************** +*** 39,44 **** +--- 39,46 ---- + + #include + ++ #define VTY_BUFSIZ 4096 ++ + /* Vty events */ + enum event + { +*************** static u_char restricted_mode = 0; +*** 90,95 **** +--- 92,113 ---- + char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; + + ++ static void ++ vty_buf_assert (struct vty *vty) ++ { ++ assert (vty->cp <= vty->length); ++ assert (vty->length < vty->max); ++ assert (vty->buf[vty->length] == '\0'); ++ } ++ ++ /* Sanity/safety wrappers around access to vty->buf */ ++ static void vty_buf_put (struct vty *vty, char c) ++ { ++ vty_buf_assert (vty); ++ vty->buf[vty->cp] = c; ++ vty->buf[vty->max - 1] = '\0'; ++ } ++ + /* VTY standard output function. */ + int + vty_out (struct vty *vty, const char *format, ...) +*************** vty_write (struct vty *vty, const char * +*** 470,553 **** + 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) + { + int i; + int length; + +- vty_ensure (vty, vty->length + 1); + length = vty->length - vty->cp; + memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length); +! vty->buf[vty->cp] = c; + + vty_write (vty, &vty->buf[vty->cp], length + 1); + for (i = 0; i < length; i++) + vty_write (vty, &telnet_backward_char, 1); + + vty->cp++; +! vty->length++; + } + + /* Self insert character 'c' in overwrite mode. */ + 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; + + vty_write (vty, &c, 1); + } + +! /* Insert a word into vty interface with overwrite mode. */ + 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; + vty->length = vty->cp; + } + + /* Forward character. */ + static void + vty_forward_char (struct vty *vty) + { + if (vty->cp < vty->length) + { + vty_write (vty, &vty->buf[vty->cp], 1); + vty->cp++; + } + } + + /* Backward character. */ + static void + vty_backward_char (struct vty *vty) + { + if (vty->cp > 0) + { + vty->cp--; + vty_write (vty, &telnet_backward_char, 1); + } + } + + /* Move to the beginning of the line. */ +--- 488,591 ---- + buffer_put (vty->obuf, buf, nbytes); + } + + /* Basic function to insert character into vty. */ + static void + vty_self_insert (struct vty *vty, char c) + { + int i; + int length; ++ ++ vty_buf_assert (vty); ++ ++ /* length is sans nul, max is with */ ++ if (vty->length + 1 >= vty->max) ++ return; + + length = vty->length - vty->cp; + memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length); +! vty->length++; +! vty->buf[vty->length] = '\0'; +! +! vty_buf_put (vty, c); + + vty_write (vty, &vty->buf[vty->cp], length + 1); + for (i = 0; i < length; i++) + vty_write (vty, &telnet_backward_char, 1); + + vty->cp++; +! +! vty_buf_assert (vty); + } + + /* Self insert character 'c' in overwrite mode. */ + static void + vty_self_insert_overwrite (struct vty *vty, char c) + { +! vty_buf_assert (vty); +! +! if (vty->cp == vty->length) +! { +! vty_self_insert (vty, c); +! return; +! } + ++ vty_buf_put (vty, c); ++ vty->cp++; ++ ++ vty_buf_assert (vty); ++ + vty_write (vty, &c, 1); + } + +! /** +! * 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) + { +! vty_buf_assert (vty); +! +! size_t nwrite = MIN ((int) strlen (str), vty->max - vty->cp - 1); +! memcpy (&vty->buf[vty->cp], str, nwrite); +! vty->cp += nwrite; + vty->length = vty->cp; ++ vty->buf[vty->length] = '\0'; ++ vty_buf_assert (vty); ++ ++ vty_write (vty, str, nwrite); + } + + /* Forward character. */ + static void + vty_forward_char (struct vty *vty) + { ++ vty_buf_assert (vty); ++ + if (vty->cp < vty->length) + { + vty_write (vty, &vty->buf[vty->cp], 1); + vty->cp++; + } ++ ++ vty_buf_assert (vty); + } + + /* Backward character. */ + static void + vty_backward_char (struct vty *vty) + { ++ vty_buf_assert (vty); ++ + if (vty->cp > 0) + { + vty->cp--; + vty_write (vty, &telnet_backward_char, 1); + } ++ ++ vty_buf_assert (vty); + } + + /* Move to the beginning of the line. */ +*************** vty_history_print (struct vty *vty) +*** 582,588 **** + length = strlen (vty->hist[vty->hp]); + memcpy (vty->buf, vty->hist[vty->hp], length); + vty->cp = vty->length = length; +! + /* Redraw current line */ + vty_redraw_line (vty); + } +--- 620,628 ---- + length = strlen (vty->hist[vty->hp]); + memcpy (vty->buf, vty->hist[vty->hp], length); + vty->cp = vty->length = length; +! vty->buf[vty->length] = '\0'; +! vty_buf_assert (vty); +! + /* Redraw current line */ + vty_redraw_line (vty); + } +*************** vty_redraw_line (struct vty *vty) +*** 638,643 **** +--- 678,685 ---- + { + vty_write (vty, vty->buf, vty->length); + vty->cp = vty->length; ++ ++ vty_buf_assert (vty); + } + + /* Forward word. */ +*************** vty_delete_char (struct vty *vty) +*** 737,746 **** + vty_down_level (vty); + return; + } +! + if (vty->cp == vty->length) + return; /* completion need here? */ + + size = vty->length - vty->cp; + + vty->length--; +--- 779,790 ---- + vty_down_level (vty); + return; + } +! + if (vty->cp == vty->length) + return; /* completion need here? */ + ++ vty_buf_assert (vty); ++ + size = vty->length - vty->cp; + + vty->length--; +*************** vty_kill_line (struct vty *vty) +*** 787,792 **** +--- 831,837 ---- + + memset (&vty->buf[vty->cp], 0, size); + vty->length = vty->cp; ++ vty_buf_assert (vty); + } + + /* Kill line from the beginning. */ +*************** vtysh_read (struct thread *thread) +*** 2087,2098 **** + printf ("line: %.*s\n", nbytes, buf); + #endif /* VTYSH_DEBUG */ + + 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 +--- 2132,2152 ---- + printf ("line: %.*s\n", nbytes, buf); + #endif /* VTYSH_DEBUG */ + ++ if (vty->length + nbytes >= vty->max) ++ { ++ /* 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->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 +*************** vtysh_read (struct thread *thread) +*** 2113,2118 **** +--- 2167,2173 ---- + } + } + ++ out: + vty_event (VTYSH_READ, sock, vty); + + return 0; +*** lib/vty.h +--- lib/vty.h +*************** Software Foundation, Inc., 59 Temple Pla +*** 24,30 **** + #include "thread.h" + #include "log.h" + +- #define VTY_BUFSIZ 512 + #define VTY_MAXHIST 20 + + /* VTY struct. */ +--- 24,29 ---- +*** vtysh/vtysh.c +--- vtysh/vtysh.c +*************** vtysh_config_from_file (struct vty *vty, +*** 459,465 **** + vector vline; + struct cmd_element *cmd; + +! while (fgets (vty->buf, VTY_BUFSIZ, fp)) + { + if (vty->buf[0] == '!' || vty->buf[1] == '#') + continue; +--- 459,465 ---- + vector vline; + struct cmd_element *cmd; + +! while (fgets (vty->buf, vty->max, fp)) + { + if (vty->buf[0] == '!' || vty->buf[1] == '#') + continue;