lkml.org 
[lkml]   [2010]   [Dec]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] [4/223] block: take care not to overflow when calculating total iov length
    Date
    2.6.35-longterm review patch.  If anyone has any objections, please let me know.

    ------------------
    From: Jens Axboe <jaxboe@fusionio.com>

    commit 9f864c80913467312c7b8690e41fb5ebd1b50e92 upstream.

    Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
    Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
    Signed-off-by: Andi Kleen <ak@linux.intel.com>

    ---
    block/scsi_ioctl.c | 34 ++++++++++++++++++++++++----------
    1 file changed, 24 insertions(+), 10 deletions(-)

    Index: linux/block/scsi_ioctl.c
    ===================================================================
    --- linux.orig/block/scsi_ioctl.c
    +++ linux/block/scsi_ioctl.c
    @@ -321,33 +321,47 @@ static int sg_io(struct request_queue *q
    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);

    \
     
     \ /
      Last update: 2010-12-13 01:33    [W:0.023 / U:0.264 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site