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