USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
Subsystems (5)
Greg KH
maintainerPATCH 1/1 USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
From: Hui Peng <[email protected]>
The function hso_probe reads if_num from the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read in hso_probe or hso_get_config_data. Added a length check for both locations and updated hso_probe to bail on error.
--- drivers/net/usb/hso.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
drivers/net/usb/hso.c +16 -2
@@ -2807,6 +2807,12 @@ static int hso_get_config_data(struct usb_interface *interface)return -EIO ; } +/* check if we have a valid interface */ +if (if_num >16 ) { +kfree (config_data); +return -EINVAL ; + } +switch (config_data[if_num]) {case 0x0 : result =0 ;
@@ -2877,10 +2883,18 @@ static int hso_probe(struct usb_interface *interface,/* Get the interface/port specification from either driver_info or from * the device itself */ -if (id->driver_info) +if (id->driver_info) { +/* if_num is controlled by the device, driver_info is a 0 terminated +* array. Make sure, the access is in bounds! */ +for (i =0 ; i <= if_num; ++i) +if (((u32 *)(id->driver_info))[i] ==0 ) + goto exit; port_spec = ((u32 *)(id->driver_info))[if_num]; -else + }else { port_spec =hso_get_config_data (interface); +if (IS_ERR_VALUE ((long )port_spec)) + goto exit; + }/* Check if we need to switch to alt interfaces prior to port * configuration */
David Miller
maintainerFrom: Greg KH <[email protected]>
Date: Sun, 9 Dec 2018 17:32:45 +0100
drivers/net/usb/hso.c static int hso_probe(struct usb_interface *interface, · line 2896
Quoted 4 lines
drivers/net/usb/hso.c +3
-0+ }else { port_spec =hso_get_config_data (interface); +if (IS_ERR_VALUE ((long )port_spec)) + goto exit;
'port_spec' is an 'int', it makes no sense to cast it 3 times all the way back to 'int' to figure out if it is a negative error value or not. (--> long --> void * --> int)
Hi David,
Quoted 9 lines
drivers/net/usb/hso.c static int hso_probe(struct usb_interface *interface, · line 2896
Quoted 4 lines
drivers/net/usb/hso.c +3
-0+ }else { port_spec =hso_get_config_data (interface); +if (IS_ERR_VALUE ((long )port_spec)) + goto exit;'
port_spec' is an 'int', it makes no sense to cast it 3 times all the way back to 'int' to figure out if it is a negative error value or not. (--> long --> void * --> int)
Passing an int to the macro results in a compiler warning. One option would be to test for the individual errors (instead of using the macro) with the drawback that future extensions that return different errors may be missed. Another alternative is to test for negative values with the drawback that this bypasses the existing test macros.
Also, the macro does not cast back to int but unsigned long:
https://elixir.bootlin.com/linux/v4.20-rc5/source/include/linux/err.h#L22
#define IS_ERR_VALUE(x) unlikely((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO)
The cast chain is int -> long -> void * -> unsigned long.
What other check would you propose?
Thanks,
Mathias
David Miller
maintainerRe: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
From: Mathias Payer <[email protected]>
Date: Sun, 9 Dec 2018 21:02:25 +0100
Quoted 5 lines
Passing an int to the macro results in a compiler warning. One option would be to test for the individual errors (instead of using the macro) with the drawback that future extensions that return different errors may be missed. Another alternative is to test for negative values with the drawback that this bypasses the existing test macros.
The whole kernel is full of situations where an int is returned and if it's negative it's an error. Why is this location so different?
Just check < 0 and be done with it.
Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
Quoted 4 lines
The whole kernel is full of situations where an int is returned and if it's negative it's an error. Why is this location so different?
Just check < 0 and be done with it.
OK, whatever you prefer.
I've attached the updated patch. (Greg, please add your Signed-off-by).
Best,
Mathias
commit 78e4a03cd3ae7c8f5957a170bc054fd89d7600f1
Author: Mathias Payer <[email protected]> Date: Sun Dec 9 16:45:09 2018 +0100
NET: hso: Fix OOB memory access in hso_probe/hso_get_config_data in hso.c
From: Hui Peng <[email protected]>
The function hso_probe reads if_num from the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read in hso_probe or hso_get_config_data. Added a length check for both locations and updated hso_probe to bail on error.
This issue has been assigned CVE-2018-19985.
drivers/net/usb/hso.c +16 -2
@@ -2807,6 +2807,12 @@ static int hso_get_config_data(struct usb_interface *interface)return -EIO ; } +/* check if we have a valid interface */ +if (if_num >16 ) { +kfree (config_data); +return -EINVAL ; + } +switch (config_data[if_num]) {case 0x0 : result =0 ;
@@ -2877,10 +2883,18 @@ static int hso_probe(struct usb_interface *interface,/* Get the interface/port specification from either driver_info or from * the device itself */ -if (id->driver_info) +if (id->driver_info) { +/* if_num is controlled by the device, driver_info is a 0 terminated +* array. Make sure, the access is in bounds! */ +for (i =0 ; i <= if_num; ++i) +if (((u32 *)(id->driver_info))[i] ==0 ) + goto exit; port_spec = ((u32 *)(id->driver_info))[if_num]; -else + }else { port_spec =hso_get_config_data (interface); +if (port_spec <0 ) + goto exit; + }/* Check if we need to switch to alt interfaces prior to port * configuration */
David Miller
maintainerRe: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
From: Mathias Payer <[email protected]>
Date: Sun, 9 Dec 2018 21:17:58 +0100
Quoted 1 line
I've attached the updated patch. (Greg, please add your Signed-off-by).
Patches should be posted inline, not as attachments as per process/submitting-patches.rst
Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
Quoted 7 lines · David Miller
From: Mathias Payer <[email protected]>
Date: Sun, 9 Dec 2018 21:17:58 +0100Quoted 1 line
I've attached the updated patch. (Greg, please add your Signed-off-by).
Patches should be posted inline, not as attachments as per
process/submitting-patches.rst
Sorry! And thanks for your patience, we're going through a learning experience. Inlined updated patch with the discussed changes:
commit 78e4a03cd3ae7c8f5957a170bc054fd89d7600f1
Author: Mathias Payer <[email protected]> Date: Sun Dec 9 16:45:09 2018 +0100
NET: hso: Fix OOB memory access in hso_probe/hso_get_config_data in hso.c
From: Hui Peng <[email protected]>
The function hso_probe reads if_num from the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read in hso_probe or hso_get_config_data. Added a length check for both locations and updated hso_probe to bail on error.
This issue has been assigned CVE-2018-19985.
result = 0;
@@ -2877,10 +2883,18 @@ static int hso_probe(struct usb_interface *interface,
/* Get the interface/port specification from either driver_info or from
* the device itself */
- if (id->driver_info)
+ if (id->driver_info) {
+ /* if_num is controlled by the device, driver_info is a 0 terminated
+ * array. Make sure, the access is in bounds! */
+ for (i = 0; i <= if_num; ++i)
+ if (((u32 *)(id->driver_info))[i] == 0)
+ goto exit;
port_spec = ((u32 *)(id->driver_info))[if_num];
- else
+ } else {
port_spec = hso_get_config_data(interface);
+ if (port_spec < 0)
+ goto exit;
+ }
/* Check if we need to switch to alt interfaces prior to port
* configuration */
drivers/net/usb/hso.c +0 -0
@@ -2807,6 +2807,12 @@ static int hso_get_config_data(struct usb_interface
*interface)
return -EIO;
}
+ /* check if we have a valid interface */
+ if (if_num > 16) {
+ kfree(config_data);
+ return -EINVAL;
+ }
+
switch (config_data[if_num]) {
case 0x0:
Greg KH
maintainerRe: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data,Re: [PATCH] USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
In reply to Mathias PayerQuoted 6 lines · Mathias Payer
Quoted 4 lines
The whole kernel is full of situations where an int is returned and if it's negative it's an error. Why is this location so different?
Just check < 0 and be done with it.
OK, whatever you prefer.
My fault, I was tired and suggested the other way...
Quoted 1 line
I've attached the updated patch. (Greg, please add your Signed-off-by).
Patches can't be attached, I'll fix this up and resend, thanks.
greg k-h
FYI, this issue has been assigned CVE-2018-19985.
Thanks,
Mathias
Quoted 55 lines · Greg KH
From: Hui Peng <[email protected]>
The function
hso_probereadsif_numfrom the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read inhso_probeorhso_get_config_data. Added a length check for both locations and updatedhso_probeto bail on error.Reported-by Hui Peng <[email protected]>Reported-by Mathias Payer <[email protected]>Signed-off-by Hui Peng <[email protected]>Signed-off-by Mathias Payer <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- drivers/net/usb/hso.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)drivers/net/usb/hso.c +16
-2@@ -2807,6 +2807,12 @@ static int hso_get_config_data(struct usb_interface *interface)return -EIO ; } +/* check if we have a valid interface */ +if (if_num >16 ) { +kfree (config_data); +return -EINVAL ; + } +switch (config_data[if_num]) {case 0x0 : result =0 ;@@ -2877,10 +2883,18 @@ static int hso_probe(struct usb_interface *interface,/* Get the interface/port specification from either driver_info or from * the device itself */ -if (id->driver_info) +if (id->driver_info) { +/* if_num is controlled by the device, driver_info is a 0 terminated +* array. Make sure, the access is in bounds! */ +for (i =0 ; i <= if_num; ++i) +if (((u32 *)(id->driver_info))[i] ==0 ) + goto exit; port_spec = ((u32 *)(id->driver_info))[if_num]; -else + }else { port_spec =hso_get_config_data (interface); +if (IS_ERR_VALUE ((long )port_spec)) + goto exit; + }/* Check if we need to switch to alt interfaces prior to port * configuration */
Greg KH
maintainerPATCH v2 1/1 USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
In reply to Greg KHFrom: Hui Peng <[email protected]>
The function hso_probe reads if_num from the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read in hso_probe or hso_get_config_data. Added a length check for both locations and updated hso_probe to bail on error.
This issue has been assigned CVE-2018-19985.
---
v2: fixed error check to just be < 0
Added CVE to changelog text
drivers/net/usb/hso.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
drivers/net/usb/hso.c +16 -2
@@ -2807,6 +2807,12 @@ static int hso_get_config_data(struct usb_interface *interface)return -EIO ; } +/* check if we have a valid interface */ +if (if_num >16 ) { +kfree (config_data); +return -EINVAL ; + } +switch (config_data[if_num]) {case 0x0 : result =0 ;
@@ -2877,10 +2883,18 @@ static int hso_probe(struct usb_interface *interface,/* Get the interface/port specification from either driver_info or from * the device itself */ -if (id->driver_info) +if (id->driver_info) { +/* if_num is controlled by the device, driver_info is a 0 terminated +* array. Make sure, the access is in bounds! */ +for (i =0 ; i <= if_num; ++i) +if (((u32 *)(id->driver_info))[i] ==0 ) + goto exit; port_spec = ((u32 *)(id->driver_info))[if_num]; -else + }else { port_spec =hso_get_config_data (interface); +if (port_spec <0 ) + goto exit; + }/* Check if we need to switch to alt interfaces prior to port * configuration */
Quoted 6 lines · Greg KH
From: Hui Peng <[email protected]>
The function
hso_probereadsif_numfrom the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read inhso_probeorhso_get_config_data. Added a length check for both locations and updatedhso_probeto bail on error.
The function hso_probe reads if_num from the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read in hso_probe or hso_get_config_data.
Add a length check for both locations and update hso_probe to bail on error.
Quoted 7 lines
This issue has been assigned CVE-2018-19985.
Reported-by Hui Peng <[email protected]>Reported-by Mathias Payer <[email protected]>Signed-off-by Hui Peng <[email protected]>Signed-off-by Mathias Payer <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>
Sebastian
Greg KH
maintainerQuoted 17 lines · Sebastian Andrzej Siewior
Quoted 6 lines · Greg KH
From: Hui Peng <[email protected]>
The function
hso_probereadsif_numfrom the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read inhso_probeorhso_get_config_data. Added a length check for both locations and updatedhso_probeto bail on error.The function
hso_probereadsif_numfrom the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read inhso_probeorhso_get_config_data.Add a length check for both locations and update
hso_probeto bail on error.Quoted 2 lines
This issue has been assigned CVE-2018-19985.
Quoted 7 lines
Quoted 5 lines
Reported-by Hui Peng <[email protected]>Reported-by Mathias Payer <[email protected]>Signed-off-by Hui Peng <[email protected]>Signed-off-by Mathias Payer <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>Reviewed-by Sebastian Andrzej Siewior <[email protected]>
Thanks, will update the changelog and add resend.
greg k-h
Greg KH
maintainerPATCH v3 1/1 USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data
In reply to Greg KHFrom: Hui Peng <[email protected]>
The function hso_probe reads if_num from the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read in hso_probe or hso_get_config_data.
Add a length check for both locations and updated hso_probe to bail on error.
This issue has been assigned CVE-2018-19985.
---
v3: redid the changelog text based on review comments from Sebastian
v2: fixed error check to just be < 0
Added CVE to changelog text
drivers/net/usb/hso.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
drivers/net/usb/hso.c +16 -2
@@ -2807,6 +2807,12 @@ static int hso_get_config_data(struct usb_interface *interface)return -EIO ; } +/* check if we have a valid interface */ +if (if_num >16 ) { +kfree (config_data); +return -EINVAL ; + } +switch (config_data[if_num]) {case 0x0 : result =0 ;
@@ -2877,10 +2883,18 @@ static int hso_probe(struct usb_interface *interface,/* Get the interface/port specification from either driver_info or from * the device itself */ -if (id->driver_info) +if (id->driver_info) { +/* if_num is controlled by the device, driver_info is a 0 terminated +* array. Make sure, the access is in bounds! */ +for (i =0 ; i <= if_num; ++i) +if (((u32 *)(id->driver_info))[i] ==0 ) + goto exit; port_spec = ((u32 *)(id->driver_info))[if_num]; -else + }else { port_spec =hso_get_config_data (interface); +if (port_spec <0 ) + goto exit; + }/* Check if we need to switch to alt interfaces prior to port * configuration */
David Miller
maintainerFrom: Greg KH <[email protected]>
Date: Wed, 12 Dec 2018 12:42:24 +0100
Quoted 9 lines
From: Hui Peng <[email protected]>
The function
hso_probereadsif_numfrom the USB device (as an u8) and uses it without a length check to index an array, resulting in an OOB memory read inhso_probeorhso_get_config_data.Add a length check for both locations and updated
hso_probeto bail on error.
Quoted 8 lines
This issue has been assigned CVE-2018-19985.
Reported-by Hui Peng <[email protected]>Reported-by Mathias Payer <[email protected]>Signed-off-by Hui Peng <[email protected]>Signed-off-by Mathias Payer <[email protected]>Reviewed-by Sebastian Andrzej Siewior <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>
Applied and queued up for -stable, thanks Greg.