Patch "usb: usbmon: Read text within supplied buffer size" has been added to the 4.9-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
usb: usbmon: Read text within supplied buffer size
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
usb-usbmon-read-text-within-supplied-buffer-size.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
a5f596830e27e15f7a0ecd6be55e433d776986d8Mon Sep 17 00:00:00 2001
From: Pete Zaitcev <[email protected]>
Date: Fri, 9 Mar 2018 00:21:14 -0600
Subject: usb: usbmon: Read text within supplied buffer size
From: Pete Zaitcev <[email protected]>
commit a5f596830e27e15f7a0ecd6be55e433d776986d8 upstream.
This change fixes buffer overflows and silent data corruption with the usbmon device driver text file read operations.
--- drivers/usb/mon/mon_text.c | 124 +++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 47 deletions(-)
drivers/usb/mon/mon_text.c +77 -47
@@ -83,6 +83,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;
@@ -374,75 +376,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,
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/usb-usbmon-read-text-within-supplied-buffer-size.patch