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 Reviewed by: ken, mav MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D9869
This commit is contained in:
parent
8ff15e8613
commit
a0bbf9e0e3
@ -435,6 +435,9 @@ xptdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *
|
||||
inccb->csio.bio = NULL;
|
||||
#endif
|
||||
|
||||
if (inccb->ccb_h.flags & CAM_UNLOCKED)
|
||||
return (EINVAL);
|
||||
|
||||
bus = xpt_find_bus(inccb->ccb_h.path_id);
|
||||
if (bus == NULL)
|
||||
return (EINVAL);
|
||||
|
@ -1782,6 +1782,11 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
|
||||
inccb->csio.bio = NULL;
|
||||
#endif
|
||||
|
||||
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.
|
||||
@ -1875,24 +1880,27 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
|
||||
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 defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
|
||||
if (ccb->ccb_h.func_code == XPT_SCSI_IO)
|
||||
ccb->csio.bio = NULL;
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1904,10 +1912,8 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1953,11 +1959,8 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
|
||||
|| (fc == XPT_SMP_IO) || (fc == XPT_DEV_MATCH)
|
||||
|| (fc == XPT_DEV_ADVINFO)) {
|
||||
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;
|
||||
|
||||
@ -2002,6 +2005,11 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
|
||||
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:
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user