2000-11-24 21:34:33

by Tim Waugh

[permalink] [raw]
Subject: [patch] 2.2.18pre23: user access checking in pipe_read/pipe_write

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)--;