Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Dec 2019 00:29:48 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r355636 - stable/12/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201912120029.xBC0TmAJ021932@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Thu Dec 12 00:29:48 2019
New Revision: 355636
URL: https://svnweb.freebsd.org/changeset/base/355636

Log:
  MFC r355182: Fix use-after-free in case of L2ARC prefetch failure.
  
  In case L2ARC read failed, l2arc_read_done() creates _different_ ZIO
  to read data from the original storage device.  Unfortunately pointer
  to the failed ZIO remains in hdr->b_l1hdr.b_acb->acb_zio_head, and if
  some other read try to bump the ZIO priority, it will crash.
  
  The problem is reproducible by corrupting L2ARC content and reading
  some data with prefetch if l2arc_noprefetch tunable is changed to 0.
  With the default setting the issue is probably not reproducible now.

Modified:
  stable/12/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
==============================================================================
--- stable/12/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c	Thu Dec 12 00:14:01 2019	(r355635)
+++ stable/12/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c	Thu Dec 12 00:29:48 2019	(r355636)
@@ -7886,7 +7886,6 @@ l2arc_read_done(zio_t *zio)
 		zio->io_private = hdr;
 		arc_read_done(zio);
 	} else {
-		mutex_exit(hash_lock);
 		/*
 		 * Buffer didn't survive caching.  Increment stats and
 		 * reissue to the original storage device.
@@ -7909,11 +7908,17 @@ l2arc_read_done(zio_t *zio)
 
 			ASSERT(!pio || pio->io_child_type == ZIO_CHILD_LOGICAL);
 
-			zio_nowait(zio_read(pio, zio->io_spa, zio->io_bp,
+			zio = zio_read(pio, zio->io_spa, zio->io_bp,
 			    hdr->b_l1hdr.b_pabd, zio->io_size, arc_read_done,
 			    hdr, zio->io_priority, cb->l2rcb_flags,
-			    &cb->l2rcb_zb));
-		}
+			    &cb->l2rcb_zb);
+			for (struct arc_callback *acb = hdr->b_l1hdr.b_acb;
+			    acb != NULL; acb = acb->acb_next)
+				acb->acb_zio_head = zio;
+			mutex_exit(hash_lock);
+			zio_nowait(zio);
+		} else
+			mutex_exit(hash_lock);
 	}
 
 	kmem_free(cb, sizeof (l2arc_read_callback_t));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912120029.xBC0TmAJ021932>