diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-26 19:43:16 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-29 23:18:31 -0400 |
commit | 95af8496ac48263badf5b8dde5e06ef35aaace2b (patch) | |
tree | d316aa39d95c2b72ae36593503b6005c7bf0d448 /fs/aio.c | |
parent | d2988bd412fac87859f0b68f5ea328fb0f09c216 (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.c | 46 |
1 files changed, 22 insertions, 24 deletions
@@ -1720,22 +1720,26 @@ out_fail: | |||
1720 | } | 1720 | } |
1721 | 1721 | ||
1722 | static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | 1722 | static 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 | } |