diff -urNp 2.4.19rc1/fs/read_write.c diff/fs/read_write.c --- 2.4.19rc1/fs/read_write.c Tue Jun 25 23:56:12 2002 +++ diff/fs/read_write.c Fri Jun 28 18:25:16 2002 @@ -2,21 +2,6 @@ * linux/fs/read_write.c * * Copyright (C) 1991, 1992 Linus Torvalds - * Minor pieces Copyright (C) 2002 Red Hat Inc, All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include @@ -218,7 +203,7 @@ static ssize_t do_readv_writev(int type, typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); - ssize_t tot_len; + size_t tot_len; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack; ssize_t ret, i; @@ -248,23 +233,17 @@ static ssize_t do_readv_writev(int type, if (copy_from_user(iov, vector, count*sizeof(*vector))) goto out; - /* - * Single unix specification: - * We should -EINVAL if an element length is not >= 0 and fitting an ssize_t - * The total length is fitting an ssize_t - * - * Be careful here because iov_len is a size_t not an ssize_t - */ - + /* 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; ret = -EINVAL; for (i = 0 ; i < count ; i++) { - ssize_t tmp = tot_len; - ssize_t len = (ssize_t) iov[i].iov_len; - if (len < 0) /* size_t not fitting an ssize_t .. */ + size_t tmp = tot_len; + int len = iov[i].iov_len; + if (len < 0) goto out; - tot_len += len; - if (tot_len < tmp) /* maths overflow on the ssize_t */ + (u32)tot_len += len; + if (tot_len < tmp || tot_len < (u32)len) goto out; }