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 <jvasquez1011@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Richard Yao <ryao@gentoo.org>
Issue #3792
This commit is contained in:
Richard Yao 2015-09-21 19:08:26 -04:00 committed by Ned Bass
parent 13e3c4be75
commit c9e237a7b2
1 changed files with 0 additions and 5 deletions

View File

@ -64,8 +64,6 @@ uiomove_iov(void *p, size_t n, enum uio_rw rw, struct uio *uio)
size_t skip = uio->uio_skip; size_t skip = uio->uio_skip;
ulong_t cnt; ulong_t cnt;
ASSERT3U(skip, <, iov->iov_len);
while (n && uio->uio_resid) { while (n && uio->uio_resid) {
cnt = MIN(iov->iov_len - skip, n); cnt = MIN(iov->iov_len - skip, n);
switch (uio->uio_segflg) { 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; size_t skip = uio->uio_skip;
ulong_t cnt; ulong_t cnt;
ASSERT3U(skip, <, bv->bv_len);
while (n && uio->uio_resid) { while (n && uio->uio_resid) {
void *paddr; void *paddr;
cnt = MIN(bv->bv_len - skip, n); cnt = MIN(bv->bv_len - skip, n);
@ -184,7 +180,6 @@ uio_prefaultpages(ssize_t n, struct uio *uio)
iov = uio->uio_iov; iov = uio->uio_iov;
iovcnt = uio->uio_iovcnt; iovcnt = uio->uio_iovcnt;
ASSERT3U(skip, <, iov->iov_len);
while ((n > 0) && (iovcnt > 0)) { while ((n > 0) && (iovcnt > 0)) {
cnt = MIN(iov->iov_len - skip, n); cnt = MIN(iov->iov_len - skip, n);