Here is an untested patch intended to fix the following behaviour:
$ cat a.c
#include <unistd.h>
int main (int argc, char **arghhh)
{
int fd[2];
pipe (fd);
write (fd[1], NULL, 1);
}
$ gcc -o a a.c
$ strace -ewrite ./a
write(4, NULL, 1) = 1
$
Tim.
*/
--- linux-2.2.18pre23/fs/pipe.c.cfu Fri Nov 24 20:55:11 2000
+++ linux-2.2.18pre23/fs/pipe.c Fri Nov 24 21:00:11 2000
@@ -31,7 +31,7 @@
size_t count, loff_t *ppos)
{
struct inode * inode = filp->f_dentry->d_inode;
- ssize_t chars = 0, size = 0, read = 0;
+ ssize_t chars = 0, size = 0, read = 0, err = 0;
char *pipebuf;
@@ -67,11 +67,14 @@
chars = size;
read += chars;
pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode);
+ if (copy_to_user(buf, pipebuf, chars )) {
+ err = -EFAULT;
+ break;
+ }
PIPE_START(*inode) += chars;
PIPE_START(*inode) &= (PIPE_BUF-1);
PIPE_LEN(*inode) -= chars;
count -= chars;
- copy_to_user(buf, pipebuf, chars );
buf += chars;
}
PIPE_LOCK(*inode)--;
@@ -80,9 +83,9 @@
UPDATE_ATIME(inode);
return read;
}
- if (PIPE_WRITERS(*inode))
+ if (!err && PIPE_WRITERS(*inode))
return -EAGAIN;
- return 0;
+ return err;
}
static ssize_t pipe_write(struct file * filp, const char * buf,
@@ -109,7 +112,7 @@
down(&inode->i_sem);
return -ERESTARTSYS;
}
- while (count>0) {
+ while (count>0 && !err) {
while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) {
if (!PIPE_READERS(*inode)) { /* no readers */
send_sig(SIGPIPE,current,0);
@@ -134,10 +137,13 @@
if (chars > free)
chars = free;
pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode);
+ if (copy_from_user(pipebuf, buf, chars )) {
+ err = -EFAULT;
+ break;
+ }
written += chars;
PIPE_LEN(*inode) += chars;
count -= chars;
- copy_from_user(pipebuf, buf, chars );
buf += chars;
}
PIPE_LOCK(*inode)--;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Thu Nov 30 2000 - 21:00:12 EST