From c9e237a7b2c18eb90cf81b1bb6f1e1682461ce14 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Mon, 21 Sep 2015 19:08:26 -0400 Subject: [PATCH] Userspace can pass zero length segments via writev/readv Userspace can trigger an assertion by passing a zero-length segment when assertions are enabled: [27961.614792] VERIFY3(skip < iov->iov_len) failed (0 < 0) [27961.614795] PANIC at zfs_uio.c:187:uio_prefaultpages() [27961.614805] Call Trace: [27961.614811] dump_stack+0x45/0x57 [27961.614830] spl_dumpstack+0x44/0x50 [spl] [27961.614834] spl_panic+0xbb/0x100 [spl] [27961.614908] uio_prefaultpages+0x134/0x140 [zcommon] [27961.614930] zfs_write+0x1fd/0xe80 [zfs] [27961.615014] zpl_write_common_iovec+0x7f/0x110 [zfs] [27961.615035] zpl_iter_write+0xa0/0xd0 [zfs] [27961.615037] do_iter_readv_writev+0x59/0x80 [27961.615063] do_readv_writev+0x11b/0x260 [27961.615098] vfs_writev+0x39/0x50 [27961.615100] SyS_writev+0x4a/0xe0 [27961.615103] system_call_fastpath+0x16/0x6e The solution is to delete the assertion. This could potentially occur in uiomove as well, which contains analogous assertions that appear similarly unnecessary, so we remove those as well. Reported-by: Jonathan Vasquez Signed-off-by: Brian Behlendorf Signed-off-by: Richard Yao Issue #3792 --- module/zcommon/zfs_uio.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/module/zcommon/zfs_uio.c b/module/zcommon/zfs_uio.c index a5634fca0c..6037fed801 100644 --- a/module/zcommon/zfs_uio.c +++ b/module/zcommon/zfs_uio.c @@ -64,8 +64,6 @@ uiomove_iov(void *p, size_t n, enum uio_rw rw, struct uio *uio) size_t skip = uio->uio_skip; ulong_t cnt; - ASSERT3U(skip, <, iov->iov_len); - while (n && uio->uio_resid) { cnt = MIN(iov->iov_len - skip, n); switch (uio->uio_segflg) { @@ -114,8 +112,6 @@ uiomove_bvec(void *p, size_t n, enum uio_rw rw, struct uio *uio) size_t skip = uio->uio_skip; ulong_t cnt; - ASSERT3U(skip, <, bv->bv_len); - while (n && uio->uio_resid) { void *paddr; cnt = MIN(bv->bv_len - skip, n); @@ -184,7 +180,6 @@ uio_prefaultpages(ssize_t n, struct uio *uio) iov = uio->uio_iov; iovcnt = uio->uio_iovcnt; - ASSERT3U(skip, <, iov->iov_len); while ((n > 0) && (iovcnt > 0)) { cnt = MIN(iov->iov_len - skip, n);