lkml.org 
[lkml]   [2018]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 339/410] usb: usbmon: Read text within supplied buffer size
    3.16.57-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Pete Zaitcev <zaitcev@kotori.zaitcev.us>

    commit a5f596830e27e15f7a0ecd6be55e433d776986d8 upstream.

    This change fixes buffer overflows and silent data corruption with the
    usbmon device driver text file read operations.

    Signed-off-by: Fredrik Noring <noring@nocrew.org>
    Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/usb/mon/mon_text.c | 126 +++++++++++++++++++++++--------------
    1 file changed, 78 insertions(+), 48 deletions(-)

    --- a/drivers/usb/mon/mon_text.c
    +++ b/drivers/usb/mon/mon_text.c
    @@ -82,6 +82,8 @@ struct mon_reader_text {

    wait_queue_head_t wait;
    int printf_size;
    + size_t printf_offset;
    + size_t printf_togo;
    char *printf_buf;
    struct mutex printf_lock;

    @@ -373,75 +375,103 @@ err_alloc:
    return rc;
    }

    -/*
    - * For simplicity, we read one record in one system call and throw out
    - * what does not fit. This means that the following does not work:
    - * dd if=/dbg/usbmon/0t bs=10
    - * Also, we do not allow seeks and do not bother advancing the offset.
    - */
    +static ssize_t mon_text_copy_to_user(struct mon_reader_text *rp,
    + char __user * const buf, const size_t nbytes)
    +{
    + const size_t togo = min(nbytes, rp->printf_togo);
    +
    + if (copy_to_user(buf, &rp->printf_buf[rp->printf_offset], togo))
    + return -EFAULT;
    + rp->printf_togo -= togo;
    + rp->printf_offset += togo;
    + return togo;
    +}
    +
    +/* ppos is not advanced since the llseek operation is not permitted. */
    static ssize_t mon_text_read_t(struct file *file, char __user *buf,
    - size_t nbytes, loff_t *ppos)
    + size_t nbytes, loff_t *ppos)
    {
    struct mon_reader_text *rp = file->private_data;
    struct mon_event_text *ep;
    struct mon_text_ptr ptr;
    + ssize_t ret;

    - ep = mon_text_read_wait(rp, file);
    - if (IS_ERR(ep))
    - return PTR_ERR(ep);
    mutex_lock(&rp->printf_lock);
    - ptr.cnt = 0;
    - ptr.pbuf = rp->printf_buf;
    - ptr.limit = rp->printf_size;
    -
    - mon_text_read_head_t(rp, &ptr, ep);
    - mon_text_read_statset(rp, &ptr, ep);
    - ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
    - " %d", ep->length);
    - mon_text_read_data(rp, &ptr, ep);

    - if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
    - ptr.cnt = -EFAULT;
    + if (rp->printf_togo == 0) {
    +
    + ep = mon_text_read_wait(rp, file);
    + if (IS_ERR(ep)) {
    + mutex_unlock(&rp->printf_lock);
    + return PTR_ERR(ep);
    + }
    + ptr.cnt = 0;
    + ptr.pbuf = rp->printf_buf;
    + ptr.limit = rp->printf_size;
    +
    + mon_text_read_head_t(rp, &ptr, ep);
    + mon_text_read_statset(rp, &ptr, ep);
    + ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
    + " %d", ep->length);
    + mon_text_read_data(rp, &ptr, ep);
    +
    + rp->printf_togo = ptr.cnt;
    + rp->printf_offset = 0;
    +
    + kmem_cache_free(rp->e_slab, ep);
    + }
    +
    + ret = mon_text_copy_to_user(rp, buf, nbytes);
    mutex_unlock(&rp->printf_lock);
    - kmem_cache_free(rp->e_slab, ep);
    - return ptr.cnt;
    + return ret;
    }

    +/* ppos is not advanced since the llseek operation is not permitted. */
    static ssize_t mon_text_read_u(struct file *file, char __user *buf,
    - size_t nbytes, loff_t *ppos)
    + size_t nbytes, loff_t *ppos)
    {
    struct mon_reader_text *rp = file->private_data;
    struct mon_event_text *ep;
    struct mon_text_ptr ptr;
    + ssize_t ret;

    - ep = mon_text_read_wait(rp, file);
    - if (IS_ERR(ep))
    - return PTR_ERR(ep);
    mutex_lock(&rp->printf_lock);
    - ptr.cnt = 0;
    - ptr.pbuf = rp->printf_buf;
    - ptr.limit = rp->printf_size;

    - mon_text_read_head_u(rp, &ptr, ep);
    - if (ep->type == 'E') {
    - mon_text_read_statset(rp, &ptr, ep);
    - } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
    - mon_text_read_isostat(rp, &ptr, ep);
    - mon_text_read_isodesc(rp, &ptr, ep);
    - } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
    - mon_text_read_intstat(rp, &ptr, ep);
    - } else {
    - mon_text_read_statset(rp, &ptr, ep);
    + if (rp->printf_togo == 0) {
    +
    + ep = mon_text_read_wait(rp, file);
    + if (IS_ERR(ep)) {
    + mutex_unlock(&rp->printf_lock);
    + return PTR_ERR(ep);
    + }
    + ptr.cnt = 0;
    + ptr.pbuf = rp->printf_buf;
    + ptr.limit = rp->printf_size;
    +
    + mon_text_read_head_u(rp, &ptr, ep);
    + if (ep->type == 'E') {
    + mon_text_read_statset(rp, &ptr, ep);
    + } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
    + mon_text_read_isostat(rp, &ptr, ep);
    + mon_text_read_isodesc(rp, &ptr, ep);
    + } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
    + mon_text_read_intstat(rp, &ptr, ep);
    + } else {
    + mon_text_read_statset(rp, &ptr, ep);
    + }
    + ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
    + " %d", ep->length);
    + mon_text_read_data(rp, &ptr, ep);
    +
    + rp->printf_togo = ptr.cnt;
    + rp->printf_offset = 0;
    +
    + kmem_cache_free(rp->e_slab, ep);
    }
    - ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
    - " %d", ep->length);
    - mon_text_read_data(rp, &ptr, ep);

    - if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
    - ptr.cnt = -EFAULT;
    + ret = mon_text_copy_to_user(rp, buf, nbytes);
    mutex_unlock(&rp->printf_lock);
    - kmem_cache_free(rp->e_slab, ep);
    - return ptr.cnt;
    + return ret;
    }

    static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp,
    \
     
     \ /
      Last update: 2018-06-07 17:52    [W:2.378 / U:0.112 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site