Merge git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/netdev-2.6
[pandora-kernel.git] / fs / compat.c
index ef5a077..01f39f8 100644 (file)
@@ -1217,6 +1217,10 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        if (ret < 0)
                goto out;
 
+       ret = security_file_permission(file, type == READ ? MAY_READ:MAY_WRITE);
+       if (ret)
+               goto out;
+
        fnv = NULL;
        if (type == READ) {
                fn = file->f_op->read;
@@ -1313,6 +1317,26 @@ out:
        return ret;
 }
 
+asmlinkage long
+compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
+                   unsigned int nr_segs, unsigned int flags)
+{
+       unsigned i;
+       struct iovec *iov;
+       if (nr_segs > UIO_MAXIOV)
+               return -EINVAL;
+       iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
+       for (i = 0; i < nr_segs; i++) {
+               struct compat_iovec v;
+               if (get_user(v.iov_base, &iov32[i].iov_base) ||
+                   get_user(v.iov_len, &iov32[i].iov_len) ||
+                   put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
+                   put_user(v.iov_len, &iov[i].iov_len))
+                       return -EFAULT;
+       }
+       return sys_vmsplice(fd, iov, nr_segs, flags);
+}
+
 /*
  * Exactly like fs/open.c:sys_open(), except that it doesn't set the
  * O_LARGEFILE flag.
@@ -1639,15 +1663,6 @@ void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
  * This is a virtual copy of sys_select from fs/select.c and probably
  * should be compared to it from time to time
  */
-static void *select_bits_alloc(int size)
-{
-       return kmalloc(6 * size, GFP_KERNEL);
-}
-
-static void select_bits_free(void *bits, int size)
-{
-       kfree(bits);
-}
 
 /*
  * We can actually return ERESTARTSYS instead of EINTR, but I'd
@@ -1686,7 +1701,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
         */
        ret = -ENOMEM;
        size = FDS_BYTES(n);
-       bits = select_bits_alloc(size);
+       bits = kmalloc(6 * size, GFP_KERNEL);
        if (!bits)
                goto out_nofds;
        fds.in      = (unsigned long *)  bits;
@@ -1720,7 +1735,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
        compat_set_fd_set(n, exp, fds.res_ex);
 
 out:
-       select_bits_free(bits, size);
+       kfree(bits);
 out_nofds:
        return ret;
 }
@@ -1898,7 +1913,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
        }
 
        if (sigmask) {
-               if (sigsetsize |= sizeof(compat_sigset_t))
+               if (sigsetsize != sizeof(compat_sigset_t))
                        return -EINVAL;
                if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
                        return -EFAULT;