aboutsummaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-05-26 19:43:16 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-05-29 23:18:31 -0400
commit95af8496ac48263badf5b8dde5e06ef35aaace2b (patch)
treed316aa39d95c2b72ae36593503b6005c7bf0d448 /fs/aio.c
parentd2988bd412fac87859f0b68f5ea328fb0f09c216 (diff)
aio: shift copyin of iocb into io_submit_one()
Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/aio.c')
-rw-r--r--fs/aio.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 06761d5aac1e..90b46560f0ce 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1720,22 +1720,26 @@ out_fail:
1720} 1720}
1721 1721
1722static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, 1722static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1723 struct iocb *iocb, bool compat) 1723 bool compat)
1724{ 1724{
1725 struct aio_kiocb *req; 1725 struct aio_kiocb *req;
1726 struct iocb iocb;
1726 ssize_t ret; 1727 ssize_t ret;
1727 1728
1729 if (unlikely(copy_from_user(&iocb, user_iocb, sizeof(iocb))))
1730 return -EFAULT;
1731
1728 /* enforce forwards compatibility on users */ 1732 /* enforce forwards compatibility on users */
1729 if (unlikely(iocb->aio_reserved2)) { 1733 if (unlikely(iocb.aio_reserved2)) {
1730 pr_debug("EINVAL: reserve field set\n"); 1734 pr_debug("EINVAL: reserve field set\n");
1731 return -EINVAL; 1735 return -EINVAL;
1732 } 1736 }
1733 1737
1734 /* prevent overflows */ 1738 /* prevent overflows */
1735 if (unlikely( 1739 if (unlikely(
1736 (iocb->aio_buf != (unsigned long)iocb->aio_buf) || 1740 (iocb.aio_buf != (unsigned long)iocb.aio_buf) ||
1737 (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) || 1741 (iocb.aio_nbytes != (size_t)iocb.aio_nbytes) ||
1738 ((ssize_t)iocb->aio_nbytes < 0) 1742 ((ssize_t)iocb.aio_nbytes < 0)
1739 )) { 1743 )) {
1740 pr_debug("EINVAL: overflow check\n"); 1744 pr_debug("EINVAL: overflow check\n");
1741 return -EINVAL; 1745 return -EINVAL;
@@ -1745,14 +1749,14 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1745 if (unlikely(!req)) 1749 if (unlikely(!req))
1746 return -EAGAIN; 1750 return -EAGAIN;
1747 1751
1748 if (iocb->aio_flags & IOCB_FLAG_RESFD) { 1752 if (iocb.aio_flags & IOCB_FLAG_RESFD) {
1749 /* 1753 /*
1750 * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an 1754 * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
1751 * instance of the file* now. The file descriptor must be 1755 * instance of the file* now. The file descriptor must be
1752 * an eventfd() fd, and will be signaled for each completed 1756 * an eventfd() fd, and will be signaled for each completed
1753 * event using the eventfd_signal() function. 1757 * event using the eventfd_signal() function.
1754 */ 1758 */
1755 req->ki_eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd); 1759 req->ki_eventfd = eventfd_ctx_fdget((int) iocb.aio_resfd);
1756 if (IS_ERR(req->ki_eventfd)) { 1760 if (IS_ERR(req->ki_eventfd)) {
1757 ret = PTR_ERR(req->ki_eventfd); 1761 ret = PTR_ERR(req->ki_eventfd);
1758 req->ki_eventfd = NULL; 1762 req->ki_eventfd = NULL;
@@ -1767,32 +1771,32 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1767 } 1771 }
1768 1772
1769 req->ki_user_iocb = user_iocb; 1773 req->ki_user_iocb = user_iocb;
1770 req->ki_user_data = iocb->aio_data; 1774 req->ki_user_data = iocb.aio_data;
1771 1775
1772 switch (iocb->aio_lio_opcode) { 1776 switch (iocb.aio_lio_opcode) {
1773 case IOCB_CMD_PREAD: 1777 case IOCB_CMD_PREAD:
1774 ret = aio_read(&req->rw, iocb, false, compat); 1778 ret = aio_read(&req->rw, &iocb, false, compat);
1775 break; 1779 break;
1776 case IOCB_CMD_PWRITE: 1780 case IOCB_CMD_PWRITE:
1777 ret = aio_write(&req->rw, iocb, false, compat); 1781 ret = aio_write(&req->rw, &iocb, false, compat);
1778 break; 1782 break;
1779 case IOCB_CMD_PREADV: 1783 case IOCB_CMD_PREADV:
1780 ret = aio_read(&req->rw, iocb, true, compat); 1784 ret = aio_read(&req->rw, &iocb, true, compat);
1781 break; 1785 break;
1782 case IOCB_CMD_PWRITEV: 1786 case IOCB_CMD_PWRITEV:
1783 ret = aio_write(&req->rw, iocb, true, compat); 1787 ret = aio_write(&req->rw, &iocb, true, compat);
1784 break; 1788 break;
1785 case IOCB_CMD_FSYNC: 1789 case IOCB_CMD_FSYNC:
1786 ret = aio_fsync(&req->fsync, iocb, false); 1790 ret = aio_fsync(&req->fsync, &iocb, false);
1787 break; 1791 break;
1788 case IOCB_CMD_FDSYNC: 1792 case IOCB_CMD_FDSYNC:
1789 ret = aio_fsync(&req->fsync, iocb, true); 1793 ret = aio_fsync(&req->fsync, &iocb, true);
1790 break; 1794 break;
1791 case IOCB_CMD_POLL: 1795 case IOCB_CMD_POLL:
1792 ret = aio_poll(req, iocb); 1796 ret = aio_poll(req, &iocb);
1793 break; 1797 break;
1794 default: 1798 default:
1795 pr_debug("invalid aio operation %d\n", iocb->aio_lio_opcode); 1799 pr_debug("invalid aio operation %d\n", iocb.aio_lio_opcode);
1796 ret = -EINVAL; 1800 ret = -EINVAL;
1797 break; 1801 break;
1798 } 1802 }
@@ -1845,19 +1849,13 @@ static long do_io_submit(aio_context_t ctx_id, long nr,
1845 */ 1849 */
1846 for (i=0; i<nr; i++) { 1850 for (i=0; i<nr; i++) {
1847 struct iocb __user *user_iocb; 1851 struct iocb __user *user_iocb;
1848 struct iocb tmp;
1849 1852
1850 if (unlikely(__get_user(user_iocb, iocbpp + i))) { 1853 if (unlikely(__get_user(user_iocb, iocbpp + i))) {
1851 ret = -EFAULT; 1854 ret = -EFAULT;
1852 break; 1855 break;
1853 } 1856 }
1854 1857
1855 if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) { 1858 ret = io_submit_one(ctx, user_iocb, compat);
1856 ret = -EFAULT;
1857 break;
1858 }
1859
1860 ret = io_submit_one(ctx, user_iocb, &tmp, compat);
1861 if (ret) 1859 if (ret)
1862 break; 1860 break;
1863 } 1861 }