Loading block/scsi_ioctl.c +24 −10 Original line number Diff line number Diff line Loading @@ -321,33 +321,47 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, if (hdr->iovec_count) { const int size = sizeof(struct sg_iovec) * hdr->iovec_count; size_t iov_data_len; struct sg_iovec *iov; struct sg_iovec *sg_iov; struct iovec *iov; int i; iov = kmalloc(size, GFP_KERNEL); if (!iov) { sg_iov = kmalloc(size, GFP_KERNEL); if (!sg_iov) { ret = -ENOMEM; goto out; } if (copy_from_user(iov, hdr->dxferp, size)) { kfree(iov); if (copy_from_user(sg_iov, hdr->dxferp, size)) { kfree(sg_iov); ret = -EFAULT; goto out; } /* * Sum up the vecs, making sure they don't overflow */ iov = (struct iovec *) sg_iov; iov_data_len = 0; for (i = 0; i < hdr->iovec_count; i++) { if (iov_data_len + iov[i].iov_len < iov_data_len) { kfree(sg_iov); ret = -EINVAL; goto out; } iov_data_len += iov[i].iov_len; } /* SG_IO howto says that the shorter of the two wins */ iov_data_len = iov_length((struct iovec *)iov, hdr->iovec_count); if (hdr->dxfer_len < iov_data_len) { hdr->iovec_count = iov_shorten((struct iovec *)iov, hdr->iovec_count = iov_shorten(iov, hdr->iovec_count, hdr->dxfer_len); iov_data_len = hdr->dxfer_len; } ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, ret = blk_rq_map_user_iov(q, rq, NULL, sg_iov, hdr->iovec_count, iov_data_len, GFP_KERNEL); kfree(iov); kfree(sg_iov); } else if (hdr->dxfer_len) ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, GFP_KERNEL); Loading Loading
block/scsi_ioctl.c +24 −10 Original line number Diff line number Diff line Loading @@ -321,33 +321,47 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, if (hdr->iovec_count) { const int size = sizeof(struct sg_iovec) * hdr->iovec_count; size_t iov_data_len; struct sg_iovec *iov; struct sg_iovec *sg_iov; struct iovec *iov; int i; iov = kmalloc(size, GFP_KERNEL); if (!iov) { sg_iov = kmalloc(size, GFP_KERNEL); if (!sg_iov) { ret = -ENOMEM; goto out; } if (copy_from_user(iov, hdr->dxferp, size)) { kfree(iov); if (copy_from_user(sg_iov, hdr->dxferp, size)) { kfree(sg_iov); ret = -EFAULT; goto out; } /* * Sum up the vecs, making sure they don't overflow */ iov = (struct iovec *) sg_iov; iov_data_len = 0; for (i = 0; i < hdr->iovec_count; i++) { if (iov_data_len + iov[i].iov_len < iov_data_len) { kfree(sg_iov); ret = -EINVAL; goto out; } iov_data_len += iov[i].iov_len; } /* SG_IO howto says that the shorter of the two wins */ iov_data_len = iov_length((struct iovec *)iov, hdr->iovec_count); if (hdr->dxfer_len < iov_data_len) { hdr->iovec_count = iov_shorten((struct iovec *)iov, hdr->iovec_count = iov_shorten(iov, hdr->iovec_count, hdr->dxfer_len); iov_data_len = hdr->dxfer_len; } ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, ret = blk_rq_map_user_iov(q, rq, NULL, sg_iov, hdr->iovec_count, iov_data_len, GFP_KERNEL); kfree(iov); kfree(sg_iov); } else if (hdr->dxfer_len) ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, GFP_KERNEL); Loading