bonding: process the err returned by dev_set_allmulti properly in bond_enslave
[pandora-kernel.git] / fs / compat.c
index 58b1da4..4a03adb 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/dirent.h>
 #include <linux/fsnotify.h>
 #include <linux/highuid.h>
-#include <linux/nfsd/syscall.h>
 #include <linux/personality.h>
 #include <linux/rwsem.h>
 #include <linux/tsacct_kern.h>
@@ -247,11 +246,8 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
            __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
            __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
            __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
-           __put_user(0, &ubuf->f_spare[0]) || 
-           __put_user(0, &ubuf->f_spare[1]) || 
-           __put_user(0, &ubuf->f_spare[2]) || 
-           __put_user(0, &ubuf->f_spare[3]) || 
-           __put_user(0, &ubuf->f_spare[4]))
+           __put_user(kbuf->f_flags, &ubuf->f_flags) ||
+           __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
                return -EFAULT;
        return 0;
 }
@@ -550,7 +546,7 @@ out:
 ssize_t compat_rw_copy_check_uvector(int type,
                const struct compat_iovec __user *uvector, unsigned long nr_segs,
                unsigned long fast_segs, struct iovec *fast_pointer,
-               struct iovec **ret_pointer)
+               struct iovec **ret_pointer, int check_access)
 {
        compat_ssize_t tot_len;
        struct iovec *iov = *ret_pointer = fast_pointer;
@@ -576,6 +572,10 @@ ssize_t compat_rw_copy_check_uvector(int type,
        }
        *ret_pointer = iov;
 
+       ret = -EFAULT;
+       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+               goto out;
+
        /*
         * Single unix specification:
         * We should -EINVAL if an element length is not >= 0 and fitting an
@@ -597,7 +597,8 @@ ssize_t compat_rw_copy_check_uvector(int type,
                }
                if (len < 0)    /* size_t not fitting in compat_ssize_t .. */
                        goto out;
-               if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
+               if (check_access &&
+                   !access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
                        ret = -EFAULT;
                        goto out;
                }
@@ -796,8 +797,9 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
        char *dir_page;
        int retval;
 
-       retval = copy_mount_string(type, &kernel_type);
-       if (retval < 0)
+       kernel_type = copy_mount_string(type);
+       retval = PTR_ERR(kernel_type);
+       if (IS_ERR(kernel_type))
                goto out;
 
        dir_page = getname(dir_name);
@@ -805,8 +807,9 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
        if (IS_ERR(dir_page))
                goto out1;
 
-       retval = copy_mount_string(dev_name, &kernel_dev);
-       if (retval < 0)
+       kernel_dev = copy_mount_string(dev_name);
+       retval = PTR_ERR(kernel_dev);
+       if (IS_ERR(kernel_dev))
                goto out2;
 
        retval = copy_mount_options(data, &data_page);
@@ -1106,17 +1109,12 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        if (!file->f_op)
                goto out;
 
-       ret = -EFAULT;
-       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+                                              UIO_FASTIOV, iovstack, &iov, 1);
+       if (ret <= 0)
                goto out;
 
-       tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs,
-                                              UIO_FASTIOV, iovstack, &iov);
-       if (tot_len == 0) {
-               ret = 0;
-               goto out;
-       }
-
+       tot_len = ret;
        ret = rw_verify_area(type, file, pos, tot_len);
        if (ret < 0)
                goto out;
@@ -1177,11 +1175,14 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
        struct file *file;
        int fput_needed;
        ssize_t ret;
+       loff_t pos;
 
        file = fget_light(fd, &fput_needed);
        if (!file)
                return -EBADF;
-       ret = compat_readv(file, vec, vlen, &file->f_pos);
+       pos = file->f_pos;
+       ret = compat_readv(file, vec, vlen, &pos);
+       file->f_pos = pos;
        fput_light(file, fput_needed);
        return ret;
 }
@@ -1236,11 +1237,14 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
        struct file *file;
        int fput_needed;
        ssize_t ret;
+       loff_t pos;
 
        file = fget_light(fd, &fput_needed);
        if (!file)
                return -EBADF;
-       ret = compat_writev(file, vec, vlen, &file->f_pos);
+       pos = file->f_pos;
+       ret = compat_writev(file, vec, vlen, &pos);
+       file->f_pos = pos;
        fput_light(file, fput_needed);
        return ret;
 }