svn commit: r260626 - in stable/10/sys/cam: . scsi

Alexander Motin mav at FreeBSD.org
Tue Jan 14 12:01:37 UTC 2014


Author: mav
Date: Tue Jan 14 12:01:36 2014
New Revision: 260626
URL: http://svnweb.freebsd.org/changeset/base/260626

Log:
  MFC r260541, r260547:
  Take additional reference on SCSI probe periph to cover its freeze count.
  
  Otherwise periph may be invalidated and freed before single-stepping freeze
  is dropped, causing use after free panic.

Modified:
  stable/10/sys/cam/cam_periph.c
  stable/10/sys/cam/cam_periph.h
  stable/10/sys/cam/cam_xpt.c
  stable/10/sys/cam/scsi/scsi_xpt.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/cam_periph.c
==============================================================================
--- stable/10/sys/cam/cam_periph.c	Tue Jan 14 10:03:31 2014	(r260625)
+++ stable/10/sys/cam/cam_periph.c	Tue Jan 14 12:01:36 2014	(r260626)
@@ -376,6 +376,17 @@ cam_periph_acquire(struct cam_periph *pe
 }
 
 void
+cam_periph_doacquire(struct cam_periph *periph)
+{
+
+	xpt_lock_buses();
+	KASSERT(periph->refcount >= 1,
+	    ("cam_periph_doacquire() with refcount == %d", periph->refcount));
+	periph->refcount++;
+	xpt_unlock_buses();
+}
+
+void
 cam_periph_release_locked_buses(struct cam_periph *periph)
 {
 

Modified: stable/10/sys/cam/cam_periph.h
==============================================================================
--- stable/10/sys/cam/cam_periph.h	Tue Jan 14 10:03:31 2014	(r260625)
+++ stable/10/sys/cam/cam_periph.h	Tue Jan 14 12:01:36 2014	(r260626)
@@ -152,6 +152,7 @@ cam_status cam_periph_alloc(periph_ctor_
 struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
 int		cam_periph_list(struct cam_path *, struct sbuf *);
 cam_status	cam_periph_acquire(struct cam_periph *periph);
+void		cam_periph_doacquire(struct cam_periph *periph);
 void		cam_periph_release(struct cam_periph *periph);
 void		cam_periph_release_locked(struct cam_periph *periph);
 void		cam_periph_release_locked_buses(struct cam_periph *periph);

Modified: stable/10/sys/cam/cam_xpt.c
==============================================================================
--- stable/10/sys/cam/cam_xpt.c	Tue Jan 14 10:03:31 2014	(r260625)
+++ stable/10/sys/cam/cam_xpt.c	Tue Jan 14 12:01:36 2014	(r260626)
@@ -3154,9 +3154,7 @@ restart:
 			}
 			if (periph->flags & CAM_PERIPH_RUN_TASK)
 				break;
-			xpt_lock_buses();
-			periph->refcount++;	/* Unconditionally acquire */
-			xpt_unlock_buses();
+			cam_periph_doacquire(periph);
 			periph->flags |= CAM_PERIPH_RUN_TASK;
 			taskqueue_enqueue(xsoftc.xpt_taskq,
 			    &periph->periph_run_task);

Modified: stable/10/sys/cam/scsi/scsi_xpt.c
==============================================================================
--- stable/10/sys/cam/scsi/scsi_xpt.c	Tue Jan 14 10:03:31 2014	(r260625)
+++ stable/10/sys/cam/scsi/scsi_xpt.c	Tue Jan 14 12:01:36 2014	(r260626)
@@ -890,12 +890,14 @@ again:
 				     /*timeout*/60 * 1000);
 			break;
 		}
+done:
 		/*
 		 * We'll have to do without, let our probedone
 		 * routine finish up for us.
 		 */
 		start_ccb->csio.data_ptr = NULL;
 		cam_freeze_devq(periph->path);
+		cam_periph_doacquire(periph);
 		probedone(periph, start_ccb);
 		return;
 	}
@@ -921,14 +923,7 @@ again:
 				     /*timeout*/60 * 1000);
 			break;
 		}
-		/*
-		 * We'll have to do without, let our probedone
-		 * routine finish up for us.
-		 */
-		start_ccb->csio.data_ptr = NULL;
-		cam_freeze_devq(periph->path);
-		probedone(periph, start_ccb);
-		return;
+		goto done;
 	}
 	case PROBE_SERIAL_NUM:
 	{
@@ -961,19 +956,13 @@ again:
 				     /*timeout*/60 * 1000);
 			break;
 		}
-		/*
-		 * We'll have to do without, let our probedone
-		 * routine finish up for us.
-		 */
-		start_ccb->csio.data_ptr = NULL;
-		cam_freeze_devq(periph->path);
-		probedone(periph, start_ccb);
-		return;
+		goto done;
 	}
 	default:
 		panic("probestart: invalid action state 0x%x\n", softc->action);
 	}
 	start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
+	cam_periph_doacquire(periph);
 	xpt_action(start_ccb);
 }
 
@@ -1121,7 +1110,7 @@ probedone(struct cam_periph *periph, uni
 
 			if (cam_periph_error(done_ccb, 0,
 					     SF_NO_PRINT, NULL) == ERESTART) {
-out:
+outr:
 				/* Drop freeze taken due to CAM_DEV_QFREEZE */
 				cam_release_devq(path, 0, 0, 0, FALSE);
 				return;
@@ -1135,7 +1124,11 @@ out:
 		PROBE_SET_ACTION(softc, PROBE_INQUIRY);
 		xpt_release_ccb(done_ccb);
 		xpt_schedule(periph, priority);
-		goto out;
+out:
+		/* Drop freeze taken due to CAM_DEV_QFREEZE and release. */
+		cam_release_devq(path, 0, 0, 0, FALSE);
+		cam_periph_release_locked(periph);
+		return;
 	}
 	case PROBE_INQUIRY:
 	case PROBE_FULL_INQUIRY:
@@ -1222,7 +1215,7 @@ out:
 					    ? SF_RETRY_UA|SF_QUIET_IR
 					    : SF_RETRY_UA,
 					    &softc->saved_ccb) == ERESTART) {
-			goto out;
+			goto outr;
 		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
 			/* Don't wedge the queue */
 			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@@ -1263,7 +1256,7 @@ out:
 			    done_ccb->ccb_h.target_lun > 0 ?
 			    SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA,
 			    &softc->saved_ccb) == ERESTART) {
-				goto out;
+				goto outr;
 			}
 			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
 				xpt_release_devq(done_ccb->ccb_h.path, 1,
@@ -1373,7 +1366,7 @@ out:
 		} else if (cam_periph_error(done_ccb, 0,
 					    SF_RETRY_UA|SF_NO_PRINT,
 					    &softc->saved_ccb) == ERESTART) {
-			goto out;
+			goto outr;
 		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
 			/* Don't wedge the queue */
 			xpt_release_devq(done_ccb->ccb_h.path,
@@ -1416,7 +1409,7 @@ out:
 		} else if (cam_periph_error(done_ccb, 0,
 					    SF_RETRY_UA|SF_NO_PRINT,
 					    &softc->saved_ccb) == ERESTART) {
-			goto out;
+			goto outr;
 		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
 			/* Don't wedge the queue */
 			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@@ -1461,7 +1454,7 @@ out:
 		} else if (cam_periph_error(done_ccb, 0,
 					    SF_RETRY_UA,
 					    &softc->saved_ccb) == ERESTART) {
-			goto out;
+			goto outr;
 		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
 			/* Don't wedge the queue */
 			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@@ -1516,7 +1509,7 @@ probe_device_check:
 		} else if (cam_periph_error(done_ccb, 0,
 					    SF_RETRY_UA|SF_NO_PRINT,
 					    &softc->saved_ccb) == ERESTART) {
-			goto out;
+			goto outr;
 		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
 			/* Don't wedge the queue */
 			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@@ -1699,6 +1692,7 @@ probe_device_check:
 		CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n"));
 		/* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */
 		cam_release_devq(path, 0, 0, 0, FALSE);
+		cam_periph_release_locked(periph);
 		cam_periph_invalidate(periph);
 		cam_periph_release_locked(periph);
 	} else {


More information about the svn-src-all mailing list