ChangeSet 1.1553, 2005/02/07 17:20:08-02:00, [EMAIL PROTECTED]

        Linus Torvalds: backport 2.6 rw_verify_area() to check against file 
offset overflows 
        
        - Make generic rw_verify_area check against file offset overflows.
        - Add 'f_maxcount' to allow filesystems to set a per-file maximum IO 
size.
        - Rename "locks_verify_area()" to "rw_verify_area()" and clean up the 
arguments.



 arch/mips64/kernel/linux32.c      |    6 +---
 arch/parisc/kernel/sys_parisc32.c |    6 +---
 arch/ppc64/kernel/sys_ppc32.c     |    6 +---
 arch/s390x/kernel/linux32.c       |    7 +----
 arch/sparc64/kernel/sys_sparc32.c |    7 +----
 fs/file_table.c                   |    1 
 fs/read_write.c                   |   48 ++++++++++++++++++++++++++------------
 include/linux/fs.h                |   10 +------
 mm/filemap.c                      |    4 +--
 9 files changed, 48 insertions(+), 47 deletions(-)


diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c
--- a/arch/mips64/kernel/linux32.c      2005-02-07 15:02:47 -08:00
+++ b/arch/mips64/kernel/linux32.c      2005-02-07 15:02:47 -08:00
@@ -1088,11 +1088,9 @@
                i--;
        }
 
-       inode = file->f_dentry->d_inode;
        /* VERIFY_WRITE actually means a read, as we write to user space */
-       retval = locks_verify_area((type == VERIFY_WRITE
-                                   ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
-                                  inode, file, file->f_pos, tot_len);
+       retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE),
+                                  file, &file->f_pos, tot_len);
        if (retval) {
                if (iov != iovstack)
                        kfree(iov);
diff -Nru a/arch/parisc/kernel/sys_parisc32.c 
b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c 2005-02-07 15:02:47 -08:00
+++ b/arch/parisc/kernel/sys_parisc32.c 2005-02-07 15:02:47 -08:00
@@ -1671,11 +1671,9 @@
                i--;
        }
 
-       inode = file->f_dentry->d_inode;
        /* VERIFY_WRITE actually means a read, as we write to user space */
-       retval = locks_verify_area((type == VERIFY_WRITE
-                                   ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
-                                  inode, file, file->f_pos, tot_len);
+       retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE),
+                                  file, &file->f_pos, tot_len);
        if (retval) {
                if (iov != iovstack)
                        kfree(iov);
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c     2005-02-07 15:02:47 -08:00
+++ b/arch/ppc64/kernel/sys_ppc32.c     2005-02-07 15:02:47 -08:00
@@ -183,11 +183,9 @@
                i--;
        }
 
-       inode = file->f_dentry->d_inode;
        /* VERIFY_WRITE actually means a read, as we write to user space */
-       retval = locks_verify_area((type == VERIFY_WRITE
-                                   ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
-                                  inode, file, file->f_pos, tot_len);
+       retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE),
+                                  file, &file->f_pos, tot_len);
        if (retval) {
                if (iov != iovstack)
                        kfree(iov);
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c       2005-02-07 15:02:47 -08:00
+++ b/arch/s390x/kernel/linux32.c       2005-02-07 15:02:48 -08:00
@@ -1108,7 +1108,6 @@
        unsigned long tot_len;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov=iovstack, *ivp;
-       struct inode *inode;
        long retval, i;
        io_fn_t fn;
        iov_fn_t fnv;
@@ -1145,11 +1144,9 @@
                i--;
        }
 
-       inode = file->f_dentry->d_inode;
        /* VERIFY_WRITE actually means a read, as we write to user space */
-       retval = locks_verify_area((type == VERIFY_WRITE
-                                   ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
-                                  inode, file, file->f_pos, tot_len);
+       retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE),
+                                  file, &file->f_pos, tot_len);
        if (retval)
                goto out;
 
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c 
b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c 2005-02-07 15:02:47 -08:00
+++ b/arch/sparc64/kernel/sys_sparc32.c 2005-02-07 15:02:47 -08:00
@@ -1093,7 +1093,6 @@
        __kernel_ssize_t32 tot_len;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov=iovstack, *ivp;
-       struct inode *inode;
        long retval, i;
        io_fn_t fn;
        iov_fn_t fnv;
@@ -1140,11 +1139,9 @@
                i--;
        }
 
-       inode = file->f_dentry->d_inode;
        /* VERIFY_WRITE actually means a read, as we write to user space */
-       retval = locks_verify_area((type == VERIFY_WRITE
-                                   ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
-                                  inode, file, file->f_pos, tot_len);
+       retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE),
+                                  file, &file->f_pos, tot_len);
        if (retval)
                goto out;
 
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c   2005-02-07 15:02:47 -08:00
+++ b/fs/file_table.c   2005-02-07 15:02:47 -08:00
@@ -46,6 +46,7 @@
                f->f_version = ++event;
                f->f_uid = current->fsuid;
                f->f_gid = current->fsgid;
+               f->f_maxcount = INT_MAX;
                list_add(&f->f_list, &anon_list);
                file_list_unlock();
                return f;
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c   2005-02-07 15:02:47 -08:00
+++ b/fs/read_write.c   2005-02-07 15:02:47 -08:00
@@ -40,6 +40,28 @@
        return -EISDIR;
 }
 
+int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t 
count)
+{
+       struct inode *inode;
+       loff_t pos;
+
+       if (unlikely(count > file->f_maxcount))
+               return -EINVAL;
+
+       pos = *ppos;
+
+       if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
+               goto Einval;
+
+       inode = file->f_dentry->d_inode;
+       if (inode->i_flock && MANDATORY_LOCK(inode))
+               return locks_mandatory_area(read_write == READ ? 
FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, inode, file, *ppos, count);
+       return 0;
+
+Einval:
+       return -EINVAL;
+}
+
 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
 {
        long long retval;
@@ -168,8 +190,8 @@
        file = fget(fd);
        if (file) {
                if (file->f_mode & FMODE_READ) {
-                       ret = locks_verify_area(FLOCK_VERIFY_READ, 
file->f_dentry->d_inode,
-                                               file, file->f_pos, count);
+                       ret = rw_verify_area(READ, file, &file->f_pos, count);
+
                        if (!ret) {
                                ssize_t (*read)(struct file *, char *, size_t, 
loff_t *);
                                ret = -EINVAL;
@@ -193,9 +215,7 @@
        file = fget(fd);
        if (file) {
                if (file->f_mode & FMODE_WRITE) {
-                       struct inode *inode = file->f_dentry->d_inode;
-                       ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
-                               file->f_pos, count);
+                       ret = rw_verify_area(WRITE, file, &file->f_pos, count);
                        if (!ret) {
                                ssize_t (*write)(struct file *, const char *, 
size_t, loff_t *);
                                ret = -EINVAL;
@@ -224,7 +244,6 @@
        ssize_t ret, i;
        io_fn_t fn;
        iov_fn_t fnv;
-       struct inode *inode;
 
        /*
         * First get the "struct iovec" from user memory and
@@ -275,12 +294,11 @@
                        goto out;
        }
 
-       inode = file->f_dentry->d_inode;
        /* VERIFY_WRITE actually means a read, as we write to user space */
-       ret = locks_verify_area((type == VERIFY_WRITE
-                                ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
-                               inode, file, file->f_pos, tot_len);
-       if (ret) goto out;
+       ret = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE),
+                               file, &file->f_pos, tot_len);
+       if (ret) 
+               goto out;
 
        fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
        if (fnv) {
@@ -383,8 +401,8 @@
                goto bad_file;
        if (!(file->f_mode & FMODE_READ))
                goto out;
-       ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
-                               file, pos, count);
+       ret = rw_verify_area(READ, file, &pos, count);
+
        if (ret)
                goto out;
        ret = -EINVAL;
@@ -414,8 +432,8 @@
                goto bad_file;
        if (!(file->f_mode & FMODE_WRITE))
                goto out;
-       ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode,
-                               file, pos, count);
+       ret = rw_verify_area(WRITE, file, &pos, count);
+
        if (ret)
                goto out;
        ret = -EINVAL;
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h        2005-02-07 15:02:47 -08:00
+++ b/include/linux/fs.h        2005-02-07 15:02:47 -08:00
@@ -576,6 +576,7 @@
        unsigned int            f_uid, f_gid;
        int                     f_error;
 
+       size_t                  f_maxcount;
        unsigned long           f_version;
 
        /* needed for tty driver, and maybe others */
@@ -1056,14 +1057,7 @@
        return 0;
 }
 
-static inline int locks_verify_area(int read_write, struct inode *inode,
-                                   struct file *filp, loff_t offset,
-                                   size_t count)
-{
-       if (inode->i_flock && MANDATORY_LOCK(inode))
-               return locks_mandatory_area(read_write, inode, filp, offset, 
count);
-       return 0;
-}
+extern int rw_verify_area(int, struct file *, loff_t *, size_t);
 
 static inline int locks_verify_truncate(struct inode *inode,
                                    struct file *filp,
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c      2005-02-07 15:02:47 -08:00
+++ b/mm/filemap.c      2005-02-07 15:02:47 -08:00
@@ -1870,7 +1870,7 @@
                goto fput_in;
        if (!in_inode->i_mapping->a_ops->readpage)
                goto fput_in;
-       retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, 
in_file->f_pos, count);
+       retval = rw_verify_area(READ, in_file, &in_file->f_pos, count);
        if (retval)
                goto fput_in;
 
@@ -1887,7 +1887,7 @@
        if (!out_file->f_op || !out_file->f_op->write)
                goto fput_out;
        out_inode = out_file->f_dentry->d_inode;
-       retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, 
out_file->f_pos, count);
+       retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
        if (retval)
                goto fput_out;
 
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-24" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to