aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Quetchenbach <virtualphtn@gmail.com>2008-04-25 00:11:58 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-25 00:11:58 -0400
commit8d390efd903485923419584275fd0c2aa4c94183 (patch)
treeb7ca93c9bb5d90ed31003106b9f8a73675f3ae3a
parenta5d6ab56daa439d681aab29955498486e452224d (diff)
tcp: tcp_probe buffer overflow and incorrect return value
tcp_probe has a bounds-checking bug that causes many programs (less, python) to crash reading /proc/net/tcp_probe. When it outputs a log line to the reader, it only checks if that line alone will fit in the reader's buffer, rather than that line and all the previous lines it has already written. tcpprobe_read also returns the wrong value if copy_to_user fails--it just passes on the return value of copy_to_user (number of bytes not copied), which makes a failure look like a success. This patch fixes the buffer overflow and sets the return value to -EFAULT if copy_to_user fails. Patch is against latest net-2.6; tested briefly and seems to fix the crashes in less and python. Signed-off-by: Tom Quetchenbach <virtualphtn@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/tcp_probe.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 1c509592574a..5ff0ce6e9d39 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -190,19 +190,18 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
190 190
191 width = tcpprobe_sprint(tbuf, sizeof(tbuf)); 191 width = tcpprobe_sprint(tbuf, sizeof(tbuf));
192 192
193 if (width < len) 193 if (cnt + width < len)
194 tcp_probe.tail = (tcp_probe.tail + 1) % bufsize; 194 tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
195 195
196 spin_unlock_bh(&tcp_probe.lock); 196 spin_unlock_bh(&tcp_probe.lock);
197 197
198 /* if record greater than space available 198 /* if record greater than space available
199 return partial buffer (so far) */ 199 return partial buffer (so far) */
200 if (width >= len) 200 if (cnt + width >= len)
201 break; 201 break;
202 202
203 error = copy_to_user(buf + cnt, tbuf, width); 203 if (copy_to_user(buf + cnt, tbuf, width))
204 if (error) 204 return -EFAULT;
205 break;
206 cnt += width; 205 cnt += width;
207 } 206 }
208 207