Message ID | 20181109143326.31048-2-kleber.souza@canonical.com |
---|---|
State | New |
Headers | show |
Series | Fix for CVE-2018-16276 | expand |
On 2018-11-09 15:33:25 , Kleber Souza wrote: > From: Jann Horn <jannh@google.com> > > In general, accessing userspace memory beyond the length of the supplied > buffer in VFS read/write handlers can lead to both kernel memory corruption > (via kernel_read()/kernel_write(), which can e.g. be triggered via > sys_splice()) and privilege escalation inside userspace. > > Fix it by using simple_read_from_buffer() instead of custom logic. > > Fixes: 6bc235a2e24a ("USB: add driver for Meywa-Denki & Kayac YUREX") > Signed-off-by: Jann Horn <jannh@google.com> > Cc: stable <stable@vger.kernel.org> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > > CVE-2018-16276 > (backported from commit f1e255d60ae66a9f672ff9a207ee6cd8e33d2679) > [ klebers: context adjustment ] > Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > drivers/usb/misc/yurex.c | 23 ++++++----------------- > 1 file changed, 6 insertions(+), 17 deletions(-) > > diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c > index b6ab515bfc6c..0a5b1ba47b62 100644 > --- a/drivers/usb/misc/yurex.c > +++ b/drivers/usb/misc/yurex.c > @@ -415,8 +415,7 @@ static int yurex_release(struct inode *inode, struct file *file) > static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos) > { > struct usb_yurex *dev; > - int retval = 0; > - int bytes_read = 0; > + int len = 0; > char in_buffer[20]; > unsigned long flags; > > @@ -424,26 +423,16 @@ static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t > > mutex_lock(&dev->io_mutex); > if (!dev->interface) { /* already disconnected */ > - retval = -ENODEV; > - goto exit; > + mutex_unlock(&dev->io_mutex); > + return -ENODEV; > } > > spin_lock_irqsave(&dev->lock, flags); > - bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); > + len = snprintf(in_buffer, 20, "%lld\n", dev->bbu); > spin_unlock_irqrestore(&dev->lock, flags); > - > - if (*ppos < bytes_read) { > - if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos)) > - retval = -EFAULT; > - else { > - retval = bytes_read - *ppos; > - *ppos += bytes_read; > - } > - } > - > -exit: > mutex_unlock(&dev->io_mutex); > - return retval; > + > + return simple_read_from_buffer(buffer, count, ppos, in_buffer, len); > } > > static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) Acked-by: Khalid Elmously <khalid.elmously@canonical.com>
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index b6ab515bfc6c..0a5b1ba47b62 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -415,8 +415,7 @@ static int yurex_release(struct inode *inode, struct file *file) static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct usb_yurex *dev; - int retval = 0; - int bytes_read = 0; + int len = 0; char in_buffer[20]; unsigned long flags; @@ -424,26 +423,16 @@ static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t mutex_lock(&dev->io_mutex); if (!dev->interface) { /* already disconnected */ - retval = -ENODEV; - goto exit; + mutex_unlock(&dev->io_mutex); + return -ENODEV; } spin_lock_irqsave(&dev->lock, flags); - bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); + len = snprintf(in_buffer, 20, "%lld\n", dev->bbu); spin_unlock_irqrestore(&dev->lock, flags); - - if (*ppos < bytes_read) { - if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos)) - retval = -EFAULT; - else { - retval = bytes_read - *ppos; - *ppos += bytes_read; - } - } - -exit: mutex_unlock(&dev->io_mutex); - return retval; + + return simple_read_from_buffer(buffer, count, ppos, in_buffer, len); } static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)