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