From: Chris Wright Date: Sun, 8 Jan 2006 02:11:03 +0000 (-0800) Subject: Update sysctl overflow patch (2.6.14) X-Git-Tag: v2.6.14.6~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bff8842003adeeae38550223f8d32c5c1c32a684;p=thirdparty%2Fkernel%2Fstable-queue.git Update sysctl overflow patch (2.6.14) --- diff --git a/review-2.6.14/sysctl-don-t-overflow-the-user-supplied-buffer-with-0.patch b/review-2.6.14/sysctl-don-t-overflow-the-user-supplied-buffer-with-0.patch index acab18cef3d..96f08615314 100644 --- a/review-2.6.14/sysctl-don-t-overflow-the-user-supplied-buffer-with-0.patch +++ b/review-2.6.14/sysctl-don-t-overflow-the-user-supplied-buffer-with-0.patch @@ -4,38 +4,77 @@ Message-Id: <200512310559.jBV5xfr2026442@hera.kernel.org> From: Linux Kernel Mailing List 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 +From: Linus Torvalds -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 +The returned length is the full untruncated length, so that you can +tell when truncation has occurred. Signed-off-by: Linus Torvalds +[chrisw: inclusive of minimal fix so it's same as upstream] Signed-off-by: Chris Wright -Signed-off-by: Greg Kroah-Hartman --- - 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; + } + + /*