tags 547902 + patch
quit

Hi, please see http://bugs.debian.org/547902

Here's a patch from Christian Hohnstaedt <chohnsta...@innominate.com>

Thanks, Gerrit.

---
Testparameter:
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; do dd 
if=/proc/sys/net/ipv4/tcp_wmem bs=$i 2>/dev/null; done

for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; do dd 
if=/proc/sys/net/ipv4/tcp_wmem skip=$i bs=1 2>/dev/null |wc -c ; done

diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 9270125..038df14 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2117,17 +2117,16 @@ static int __do_proc_dointvec(void *tbl_data, struct 
ctl_table *table,
 #define TMPBUFLEN 21
        int *i, vleft, first=1, neg, val;
        unsigned long lval;
-       size_t left, len;
+       size_t left, len, off;
        
        char buf[TMPBUFLEN], *p;
        char __user *s = buffer;
        
-       if (!tbl_data || !table->maxlen || !*lenp ||
-           (*ppos && !write)) {
+       if (!tbl_data || !table->maxlen || !*lenp) {
                *lenp = 0;
                return 0;
        }
-       
+       off = 0;
        i = (int *) tbl_data;
        vleft = table->maxlen / sizeof(*i);
        left = *lenp;
@@ -2176,25 +2175,31 @@ static int __do_proc_dointvec(void *tbl_data, struct 
ctl_table *table,
                        if (conv(&neg, &lval, i, 1, data))
                                break;
                } else {
+                       loff_t diff;
                        p = buf;
-                       if (!first)
-                               *p++ = '\t';
-       
                        if (conv(&neg, &lval, i, 0, data))
                                break;
 
-                       sprintf(p, "%s%lu", neg ? "-" : "", lval);
-                       len = strlen(buf);
-                       if (len > left)
-                               len = left;
-                       if(copy_to_user(s, buf, len))
-                               return -EFAULT;
-                       left -= len;
-                       s += len;
+                       len = sprintf(p, "%s%s%lu", first ? "" : "\t",
+                                               neg ? "-" : "", lval);
+                       diff = *ppos - off;
+                       off += len;
+                       if (diff > 0 && diff < len) {
+                               p += diff;
+                               len -= diff;
+                       }
+                       if (off > *ppos) {
+                               if (len > left)
+                                       len = left;
+                               if(copy_to_user(s, p, len))
+                                       return -EFAULT;
+                               left -= len;
+                               s += len;
+                       }
                }
        }
 
-       if (!write && !first && left) {
+       if (!write && !first && left && off >= *ppos) {
                if(put_user('\n', s))
                        return -EFAULT;
                left--, s++;



-- 
To UNSUBSCRIBE, email to debian-kernel-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to