Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932288AbbFPIkV (ORCPT ); Tue, 16 Jun 2015 04:40:21 -0400 Received: from mail.kernel.org ([198.145.29.136]:54035 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756360AbbFPIii (ORCPT ); Tue, 16 Jun 2015 04:38:38 -0400 From: lizf@kernel.org To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Oliver Neukum , Greg Kroah-Hartman , Zefan Li Subject: [PATCH 3.4 016/172] cdc-acm: add sanity checks Date: Tue, 16 Jun 2015 16:34:30 +0800 Message-Id: <1434443826-4929-16-git-send-email-lizf@kernel.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1434443587-4599-1-git-send-email-lizf@kernel.org> References: <1434443587-4599-1-git-send-email-lizf@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3144 Lines: 99 From: Oliver Neukum 3.4.108-rc1 review patch. If anyone has any objections, please let me know. ------------------ commit 7e860a6e7aa62b337a61110430cd633db5b0d2dd upstream. Check the special CDC headers for a plausible minimum length. Another big operating systems ignores such garbage. Signed-off-by: Oliver Neukum Reviewed-by: Adam Lee Tested-by: Adam Lee Signed-off-by: Greg Kroah-Hartman [lizf: Backported to 3.4: adjust context] Signed-off-by: Zefan Li --- drivers/usb/class/cdc-acm.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 0532577..57877a9 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1008,6 +1008,7 @@ static int acm_probe(struct usb_interface *intf, unsigned long quirks; int num_rx_buf; int i; + unsigned int elength = 0; int combined_interfaces = 0; /* normal quirks */ @@ -1047,9 +1048,12 @@ static int acm_probe(struct usb_interface *intf, dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; } + elength = buffer[0]; switch (buffer[2]) { case USB_CDC_UNION_TYPE: /* we've found it */ + if (elength < sizeof(struct usb_cdc_union_desc)) + goto next_desc; if (union_header) { dev_err(&intf->dev, "More than one " "union descriptor, skipping ...\n"); @@ -1058,31 +1062,38 @@ static int acm_probe(struct usb_interface *intf, union_header = (struct usb_cdc_union_desc *)buffer; break; case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/ + if (elength < sizeof(struct usb_cdc_country_functional_desc)) + goto next_desc; cfd = (struct usb_cdc_country_functional_desc *)buffer; break; case USB_CDC_HEADER_TYPE: /* maybe check version */ break; /* for now we ignore it */ case USB_CDC_ACM_TYPE: + if (elength < 4) + goto next_desc; ac_management_function = buffer[3]; break; case USB_CDC_CALL_MANAGEMENT_TYPE: + if (elength < 5) + goto next_desc; call_management_function = buffer[3]; call_interface_num = buffer[4]; if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); break; default: - /* there are LOTS more CDC descriptors that + /* + * there are LOTS more CDC descriptors that * could legitimately be found here. */ dev_dbg(&intf->dev, "Ignoring descriptor: " - "type %02x, length %d\n", - buffer[2], buffer[0]); + "type %02x, length %ud\n", + buffer[2], elength); break; } next_desc: - buflen -= buffer[0]; - buffer += buffer[0]; + buflen -= elength; + buffer += elength; } if (!union_header) { -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/