From owner-svn-src-all@freebsd.org Wed Oct 16 06:11:12 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 4D03F15C503; Wed, 16 Oct 2019 06:11:12 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46tMPD0s8bz4HK3; Wed, 16 Oct 2019 06:11:12 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D81072906; Wed, 16 Oct 2019 06:11:11 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x9G6BB9K065959; Wed, 16 Oct 2019 06:11:11 GMT (envelope-from avg@FreeBSD.org) Received: (from avg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x9G6BBP1065958; Wed, 16 Oct 2019 06:11:11 GMT (envelope-from avg@FreeBSD.org) Message-Id: <201910160611.x9G6BBP1065958@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avg set sender to avg@FreeBSD.org using -f From: Andriy Gapon Date: Wed, 16 Oct 2019 06:11:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r353610 - vendor-sys/illumos/dist/uts/common/fs/zfs X-SVN-Group: vendor-sys X-SVN-Commit-Author: avg X-SVN-Commit-Paths: vendor-sys/illumos/dist/uts/common/fs/zfs X-SVN-Commit-Revision: 353610 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Oct 2019 06:11:12 -0000 Author: avg Date: Wed Oct 16 06:11:11 2019 New Revision: 353610 URL: https://svnweb.freebsd.org/changeset/base/353610 Log: 10230 zfs mishandles partial writes illumos/illumos-gate@b0ef425652e5cfce27df9fa5826a9cd64cee110a https://github.com/illumos/illumos-gate/commit/b0ef425652e5cfce27df9fa5826a9cd64cee110a https://www.illumos.org/issues/10230 The trinity fuzzer calls pwritev with an iovec that has one or more entries which point to some initial valid data and then the rest point to addresses which are not mapped. This yields EFAULT once the write hits the invalid address, but we do successfully complete some amount of writing. The zfs_write code does not handle this properly. It loses track of the error return from dmu_write_uio_dbuf and it has an invalid ASSERT which does not account for the partial write case. Author: Jerry Jelinek Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c Wed Oct 16 06:09:00 2019 (r353609) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c Wed Oct 16 06:11:11 2019 (r353610) @@ -23,7 +23,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2017 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] - * Copyright 2015 Joyent, Inc. + * Copyright 2019 Joyent, Inc. * Copyright 2017 Nexenta Systems, Inc. */ @@ -665,6 +665,7 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t ssize_t n, nbytes; int max_blksz = zfsvfs->z_max_blksz; int error = 0; + int prev_error; arc_buf_t *abuf; iovec_t *aiov = NULL; xuio_t *xuio = NULL; @@ -972,7 +973,6 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t while ((end_size = zp->z_size) < uio->uio_loffset) { (void) atomic_cas_64(&zp->z_size, end_size, uio->uio_loffset); - ASSERT(error == 0); } /* * If we are replaying and eof is non zero then force @@ -982,12 +982,17 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t if (zfsvfs->z_replay && zfsvfs->z_replay_eof != 0) zp->z_size = zfsvfs->z_replay_eof; + /* + * Keep track of a possible pre-existing error from a partial + * write via dmu_write_uio_dbuf above. + */ + prev_error = error; error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx); zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag); dmu_tx_commit(tx); - if (error != 0) + if (prev_error != 0 || error != 0) break; ASSERT(tx_bytes == nbytes); n -= nbytes;