iovec_import() has a safer calling convention than import_iovec().

Signed-off-by: David Laight <[email protected]>
---
 fs/aio.c        | 34 ++++++++++++------------
 fs/read_write.c | 69 ++++++++++++++++++++++++++-----------------------
 fs/splice.c     | 22 +++++++++-------
 3 files changed, 65 insertions(+), 60 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index d5ec30385566..909c03143374 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1477,24 +1477,20 @@ static int aio_prep_rw(struct kiocb *req, const struct 
iocb *iocb)
        return 0;
 }
 
-static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
-               struct iovec **iovec, bool vectored, bool compat,
+static struct iovec *aio_setup_rw(int rw, const struct iocb *iocb,
+               struct iovec_cache *cache, bool vectored, bool compat,
                struct iov_iter *iter)
 {
        void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf;
        size_t len = iocb->aio_nbytes;
 
-       if (!vectored) {
-               ssize_t ret = import_single_range(rw, buf, len, *iovec, iter);
-               *iovec = NULL;
-               return ret;
-       }
+       if (!vectored)
+               return ERR_PTR(import_single_range(rw, buf, len, cache->iov, 
iter));
 #ifdef CONFIG_COMPAT
        if (compat)
-               return compat_import_iovec(rw, buf, len, UIO_FASTIOV, iovec,
-                               iter);
+               return compat_iovec_import(rw, buf, len, cache, iter);
 #endif
-       return import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter);
+       return iovec_import(rw, buf, len, cache, iter);
 }
 
 static inline void aio_rw_done(struct kiocb *req, ssize_t ret)
@@ -1520,8 +1516,9 @@ static inline void aio_rw_done(struct kiocb *req, ssize_t 
ret)
 static int aio_read(struct kiocb *req, const struct iocb *iocb,
                        bool vectored, bool compat)
 {
-       struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iovec;
        struct file *file;
        int ret;
 
@@ -1535,9 +1532,9 @@ static int aio_read(struct kiocb *req, const struct iocb 
*iocb,
        if (unlikely(!file->f_op->read_iter))
                return -EINVAL;
 
-       ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter);
-       if (ret < 0)
-               return ret;
+       iovec = aio_setup_rw(READ, iocb, &cache, vectored, compat, &iter);
+       if (IS_ERR(iovec))
+               return PTR_ERR(iovec);
        ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
        if (!ret)
                aio_rw_done(req, call_read_iter(file, req, &iter));
@@ -1548,8 +1545,9 @@ static int aio_read(struct kiocb *req, const struct iocb 
*iocb,
 static int aio_write(struct kiocb *req, const struct iocb *iocb,
                         bool vectored, bool compat)
 {
-       struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iovec;
        struct file *file;
        int ret;
 
@@ -1563,9 +1561,9 @@ static int aio_write(struct kiocb *req, const struct iocb 
*iocb,
        if (unlikely(!file->f_op->write_iter))
                return -EINVAL;
 
-       ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter);
-       if (ret < 0)
-               return ret;
+       iovec = aio_setup_rw(WRITE, iocb, &cache, vectored, compat, &iter);
+       if (IS_ERR(iovec))
+               return PTR_ERR(iovec);
        ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter));
        if (!ret) {
                /*
diff --git a/fs/read_write.c b/fs/read_write.c
index e5e891a88442..6e3d4a646f3c 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -884,35 +884,38 @@ EXPORT_SYMBOL(vfs_iter_write);
 ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
                  unsigned long vlen, loff_t *pos, rwf_t flags)
 {
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iov;
        ssize_t ret;
 
-       ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
-       if (ret >= 0) {
-               ret = do_iter_read(file, &iter, pos, flags);
-               kfree(iov);
-       }
+       iov = iovec_import(READ, vec, vlen, &cache, &iter);
+       if (IS_ERR(iov))
+               return PTR_ERR(iov);
+
+       ret = do_iter_read(file, &iter, pos, flags);
 
+       kfree(iov);
        return ret;
 }
 
 static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
                   unsigned long vlen, loff_t *pos, rwf_t flags)
 {
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iov;
        ssize_t ret;
 
-       ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
-       if (ret >= 0) {
-               file_start_write(file);
-               ret = do_iter_write(file, &iter, pos, flags);
-               file_end_write(file);
-               kfree(iov);
-       }
+       iov = iovec_import(WRITE, vec, vlen, &cache, &iter);
+       if (IS_ERR(iov))
+               return PTR_ERR(iov);
+
+       file_start_write(file);
+       ret = do_iter_write(file, &iter, pos, flags);
+       file_end_write(file);
+
+       kfree(iov);
        return ret;
 }
 
@@ -1073,16 +1076,17 @@ static size_t compat_readv(struct file *file,
                           const struct compat_iovec __user *vec,
                           unsigned long vlen, loff_t *pos, rwf_t flags)
 {
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iov;
        ssize_t ret;
 
-       ret = compat_import_iovec(READ, vec, vlen, UIO_FASTIOV, &iov, &iter);
-       if (ret >= 0) {
-               ret = do_iter_read(file, &iter, pos, flags);
-               kfree(iov);
-       }
+       iov = compat_iovec_import(READ, vec, vlen, &cache, &iter);
+       if (IS_ERR(iov))
+               return PTR_ERR(iov);
+
+       ret = do_iter_read(file, &iter, pos, flags);
+       kfree(iov);
        if (ret > 0)
                add_rchar(current, ret);
        inc_syscr(current);
@@ -1181,18 +1185,19 @@ static size_t compat_writev(struct file *file,
                            const struct compat_iovec __user *vec,
                            unsigned long vlen, loff_t *pos, rwf_t flags)
 {
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iov;
        ssize_t ret;
 
-       ret = compat_import_iovec(WRITE, vec, vlen, UIO_FASTIOV, &iov, &iter);
-       if (ret >= 0) {
-               file_start_write(file);
-               ret = do_iter_write(file, &iter, pos, flags);
-               file_end_write(file);
-               kfree(iov);
-       }
+       iov = compat_iovec_import(WRITE, vec, vlen, &cache, &iter);
+       if (IS_ERR(iov))
+               return PTR_ERR(iov);
+
+       file_start_write(file);
+       ret = do_iter_write(file, &iter, pos, flags);
+       file_end_write(file);
+       kfree(iov);
        if (ret > 0)
                add_wchar(current, ret);
        inc_syscw(current);
diff --git a/fs/splice.c b/fs/splice.c
index d7c8a7c4db07..ec1a825525d0 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1349,9 +1349,9 @@ static long do_vmsplice(struct file *f, struct iov_iter 
*iter, unsigned int flag
 SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
                unsigned long, nr_segs, unsigned int, flags)
 {
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iov;
        ssize_t error;
        struct fd f;
        int type;
@@ -1361,9 +1361,10 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec 
__user *, uiov,
        if (error)
                return error;
 
-       error = import_iovec(type, uiov, nr_segs,
-                            ARRAY_SIZE(iovstack), &iov, &iter);
-       if (error >= 0) {
+       iov = iovec_import(type, uiov, nr_segs, &cache, &iter);
+       if (IS_ERR(iov)) {
+               error = PTR_ERR(iov);
+       } else {
                error = do_vmsplice(f.file, &iter, flags);
                kfree(iov);
        }
@@ -1375,9 +1376,9 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec 
__user *, uiov,
 COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, 
iov32,
                    unsigned int, nr_segs, unsigned int, flags)
 {
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
+       struct iovec_cache cache;
        struct iov_iter iter;
+       struct iovec *iov;
        ssize_t error;
        struct fd f;
        int type;
@@ -1387,9 +1388,10 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct 
compat_iovec __user *, io
        if (error)
                return error;
 
-       error = compat_import_iovec(type, iov32, nr_segs,
-                            ARRAY_SIZE(iovstack), &iov, &iter);
-       if (error >= 0) {
+       iov = compat_iovec_import(type, iov32, nr_segs, &cache, &iter);
+       if (IS_ERR(iov)) {
+               error = PTR_ERR(iov);
+       } else {
                error = do_vmsplice(f.file, &iter, flags);
                kfree(iov);
        }
-- 
2.25.1

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)

Reply via email to