From 8846b1dbfd2146b145d73ba31a4caa4a4789aefb Mon Sep 17 00:00:00 2001 From: Hui Peng Date: Wed, 12 Dec 2018 12:42:24 +0100 Subject: USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data commit 5146f95df782b0ac61abde36567e718692725c89 upstream. 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. Reported-by: Hui Peng Reported-by: Mathias Payer Signed-off-by: Hui Peng Signed-off-by: Mathias Payer Reviewed-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/hso.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/net/usb') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 111d907e0c11..79cede19e0c4 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2825,6 +2825,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; @@ -2895,10 +2901,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 */ -- cgit v1.2.3 From f8e3d1b1014009c223793813cbc00a05706c908f Mon Sep 17 00:00:00 2001 From: James Hughes Date: Wed, 19 Apr 2017 11:13:40 +0100 Subject: smsc95xx: Use skb_cow_head to deal with cloned skbs commit e9156cd26a495a18706e796f02a81fee41ec14f4 upstream. The driver was failing to check that the SKB wasn't cloned before adding checksum data. Replace existing handling to extend/copy the header buffer with skb_cow_head. Signed-off-by: James Hughes Acked-by: Eric Dumazet Acked-by: Woojung Huh Signed-off-by: David S. Miller Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/smsc95xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/usb') diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 7cee7777d13f..b6b8aec73b28 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1838,13 +1838,13 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, /* We do not advertise SG, so skbs should be already linearized */ BUG_ON(skb_shinfo(skb)->nr_frags); - if (skb_headroom(skb) < overhead) { - struct sk_buff *skb2 = skb_copy_expand(skb, - overhead, 0, flags); + /* Make writable and expand header space by overhead if required */ + if (skb_cow_head(skb, overhead)) { + /* Must deallocate here as returning NULL to indicate error + * means the skb won't be deallocated in the caller. + */ dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return NULL; + return NULL; } if (csum) { -- cgit v1.2.3 From 4307a871ce5778ff1f994ad24b3c3ec97efeaf16 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 19 Apr 2017 09:59:25 -0700 Subject: ch9200: use skb_cow_head() to deal with cloned skbs commit 6bc6895bdd6744e0136eaa4a11fbdb20a7db4e40 upstream. We need to ensure there is enough headroom to push extra header, but we also need to check if we are allowed to change headers. skb_cow_head() is the proper helper to deal with this. Fixes: 4a476bd6d1d9 ("usbnet: New driver for QinHeng CH9200 devices") Signed-off-by: Eric Dumazet Cc: James Hughes Cc: Matthew Garrett Signed-off-by: David S. Miller Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/ch9200.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/net/usb') diff --git a/drivers/net/usb/ch9200.c b/drivers/net/usb/ch9200.c index 5e151e6a3e09..3c7715ea40c1 100644 --- a/drivers/net/usb/ch9200.c +++ b/drivers/net/usb/ch9200.c @@ -255,14 +255,9 @@ static struct sk_buff *ch9200_tx_fixup(struct usbnet *dev, struct sk_buff *skb, tx_overhead = 0x40; len = skb->len; - if (skb_headroom(skb) < tx_overhead) { - struct sk_buff *skb2; - - skb2 = skb_copy_expand(skb, tx_overhead, 0, flags); + if (skb_cow_head(skb, tx_overhead)) { dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return NULL; + return NULL; } __skb_push(skb, tx_overhead); -- cgit v1.2.3 From 49cf68d70f47d951c9053d769d3976d9e1be1a25 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 19 Apr 2017 09:59:26 -0700 Subject: kaweth: use skb_cow_head() to deal with cloned skbs commit 39fba7835aacda65284a86e611774cbba71dac20 upstream. We can use skb_cow_head() to properly deal with clones, especially the ones coming from TCP stack that allow their head being modified. This avoids a copy. Signed-off-by: Eric Dumazet Cc: James Hughes Signed-off-by: David S. Miller Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/kaweth.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/net/usb') diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index cd93220c9b45..a628db738b8a 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -812,18 +812,12 @@ static netdev_tx_t kaweth_start_xmit(struct sk_buff *skb, } /* We now decide whether we can put our special header into the sk_buff */ - if (skb_cloned(skb) || skb_headroom(skb) < 2) { - /* no such luck - we make our own */ - struct sk_buff *copied_skb; - copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC); - dev_kfree_skb_irq(skb); - skb = copied_skb; - if (!copied_skb) { - kaweth->stats.tx_errors++; - netif_start_queue(net); - spin_unlock_irq(&kaweth->device_lock); - return NETDEV_TX_OK; - } + if (skb_cow_head(skb, 2)) { + kaweth->stats.tx_errors++; + netif_start_queue(net); + spin_unlock_irq(&kaweth->device_lock); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } private_header = (__le16 *)__skb_push(skb, 2); -- cgit v1.2.3