Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Mar 2018 09:57:58 +0000 (UTC)
From:      Tijl Coosemans <tijl@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r330926 - in stable/11/sys/cam: . scsi
Message-ID:  <201803140957.w2E9vwxO038725@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tijl
Date: Wed Mar 14 09:57:58 2018
New Revision: 330926
URL: https://svnweb.freebsd.org/changeset/base/330926

Log:
  MFC r314624:
  
  Reject userland CCBs that have CAM_UNLOCKED set.
  
  CAM_UNLOCKED is internal flag and cannot correctly be set by userland.
  Return EINVAL from CAMIOCOMMAND and CAMIOQUEUE if it is set.
  
  Also fix leaks in some of the error paths for CAMIOQUEUE.
  
  PR:		215356

Modified:
  stable/11/sys/cam/cam_xpt.c
  stable/11/sys/cam/scsi/scsi_pass.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/cam/cam_xpt.c
==============================================================================
--- stable/11/sys/cam/cam_xpt.c	Wed Mar 14 09:20:03 2018	(r330925)
+++ stable/11/sys/cam/cam_xpt.c	Wed Mar 14 09:57:58 2018	(r330926)
@@ -414,6 +414,9 @@ xptdoioctl(struct cdev *dev, u_long cmd, caddr_t addr,
 
 		inccb = (union ccb *)addr;
 
+		if (inccb->ccb_h.flags & CAM_UNLOCKED)
+			return (EINVAL);
+
 		bus = xpt_find_bus(inccb->ccb_h.path_id);
 		if (bus == NULL)
 			return (EINVAL);

Modified: stable/11/sys/cam/scsi/scsi_pass.c
==============================================================================
--- stable/11/sys/cam/scsi/scsi_pass.c	Wed Mar 14 09:20:03 2018	(r330925)
+++ stable/11/sys/cam/scsi/scsi_pass.c	Wed Mar 14 09:57:58 2018	(r330926)
@@ -1798,6 +1798,11 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr
 
 		inccb = (union ccb *)addr;
 
+		if (inccb->ccb_h.flags & CAM_UNLOCKED) {
+			error = EINVAL;
+			break;
+		}
+
 		/*
 		 * Some CCB types, like scan bus and scan lun can only go
 		 * through the transport layer device.
@@ -1891,20 +1896,23 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr
 			xpt_print(periph->path, "Copy of user CCB %p to "
 				  "kernel address %p failed with error %d\n",
 				  *user_ccb, ccb, error);
-			uma_zfree(softc->pass_zone, io_req);
-			cam_periph_lock(periph);
-			break;
+			goto camioqueue_error;
 		}
 
+		if (ccb->ccb_h.flags & CAM_UNLOCKED) {
+			error = EINVAL;
+			goto camioqueue_error;
+		}
+
 		if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
 			if (ccb->csio.cdb_len > IOCDBLEN) {
 				error = EINVAL;
-				break;
+				goto camioqueue_error;
 			}
 			error = copyin(ccb->csio.cdb_io.cdb_ptr,
 			    ccb->csio.cdb_io.cdb_bytes, ccb->csio.cdb_len);
-			if (error)
-				break;
+			if (error != 0)
+				goto camioqueue_error;
 			ccb->ccb_h.flags &= ~CAM_CDB_POINTER;
 		}
 
@@ -1916,10 +1924,8 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr
 			xpt_print(periph->path, "CCB function code %#x is "
 			    "restricted to the XPT device\n",
 			    ccb->ccb_h.func_code);
-			uma_zfree(softc->pass_zone, io_req);
-			cam_periph_lock(periph);
 			error = ENODEV;
-			break;
+			goto camioqueue_error;
 		}
 
 		/*
@@ -1966,11 +1972,8 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr
 		 || (fc == XPT_DEV_ADVINFO)
 		 || (fc == XPT_NVME_ADMIN) || (fc == XPT_NVME_IO)) {
 			error = passmemsetup(periph, io_req);
-			if (error != 0) {
-				uma_zfree(softc->pass_zone, io_req);
-				cam_periph_lock(periph);
-				break;
-			}
+			if (error != 0)
+				goto camioqueue_error;
 		} else
 			io_req->mapinfo.num_bufs_used = 0;
 
@@ -2014,6 +2017,11 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr
 			TAILQ_REMOVE(&softc->active_queue, io_req, links);
 			TAILQ_INSERT_TAIL(&softc->done_queue, io_req, links);
 		}
+		break;
+
+camioqueue_error:
+		uma_zfree(softc->pass_zone, io_req);
+		cam_periph_lock(periph);
 		break;
 	}
 	case CAMIOGET:



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