mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	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. Reviewed-by: Tom Caputi <tcaputi@datto.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored-By: iXsystems, Inc. Closes #9648
This commit is contained in:
		
							parent
							
								
									9cf46ddedc
								
							
						
					
					
						commit
						388ef045b2
					
				@ -8561,7 +8561,6 @@ l2arc_read_done(zio_t *zio)
 | 
				
			|||||||
		zio->io_private = hdr;
 | 
							zio->io_private = hdr;
 | 
				
			||||||
		arc_read_done(zio);
 | 
							arc_read_done(zio);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		mutex_exit(hash_lock);
 | 
					 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Buffer didn't survive caching.  Increment stats and
 | 
							 * Buffer didn't survive caching.  Increment stats and
 | 
				
			||||||
		 * reissue to the original storage device.
 | 
							 * reissue to the original storage device.
 | 
				
			||||||
@ -8586,10 +8585,24 @@ l2arc_read_done(zio_t *zio)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			ASSERT(!pio || pio->io_child_type == ZIO_CHILD_LOGICAL);
 | 
								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,
 | 
				
			||||||
			    abd, zio->io_size, arc_read_done,
 | 
								    abd, zio->io_size, arc_read_done,
 | 
				
			||||||
			    hdr, zio->io_priority, cb->l2rcb_flags,
 | 
								    hdr, zio->io_priority, cb->l2rcb_flags,
 | 
				
			||||||
			    &cb->l2rcb_zb));
 | 
								    &cb->l2rcb_zb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * Original ZIO will be freed, so we need to update
 | 
				
			||||||
 | 
								 * ARC header with the new ZIO pointer to be used
 | 
				
			||||||
 | 
								 * by zio_change_priority() in arc_read().
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								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);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user