Bug#547902: dash only reads the first character from pipe (bash reads whole line)
tags 547902 + patch
quit
Hi, please see http://bugs.debian.org/547902
Here's a patch from Christian Hohnstaedt <chohnstaedt@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++;
Reply to: