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 [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to