65ebe04
From edb8d6dc015b7316bdb1a70507d78fdeeecb17b3 Mon Sep 17 00:00:00 2001
65ebe04
From: Quentin Young <qlyoung@cumulusnetworks.com>
65ebe04
Date: Tue, 10 Jan 2017 23:33:50 +0000
65ebe04
Subject: [PATCH] lib: limit size of vty buffer to 4096 bytes
65ebe04
65ebe04
This removes the automatic resizing of the vty input buffer and places a
65ebe04
hard size cap of 4096 bytes. It also fixes a potentially unsafe strcpy.
65ebe04
65ebe04
[Edits by Paul Jakma, paul@jakma.org]
65ebe04
65ebe04
(cherry-picked from commit b7ceefea77a246fe5c1dcd1b91bf6079d1b97c02)
65ebe04
---
65ebe04
 lib/command.c |  2 +-
65ebe04
 lib/vty.c     | 58 ++++++++++++++++++++++++++++++++--------------------------
65ebe04
 lib/vty.h     |  1 -
65ebe04
 vtysh/vtysh.c |  2 +-
65ebe04
 4 files changed, 34 insertions(+), 29 deletions(-)
65ebe04
65ebe04
diff --git a/lib/command.c b/lib/command.c
65ebe04
index 8317789..cf616d4 100644
65ebe04
--- a/lib/command.c
65ebe04
+++ b/lib/command.c
65ebe04
@@ -2769,7 +2769,7 @@ config_from_file (struct vty *vty, FILE *fp, unsigned int *line_num)
65ebe04
   *line_num = 0;
65ebe04
   vector vline;
65ebe04
 
65ebe04
-  while (fgets (vty->buf, VTY_BUFSIZ, fp))
65ebe04
+  while (fgets (vty->buf, vty->max, fp))
65ebe04
     {
65ebe04
       ++(*line_num);
65ebe04
       vline = cmd_make_strvec (vty->buf);
65ebe04
diff --git a/lib/vty.c b/lib/vty.c
65ebe04
index 750f885..cda72a0 100644
65ebe04
--- a/lib/vty.c
65ebe04
+++ b/lib/vty.c
65ebe04
@@ -39,6 +39,8 @@
65ebe04
 
65ebe04
 #include <arpa/telnet.h>
65ebe04
 
65ebe04
+#define VTY_BUFSIZ 4096
65ebe04
+
65ebe04
 /* Vty events */
65ebe04
 enum event 
65ebe04
 {
65ebe04
@@ -470,17 +472,6 @@ vty_write (struct vty *vty, const char *buf, size_t nbytes)
65ebe04
   buffer_put (vty->obuf, buf, nbytes);
65ebe04
 }
65ebe04
 
65ebe04
-/* Ensure length of input buffer.  Is buffer is short, double it. */
65ebe04
-static void
65ebe04
-vty_ensure (struct vty *vty, int length)
65ebe04
-{
65ebe04
-  if (vty->max <= length)
65ebe04
-    {
65ebe04
-      vty->max *= 2;
65ebe04
-      vty->buf = XREALLOC (MTYPE_VTY, vty->buf, vty->max);
65ebe04
-    }
65ebe04
-}
65ebe04
-
65ebe04
 /* Basic function to insert character into vty. */
65ebe04
 static void
65ebe04
 vty_self_insert (struct vty *vty, char c)
65ebe04
@@ -488,7 +479,9 @@ vty_self_insert (struct vty *vty, char c)
65ebe04
   int i;
65ebe04
   int length;
65ebe04
 
65ebe04
-  vty_ensure (vty, vty->length + 1);
65ebe04
+  if (vty->length + 1 > VTY_BUFSIZ)
65ebe04
+    return;
65ebe04
+
65ebe04
   length = vty->length - vty->cp;
65ebe04
   memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
65ebe04
   vty->buf[vty->cp] = c;
65ebe04
@@ -505,26 +498,29 @@ vty_self_insert (struct vty *vty, char c)
65ebe04
 static void
65ebe04
 vty_self_insert_overwrite (struct vty *vty, char c)
65ebe04
 {
65ebe04
-  vty_ensure (vty, vty->length + 1);
65ebe04
-  vty->buf[vty->cp++] = c;
65ebe04
-
65ebe04
-  if (vty->cp > vty->length)
65ebe04
-    vty->length++;
65ebe04
-
65ebe04
-  if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
65ebe04
-    return;
65ebe04
+  if (vty->cp == vty->length)
65ebe04
+    {
65ebe04
+      vty_self_insert (vty, c);
65ebe04
+      return;
65ebe04
+    }
65ebe04
 
65ebe04
+  vty->buf[vty->cp++] = c;
65ebe04
   vty_write (vty, &c, 1);
65ebe04
 }
65ebe04
 
65ebe04
-/* Insert a word into vty interface with overwrite mode. */
65ebe04
+/**
65ebe04
+ * Insert a string into vty->buf at the current cursor position.
65ebe04
+ *
65ebe04
+ * If the resultant string would be larger than VTY_BUFSIZ it is
65ebe04
+ * truncated to fit.
65ebe04
+ */
65ebe04
 static void
65ebe04
 vty_insert_word_overwrite (struct vty *vty, char *str)
65ebe04
 {
65ebe04
-  int len = strlen (str);
65ebe04
-  vty_write (vty, str, len);
65ebe04
-  strcpy (&vty->buf[vty->cp], str);
65ebe04
-  vty->cp += len;
65ebe04
+  size_t nwrite = MIN ((int) strlen (str), VTY_BUFSIZ - vty->cp);
65ebe04
+  vty_write (vty, str, nwrite);
65ebe04
+  strncpy (&vty->buf[vty->cp], str, nwrite);
65ebe04
+  vty->cp += nwrite;
65ebe04
   vty->length = vty->cp;
65ebe04
 }
65ebe04
 
65ebe04
@@ -2091,12 +2087,21 @@ vtysh_read (struct thread *thread)
65ebe04
   printf ("line: %.*s\n", nbytes, buf);
65ebe04
 #endif /* VTYSH_DEBUG */
65ebe04
 
65ebe04
+  if (vty->length + nbytes > VTY_BUFSIZ)
65ebe04
+    {
65ebe04
+      /* Clear command line buffer. */
65ebe04
+      vty->cp = vty->length = 0;
65ebe04
+      vty_clear_buf (vty);
65ebe04
+      vty_out (vty, "%% Command is too long.%s", VTY_NEWLINE);
65ebe04
+      goto out;
65ebe04
+    }
65ebe04
+  
65ebe04
   for (p = buf; p < buf+nbytes; p++)
65ebe04
     {
65ebe04
-      vty_ensure(vty, vty->length+1);
65ebe04
       vty->buf[vty->length++] = *p;
65ebe04
       if (*p == '\0')
65ebe04
 	{
65ebe04
+	  
65ebe04
 	  /* Pass this line to parser. */
65ebe04
 	  ret = vty_execute (vty);
65ebe04
 	  /* Note that vty_execute clears the command buffer and resets
65ebe04
@@ -2117,6 +2122,7 @@ vtysh_read (struct thread *thread)
65ebe04
 	}
65ebe04
     }
65ebe04
 
65ebe04
+out:
65ebe04
   vty_event (VTYSH_READ, sock, vty);
65ebe04
 
65ebe04
   return 0;
65ebe04
diff --git a/lib/vty.h b/lib/vty.h
65ebe04
index f31f4b5..86eef17 100644
65ebe04
--- a/lib/vty.h
65ebe04
+++ b/lib/vty.h
65ebe04
@@ -25,7 +25,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
65ebe04
 #include "log.h"
65ebe04
 #include "sockunion.h"
65ebe04
 
65ebe04
-#define VTY_BUFSIZ 512
65ebe04
 #define VTY_MAXHIST 20
65ebe04
 
65ebe04
 /* VTY struct. */
65ebe04
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
65ebe04
index 984f8d3..a673eaa 100644
65ebe04
--- a/vtysh/vtysh.c
65ebe04
+++ b/vtysh/vtysh.c
65ebe04
@@ -460,7 +460,7 @@ vtysh_config_from_file (struct vty *vty, FILE *fp)
65ebe04
   vector vline;
65ebe04
   struct cmd_element *cmd;
65ebe04
 
65ebe04
-  while (fgets (vty->buf, VTY_BUFSIZ, fp))
65ebe04
+  while (fgets (vty->buf, vty->max, fp))
65ebe04
     {
65ebe04
       if (vty->buf[0] == '!' || vty->buf[1] == '#')
65ebe04
 	continue;
65ebe04
-- 
65ebe04
2.9.3
65ebe04