diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-26 20:10:07 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-29 23:20:17 -0400 |
commit | 1da92779e2e8f309d5aecbbed346e7f812b174e8 (patch) | |
tree | ef7385c244e4affbec1e58b4f4cef068a80c6a4e /fs/aio.c | |
parent | 67ba049f94ebe49ed557e590dd243b6db45c9aff (diff) |
aio: sanitize the limit checking in io_submit(2)
as it is, the logics in native io_submit(2) is "if asked for
more than LONG_MAX/sizeof(pointer) iocbs to submit, don't
bother with more than LONG_MAX/sizeof(pointer)" (i.e.
512M requests on 32bit and 1E requests on 64bit) while
compat io_submit(2) goes with "stop after the first
PAGE_SIZE/sizeof(pointer) iocbs", i.e. 1K or so. Which is
* inconsistent
* *way* too much in native case
* possibly too little in compat one
and
* wrong anyway, since the natural point where we
ought to stop bothering is ctx->nr_events
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 | 14 |
1 files changed, 6 insertions, 8 deletions
@@ -1841,15 +1841,15 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, | |||
1841 | if (unlikely(nr < 0)) | 1841 | if (unlikely(nr < 0)) |
1842 | return -EINVAL; | 1842 | return -EINVAL; |
1843 | 1843 | ||
1844 | if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) | ||
1845 | nr = LONG_MAX/sizeof(*iocbpp); | ||
1846 | |||
1847 | ctx = lookup_ioctx(ctx_id); | 1844 | ctx = lookup_ioctx(ctx_id); |
1848 | if (unlikely(!ctx)) { | 1845 | if (unlikely(!ctx)) { |
1849 | pr_debug("EINVAL: invalid context id\n"); | 1846 | pr_debug("EINVAL: invalid context id\n"); |
1850 | return -EINVAL; | 1847 | return -EINVAL; |
1851 | } | 1848 | } |
1852 | 1849 | ||
1850 | if (nr > ctx->nr_events) | ||
1851 | nr = ctx->nr_events; | ||
1852 | |||
1853 | blk_start_plug(&plug); | 1853 | blk_start_plug(&plug); |
1854 | for (i = 0; i < nr; i++) { | 1854 | for (i = 0; i < nr; i++) { |
1855 | struct iocb __user *user_iocb; | 1855 | struct iocb __user *user_iocb; |
@@ -1870,8 +1870,6 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, | |||
1870 | } | 1870 | } |
1871 | 1871 | ||
1872 | #ifdef CONFIG_COMPAT | 1872 | #ifdef CONFIG_COMPAT |
1873 | #define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) | ||
1874 | |||
1875 | COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, | 1873 | COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, |
1876 | int, nr, compat_uptr_t __user *, iocbpp) | 1874 | int, nr, compat_uptr_t __user *, iocbpp) |
1877 | { | 1875 | { |
@@ -1883,15 +1881,15 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, | |||
1883 | if (unlikely(nr < 0)) | 1881 | if (unlikely(nr < 0)) |
1884 | return -EINVAL; | 1882 | return -EINVAL; |
1885 | 1883 | ||
1886 | if (nr > MAX_AIO_SUBMITS) | ||
1887 | nr = MAX_AIO_SUBMITS; | ||
1888 | |||
1889 | ctx = lookup_ioctx(ctx_id); | 1884 | ctx = lookup_ioctx(ctx_id); |
1890 | if (unlikely(!ctx)) { | 1885 | if (unlikely(!ctx)) { |
1891 | pr_debug("EINVAL: invalid context id\n"); | 1886 | pr_debug("EINVAL: invalid context id\n"); |
1892 | return -EINVAL; | 1887 | return -EINVAL; |
1893 | } | 1888 | } |
1894 | 1889 | ||
1890 | if (nr > ctx->nr_events) | ||
1891 | nr = ctx->nr_events; | ||
1892 | |||
1895 | blk_start_plug(&plug); | 1893 | blk_start_plug(&plug); |
1896 | for (i = 0; i < nr; i++) { | 1894 | for (i = 0; i < nr; i++) { |
1897 | compat_uptr_t user_iocb; | 1895 | compat_uptr_t user_iocb; |