]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Update sysctl overflow patch (2.6.14)
authorChris Wright <chrisw@sous-sol.org>
Sun, 8 Jan 2006 02:11:03 +0000 (18:11 -0800)
committerChris Wright <chrisw@sous-sol.org>
Sun, 8 Jan 2006 02:11:03 +0000 (18:11 -0800)
review-2.6.14/sysctl-don-t-overflow-the-user-supplied-buffer-with-0.patch

index acab18cef3d90ebb2b82a2bf231f0b681de9b639..96f086153146002e317c56f57dcb8b7806f2741b 100644 (file)
@@ -4,38 +4,77 @@ Message-Id: <200512310559.jBV5xfr2026442@hera.kernel.org>
 From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
 To: git-commits-head@vger.kernel.org
 Cc: 
-Subject: sysctl: don't overflow the user-supplied buffer with '0'
+Subject: sysctl: make sure to terminate strings with a NUL
 
-From: Linus Torvalds <torvalds@g5.osdl.org>
+From: Linus Torvalds <torvalds@osdl.org>
 
-If the string was too long to fit in the user-supplied buffer,
-the sysctl layer would zero-terminate it by writing past the
-end of the buffer. Don't do that.
+This is a slightly more complete fix for the previous minimal sysctl
+string fix.  It always terminates the returned string with a NUL, even
+if the full result wouldn't fit in the user-supplied buffer.
 
-Noticed by Yi Yang <yang.y.yi@gmail.com>
+The returned length is the full untruncated length, so that you can
+tell when truncation has occurred.
 
 Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+[chrisw: inclusive of minimal fix so it's same as upstream]
 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
 ---
- kernel/sysctl.c |    4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
+ kernel/sysctl.c |   29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
 
 --- linux-2.6.14.5.orig/kernel/sysctl.c
 +++ linux-2.6.14.5/kernel/sysctl.c
-@@ -2200,14 +2200,12 @@ int sysctl_string(ctl_table *table, int 
-               if (get_user(len, oldlenp))
+@@ -2191,29 +2191,32 @@ int sysctl_string(ctl_table *table, int 
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen, void **context)
+ {
+-      size_t l, len;
+-      
+       if (!table->data || !table->maxlen) 
+               return -ENOTDIR;
+       
+       if (oldval && oldlenp) {
+-              if (get_user(len, oldlenp))
++              size_t bufsize;
++              if (get_user(bufsize, oldlenp))
                        return -EFAULT;
-               if (len) {
+-              if (len) {
 -                      l = strlen(table->data);
-+                      l = strlen(table->data)+1;
-                       if (len > l) len = l;
-                       if (len >= table->maxlen)
+-                      if (len > l) len = l;
+-                      if (len >= table->maxlen)
++              if (bufsize) {
++                      size_t len = strlen(table->data), copied;
++
++                      /* This shouldn't trigger for a well-formed sysctl */
++                      if (len > table->maxlen)
                                len = table->maxlen;
-                       if(copy_to_user(oldval, table->data, len))
-                               return -EFAULT;
--                      if(put_user(0, ((char __user *) oldval) + len))
+-                      if(copy_to_user(oldval, table->data, len))
 -                              return -EFAULT;
-                       if(put_user(len, oldlenp))
+-                      if(put_user(0, ((char __user *) oldval) + len))
++
++                      /* Copy up to a max of bufsize-1 bytes of the string */
++                      copied = (len >= bufsize) ? bufsize - 1 : len;
++
++                      if (copy_to_user(oldval, table->data, copied) ||
++                          put_user(0, (char __user *)(oldval + copied)))
+                               return -EFAULT;
+-                      if(put_user(len, oldlenp))
++                      if (put_user(len, oldlenp))
                                return -EFAULT;
                }
+       }
+       if (newval && newlen) {
+-              len = newlen;
++              size_t len = newlen;
+               if (len > table->maxlen)
+                       len = table->maxlen;
+               if(copy_from_user(table->data, newval, len))
+@@ -2222,7 +2225,7 @@ int sysctl_string(ctl_table *table, int 
+                       len--;
+               ((char *) table->data)[len] = 0;
+       }
+-      return 0;
++      return 1;
+ }
+ /*