[patch] Re: ac18: change in fs/read_write.c

From: Ivan Kokshaysky (ink@jurassic.park.msu.ru)
Date: Thu Jun 15 2000 - 16:49:43 EST


On Wed, Jun 14, 2000 at 02:50:46PM +0100, Alan Cox wrote:
> > This code
> > + if((long) tot_len <0)
> > + return -EINVAL;
> > +
> > breaks Tru64 binaries on alpha (netscape, acroread).
> > Could it be backed out?
>
> Ok I'd like to know why its breaking stuff, and who is queueing negative
> length I/O's.
>
Oops. While thinking about alpha I've missed 2 bugs in that code.
1. It won't help for iov_len arrays such as
        { 0xffffffff, 2 }, { 0x40000000, 0x40000000, 0x80000000 } etc.
2. It returns after kmalloc() without kfree(), thus allowing any user
   crash the system in a few seconds (bad news for 2.2.16).

The patch fixes that and also returns EINVAL accordingly BSD docs.
As a side effect OSF binaries are working again on alpha.
Tested on x86 and alpha.
Applies also to 2.2.16 (with offset 11 lines)

Ivan.

--- 2.4.0.t1ac19/fs/read_write.c Thu Jun 15 22:20:04 2000
+++ linux/fs/read_write.c Thu Jun 15 22:22:02 2000
@@ -199,12 +199,19 @@
         if (copy_from_user(iov, vector, count*sizeof(*vector)))
                 goto out;
 
+ /* BSD readv/writev returns EINVAL if one of the iov_len
+ values < 0 or tot_len overflowed a 32-bit integer. -ink */
         tot_len = 0;
- for (i = 0 ; i < count ; i++)
- tot_len += iov[i].iov_len;
-
- if((long) tot_len <0)
- return -EINVAL;
+ ret = -EINVAL;
+ for (i = 0 ; i < count ; i++) {
+ size_t tmp = tot_len;
+ int len = iov[i].iov_len;
+ if (len < 0)
+ goto out;
+ (u32)tot_len += len;
+ if (tot_len < tmp || tot_len < (u32)len)
+ goto out;
+ }
 
         inode = file->f_dentry->d_inode;
         /* VERIFY_WRITE actually means a read, as we write to user space */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jun 15 2000 - 21:00:36 EST