]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Userspace can pass zero length segments via writev/readv
authorRichard Yao <ryao@gentoo.org>
Mon, 21 Sep 2015 23:08:26 +0000 (19:08 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 25 Sep 2015 19:51:16 +0000 (12:51 -0700)
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

module/zcommon/zfs_uio.c

index a5634fca0c05836a032bfc82221ab3cf89eff970..6037fed8015154591d52723f8960bd1c78cfede9 100644 (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;
        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);