|
@@ -36,6 +36,7 @@
|
|
|
#include <linux/blkdev.h>
|
|
|
#include <linux/mempool.h>
|
|
|
#include <linux/hash.h>
|
|
|
+#include <linux/compat.h>
|
|
|
|
|
|
#include <asm/kmap_types.h>
|
|
|
#include <asm/uaccess.h>
|
|
@@ -1384,13 +1385,22 @@ static ssize_t aio_fsync(struct kiocb *iocb)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb)
|
|
|
+static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
|
|
|
{
|
|
|
ssize_t ret;
|
|
|
|
|
|
- ret = rw_copy_check_uvector(type, (struct iovec __user *)kiocb->ki_buf,
|
|
|
- kiocb->ki_nbytes, 1,
|
|
|
- &kiocb->ki_inline_vec, &kiocb->ki_iovec);
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+ if (compat)
|
|
|
+ ret = compat_rw_copy_check_uvector(type,
|
|
|
+ (struct compat_iovec __user *)kiocb->ki_buf,
|
|
|
+ kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
|
|
|
+ &kiocb->ki_iovec);
|
|
|
+ else
|
|
|
+#endif
|
|
|
+ ret = rw_copy_check_uvector(type,
|
|
|
+ (struct iovec __user *)kiocb->ki_buf,
|
|
|
+ kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
|
|
|
+ &kiocb->ki_iovec);
|
|
|
if (ret < 0)
|
|
|
goto out;
|
|
|
|
|
@@ -1420,7 +1430,7 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
|
|
|
* Performs the initial checks and aio retry method
|
|
|
* setup for the kiocb at the time of io submission.
|
|
|
*/
|
|
|
-static ssize_t aio_setup_iocb(struct kiocb *kiocb)
|
|
|
+static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
|
|
|
{
|
|
|
struct file *file = kiocb->ki_filp;
|
|
|
ssize_t ret = 0;
|
|
@@ -1469,7 +1479,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
|
|
|
ret = security_file_permission(file, MAY_READ);
|
|
|
if (unlikely(ret))
|
|
|
break;
|
|
|
- ret = aio_setup_vectored_rw(READ, kiocb);
|
|
|
+ ret = aio_setup_vectored_rw(READ, kiocb, compat);
|
|
|
if (ret)
|
|
|
break;
|
|
|
ret = -EINVAL;
|
|
@@ -1483,7 +1493,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
|
|
|
ret = security_file_permission(file, MAY_WRITE);
|
|
|
if (unlikely(ret))
|
|
|
break;
|
|
|
- ret = aio_setup_vectored_rw(WRITE, kiocb);
|
|
|
+ ret = aio_setup_vectored_rw(WRITE, kiocb, compat);
|
|
|
if (ret)
|
|
|
break;
|
|
|
ret = -EINVAL;
|
|
@@ -1548,7 +1558,8 @@ static void aio_batch_free(struct hlist_head *batch_hash)
|
|
|
}
|
|
|
|
|
|
static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
|
|
|
- struct iocb *iocb, struct hlist_head *batch_hash)
|
|
|
+ struct iocb *iocb, struct hlist_head *batch_hash,
|
|
|
+ bool compat)
|
|
|
{
|
|
|
struct kiocb *req;
|
|
|
struct file *file;
|
|
@@ -1609,7 +1620,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
|
|
|
req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
|
|
|
req->ki_opcode = iocb->aio_lio_opcode;
|
|
|
|
|
|
- ret = aio_setup_iocb(req);
|
|
|
+ ret = aio_setup_iocb(req, compat);
|
|
|
|
|
|
if (ret)
|
|
|
goto out_put_req;
|
|
@@ -1637,20 +1648,8 @@ out_put_req:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/* sys_io_submit:
|
|
|
- * Queue the nr iocbs pointed to by iocbpp for processing. Returns
|
|
|
- * the number of iocbs queued. May return -EINVAL if the aio_context
|
|
|
- * specified by ctx_id is invalid, if nr is < 0, if the iocb at
|
|
|
- * *iocbpp[0] is not properly initialized, if the operation specified
|
|
|
- * is invalid for the file descriptor in the iocb. May fail with
|
|
|
- * -EFAULT if any of the data structures point to invalid data. May
|
|
|
- * fail with -EBADF if the file descriptor specified in the first
|
|
|
- * iocb is invalid. May fail with -EAGAIN if insufficient resources
|
|
|
- * are available to queue any iocbs. Will return 0 if nr is 0. Will
|
|
|
- * fail with -ENOSYS if not implemented.
|
|
|
- */
|
|
|
-SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
|
|
|
- struct iocb __user * __user *, iocbpp)
|
|
|
+long do_io_submit(aio_context_t ctx_id, long nr,
|
|
|
+ struct iocb __user *__user *iocbpp, bool compat)
|
|
|
{
|
|
|
struct kioctx *ctx;
|
|
|
long ret = 0;
|
|
@@ -1687,7 +1686,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash);
|
|
|
+ ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash, compat);
|
|
|
if (ret)
|
|
|
break;
|
|
|
}
|
|
@@ -1697,6 +1696,24 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
|
|
|
return i ? i : ret;
|
|
|
}
|
|
|
|
|
|
+/* sys_io_submit:
|
|
|
+ * Queue the nr iocbs pointed to by iocbpp for processing. Returns
|
|
|
+ * the number of iocbs queued. May return -EINVAL if the aio_context
|
|
|
+ * specified by ctx_id is invalid, if nr is < 0, if the iocb at
|
|
|
+ * *iocbpp[0] is not properly initialized, if the operation specified
|
|
|
+ * is invalid for the file descriptor in the iocb. May fail with
|
|
|
+ * -EFAULT if any of the data structures point to invalid data. May
|
|
|
+ * fail with -EBADF if the file descriptor specified in the first
|
|
|
+ * iocb is invalid. May fail with -EAGAIN if insufficient resources
|
|
|
+ * are available to queue any iocbs. Will return 0 if nr is 0. Will
|
|
|
+ * fail with -ENOSYS if not implemented.
|
|
|
+ */
|
|
|
+SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
|
|
|
+ struct iocb __user * __user *, iocbpp)
|
|
|
+{
|
|
|
+ return do_io_submit(ctx_id, nr, iocbpp, 0);
|
|
|
+}
|
|
|
+
|
|
|
/* lookup_kiocb
|
|
|
* Finds a given iocb for cancellation.
|
|
|
*/
|