git: e76786909ce0 - main - Fix data race in scsi cd driver.

Alexander Motin mav at FreeBSD.org
Mon Sep 13 13:02:31 UTC 2021


The branch main has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=e76786909ce0195855196305a04d86b40f138894

commit e76786909ce0195855196305a04d86b40f138894
Author:     Alexander Motin <mav at FreeBSD.org>
AuthorDate: 2021-09-13 12:59:51 +0000
Commit:     Alexander Motin <mav at FreeBSD.org>
CommitDate: 2021-09-13 12:59:51 +0000

    Fix data race in scsi cd driver.
    
    There is a data race between cdsysctlinit and cdcheckmedia.  Both
    functions change softc->flags without synchronization.
    
    Submitted by:   Arseny Smalyuk <smalukav at gmail.com>
    MFC after:      2 weeks
    Differential Revision: https://reviews.freebsd.org/D31726
---
 sys/cam/scsi/scsi_cd.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index 4babe4003050..3e8187544bff 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -371,6 +371,7 @@ cdoninvalidate(struct cam_periph *periph)
 {
 	struct cd_softc *softc;
 
+	cam_periph_assert(periph, MA_OWNED);
 	softc = (struct cd_softc *)periph->softc;
 
 	/*
@@ -451,7 +452,7 @@ cdasync(void *callback_arg, u_int32_t code,
 			printf("cdasync: Unable to attach new device "
 			       "due to status 0x%x\n", status);
 
-		break;
+		return;
 	}
 	case AC_UNIT_ATTENTION:
 	{
@@ -471,10 +472,10 @@ cdasync(void *callback_arg, u_int32_t code,
 			if (asc == 0x28 && ascq == 0x00)
 				disk_media_changed(softc->disk, M_NOWAIT);
 		}
-		cam_periph_async(periph, code, path, arg);
 		break;
 	}
 	case AC_SCSI_AEN:
+		cam_periph_assert(periph, MA_OWNED);
 		softc = (struct cd_softc *)periph->softc;
 		if (softc->state == CD_STATE_NORMAL && !softc->tur) {
 			if (cam_periph_acquire(periph) == 0) {
@@ -488,6 +489,7 @@ cdasync(void *callback_arg, u_int32_t code,
 	{
 		struct ccb_hdr *ccbh;
 
+		cam_periph_assert(periph, MA_OWNED);
 		softc = (struct cd_softc *)periph->softc;
 		/*
 		 * Don't fail on the expected unit attention
@@ -496,12 +498,13 @@ cdasync(void *callback_arg, u_int32_t code,
 		softc->flags |= CD_FLAG_RETRY_UA;
 		LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
 			ccbh->ccb_state |= CD_CCB_RETRY_UA;
-		/* FALLTHROUGH */
+		break;
 	}
 	default:
-		cam_periph_async(periph, code, path, arg);
 		break;
 	}
+
+	cam_periph_async(periph, code, path, arg);
 }
 
 static void
@@ -520,7 +523,9 @@ cdsysctlinit(void *context, int pending)
 	snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
 
 	sysctl_ctx_init(&softc->sysctl_ctx);
+	cam_periph_lock(periph);
 	softc->flags |= CD_FLAG_SCTX_INIT;
+	cam_periph_unlock(periph);
 	softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
 		SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO,
 		tmpstr2, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr,
@@ -899,6 +904,7 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
 	struct bio *bp;
 	struct ccb_scsiio *csio;
 
+	cam_periph_assert(periph, MA_OWNED);
 	softc = (struct cd_softc *)periph->softc;
 
 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstart\n"));
@@ -1143,6 +1149,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
 
 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cddone\n"));
 
+	cam_periph_assert(periph, MA_OWNED);
 	softc = (struct cd_softc *)periph->softc;
 	csio = &done_ccb->csio;
 
@@ -2624,6 +2631,7 @@ cdprevent(struct cam_periph *periph, int action)
 
 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdprevent\n"));
 
+	cam_periph_assert(periph, MA_OWNED);
 	softc = (struct cd_softc *)periph->softc;
 
 	if (((action == PR_ALLOW)
@@ -2661,6 +2669,7 @@ cdmediaprobedone(struct cam_periph *periph)
 {
 	struct cd_softc *softc;
 
+	cam_periph_assert(periph, MA_OWNED);
 	softc = (struct cd_softc *)periph->softc;
 
 	softc->flags &= ~CD_FLAG_MEDIA_SCAN_ACT;
@@ -2682,6 +2691,7 @@ cdcheckmedia(struct cam_periph *periph, int do_wait)
 	struct cd_softc *softc;
 	int error;
 
+	cam_periph_assert(periph, MA_OWNED);
 	softc = (struct cd_softc *)periph->softc;
 	error = 0;
 
@@ -3071,13 +3081,14 @@ cderror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 	periph = xpt_path_periph(ccb->ccb_h.path);
 	softc = (struct cd_softc *)periph->softc;
 
-	error = 0;
+	cam_periph_assert(periph, MA_OWNED);
 
 	/*
 	 * We use a status of CAM_REQ_INVALID as shorthand -- if a 6 byte
 	 * CDB comes back with this particular error, try transforming it
 	 * into the 10 byte version.
 	 */
+	error = 0;
 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
 		error = cd6byteworkaround(ccb);
 	} else if (scsi_extract_sense_ccb(ccb,


More information about the dev-commits-src-all mailing list