mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-23 07:31:31 +00:00
Don't pass a user buffer pointer as the data pointer in a CCB.
Allocate a temporary buffer in the kernel to serve as the CCB data pointer for a pass-through transaction and use copyin/copyout to shuffle the data to/from the user buffer. Reviewed by: scottl, brooks Obtained from: CheriBSD MFC after: 2 weeks Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D24489
This commit is contained in:
parent
24c2e17d2b
commit
81b62a7663
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=360179
@ -508,6 +508,7 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
|
||||
struct cam_periph *periph;
|
||||
struct sg_softc *softc;
|
||||
struct sg_io_hdr *req;
|
||||
void *data_ptr;
|
||||
int dir, error;
|
||||
|
||||
periph = (struct cam_periph *)dev->si_drv1;
|
||||
@ -552,12 +553,20 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
|
||||
break;
|
||||
}
|
||||
|
||||
if (req->dxfer_len > MAXPHYS) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
data_ptr = malloc(req->dxfer_len, M_DEVBUF, M_WAITOK);
|
||||
|
||||
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
|
||||
csio = &ccb->csio;
|
||||
|
||||
error = copyin(req->cmdp, &csio->cdb_io.cdb_bytes,
|
||||
req->cmd_len);
|
||||
if (error) {
|
||||
free(data_ptr, M_DEVBUF);
|
||||
xpt_release_ccb(ccb);
|
||||
break;
|
||||
}
|
||||
@ -570,7 +579,7 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
|
||||
dir = CAM_DIR_IN;
|
||||
break;
|
||||
case SG_DXFER_TO_FROM_DEV:
|
||||
dir = CAM_DIR_IN | CAM_DIR_OUT;
|
||||
dir = CAM_DIR_BOTH;
|
||||
break;
|
||||
case SG_DXFER_NONE:
|
||||
default:
|
||||
@ -578,12 +587,21 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dir == CAM_DIR_IN || dir == CAM_DIR_BOTH) {
|
||||
error = copyin(req->dxferp, data_ptr, req->dxfer_len);
|
||||
if (error) {
|
||||
free(data_ptr, M_DEVBUF);
|
||||
xpt_release_ccb(ccb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cam_fill_csio(csio,
|
||||
/*retries*/1,
|
||||
/*cbfcnp*/NULL,
|
||||
dir|CAM_DEV_QFRZDIS,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
req->dxferp,
|
||||
data_ptr,
|
||||
req->dxfer_len,
|
||||
req->mx_sb_len,
|
||||
req->cmd_len,
|
||||
@ -593,6 +611,7 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
|
||||
if (error) {
|
||||
req->host_status = DID_ERROR;
|
||||
req->driver_status = DRIVER_INVALID;
|
||||
free(data_ptr, M_DEVBUF);
|
||||
xpt_release_ccb(ccb);
|
||||
break;
|
||||
}
|
||||
@ -611,6 +630,10 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
|
||||
req->sb_len_wr);
|
||||
}
|
||||
|
||||
if ((dir == CAM_DIR_OUT || dir == CAM_DIR_BOTH) && error == 0)
|
||||
error = copyout(data_ptr, req->dxferp, req->dxfer_len);
|
||||
|
||||
free(data_ptr, M_DEVBUF);
|
||||
xpt_release_ccb(ccb);
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user