Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: core: Change usb_get_device_descriptor() API

The usb_get_device_descriptor() routine reads the device descriptor
from the udev device and stores it directly in udev->descriptor. This
interface is error prone, because the USB subsystem expects in-memory
copies of a device's descriptors to be immutable once the device has
been initialized.

The interface is changed so that the device descriptor is left in a
kmalloc-ed buffer, not copied into the usb_device structure. A
pointer to the buffer is returned to the caller, who is then
responsible for kfree-ing it. The corresponding changes needed in the
various callers are fairly small.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://lore.kernel.org/r/d0111bb6-56c1-4f90-adf2-6cfe152f6561@rowland.harvard.edu
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
de28e469 85d07c55

+44 -43
+7 -3
drivers/usb/core/hcd.c
··· 983 983 { 984 984 struct device *parent_dev = hcd->self.controller; 985 985 struct usb_device *usb_dev = hcd->self.root_hub; 986 + struct usb_device_descriptor *descr; 986 987 const int devnum = 1; 987 988 int retval; 988 989 ··· 995 994 mutex_lock(&usb_bus_idr_lock); 996 995 997 996 usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); 998 - retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); 999 - if (retval != sizeof usb_dev->descriptor) { 997 + descr = usb_get_device_descriptor(usb_dev); 998 + if (IS_ERR(descr)) { 999 + retval = PTR_ERR(descr); 1000 1000 mutex_unlock(&usb_bus_idr_lock); 1001 1001 dev_dbg (parent_dev, "can't read %s device descriptor %d\n", 1002 1002 dev_name(&usb_dev->dev), retval); 1003 - return (retval < 0) ? retval : -EMSGSIZE; 1003 + return retval; 1004 1004 } 1005 + usb_dev->descriptor = *descr; 1006 + kfree(descr); 1005 1007 1006 1008 if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { 1007 1009 retval = usb_get_bos_descriptor(usb_dev);
+23 -21
drivers/usb/core/hub.c
··· 2694 2694 } 2695 2695 2696 2696 if (usb_dev->wusb) { 2697 - result = usb_get_device_descriptor(usb_dev, sizeof(usb_dev->descriptor)); 2698 - if (result < 0) { 2697 + struct usb_device_descriptor *descr; 2698 + 2699 + descr = usb_get_device_descriptor(usb_dev); 2700 + if (IS_ERR(descr)) { 2701 + result = PTR_ERR(descr); 2699 2702 dev_err(&usb_dev->dev, "can't re-read device descriptor for " 2700 2703 "authorization: %d\n", result); 2701 2704 goto error_device_descriptor; 2702 2705 } 2706 + usb_dev->descriptor = *descr; 2707 + kfree(descr); 2703 2708 } 2704 2709 2705 2710 usb_dev->authorized = 1; ··· 4832 4827 const char *driver_name; 4833 4828 bool do_new_scheme; 4834 4829 int maxp0; 4835 - struct usb_device_descriptor *buf; 4830 + struct usb_device_descriptor *buf, *descr; 4836 4831 4837 4832 buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); 4838 4833 if (!buf) ··· 5074 5069 usb_ep0_reinit(udev); 5075 5070 } 5076 5071 5077 - retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); 5078 - if (retval < (signed)sizeof(udev->descriptor)) { 5072 + descr = usb_get_device_descriptor(udev); 5073 + if (IS_ERR(descr)) { 5074 + retval = PTR_ERR(descr); 5079 5075 if (retval != -ENODEV) 5080 5076 dev_err(&udev->dev, "device descriptor read/all, error %d\n", 5081 5077 retval); 5082 - if (retval >= 0) 5083 - retval = -ENOMSG; 5084 5078 goto fail; 5085 5079 } 5080 + udev->descriptor = *descr; 5081 + kfree(descr); 5086 5082 5087 5083 /* 5088 5084 * Some superspeed devices have finished the link training process ··· 5202 5196 5203 5197 5204 5198 static int descriptors_changed(struct usb_device *udev, 5205 - struct usb_device_descriptor *old_device_descriptor, 5199 + struct usb_device_descriptor *new_device_descriptor, 5206 5200 struct usb_host_bos *old_bos) 5207 5201 { 5208 5202 int changed = 0; ··· 5213 5207 int length; 5214 5208 char *buf; 5215 5209 5216 - if (memcmp(&udev->descriptor, old_device_descriptor, 5217 - sizeof(*old_device_descriptor)) != 0) 5210 + if (memcmp(&udev->descriptor, new_device_descriptor, 5211 + sizeof(*new_device_descriptor)) != 0) 5218 5212 return 1; 5219 5213 5220 5214 if ((old_bos && !udev->bos) || (!old_bos && udev->bos)) ··· 5539 5533 { 5540 5534 struct usb_port *port_dev = hub->ports[port1 - 1]; 5541 5535 struct usb_device *udev = port_dev->child; 5542 - struct usb_device_descriptor descriptor; 5536 + struct usb_device_descriptor *descr; 5543 5537 int status = -ENODEV; 5544 - int retval; 5545 5538 5546 5539 dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus, 5547 5540 portchange, portspeed(hub, portstatus)); ··· 5567 5562 * changed device descriptors before resuscitating the 5568 5563 * device. 5569 5564 */ 5570 - descriptor = udev->descriptor; 5571 - retval = usb_get_device_descriptor(udev, 5572 - sizeof(udev->descriptor)); 5573 - if (retval < 0) { 5565 + descr = usb_get_device_descriptor(udev); 5566 + if (IS_ERR(descr)) { 5574 5567 dev_dbg(&udev->dev, 5575 - "can't read device descriptor %d\n", 5576 - retval); 5568 + "can't read device descriptor %ld\n", 5569 + PTR_ERR(descr)); 5577 5570 } else { 5578 - if (descriptors_changed(udev, &descriptor, 5571 + if (descriptors_changed(udev, descr, 5579 5572 udev->bos)) { 5580 5573 dev_dbg(&udev->dev, 5581 5574 "device descriptor has changed\n"); 5582 - /* for disconnect() calls */ 5583 - udev->descriptor = descriptor; 5584 5575 } else { 5585 5576 status = 0; /* Nothing to do */ 5586 5577 } 5578 + kfree(descr); 5587 5579 } 5588 5580 #ifdef CONFIG_PM 5589 5581 } else if (udev->state == USB_STATE_SUSPENDED &&
+12 -17
drivers/usb/core/message.c
··· 1041 1041 EXPORT_SYMBOL_GPL(usb_cache_string); 1042 1042 1043 1043 /* 1044 - * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) 1045 - * @dev: the device whose device descriptor is being updated 1046 - * @size: how much of the descriptor to read 1044 + * usb_get_device_descriptor - read the device descriptor 1045 + * @udev: the device whose device descriptor should be read 1047 1046 * 1048 1047 * Context: task context, might sleep. 1049 - * 1050 - * Updates the copy of the device descriptor stored in the device structure, 1051 - * which dedicates space for this purpose. 1052 1048 * 1053 1049 * Not exported, only for use by the core. If drivers really want to read 1054 1050 * the device descriptor directly, they can call usb_get_descriptor() with 1055 1051 * type = USB_DT_DEVICE and index = 0. 1056 1052 * 1057 - * This call is synchronous, and may not be used in an interrupt context. 1058 - * 1059 - * Return: The number of bytes received on success, or else the status code 1060 - * returned by the underlying usb_control_msg() call. 1053 + * Returns: a pointer to a dynamically allocated usb_device_descriptor 1054 + * structure (which the caller must deallocate), or an ERR_PTR value. 1061 1055 */ 1062 - int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) 1056 + struct usb_device_descriptor *usb_get_device_descriptor(struct usb_device *udev) 1063 1057 { 1064 1058 struct usb_device_descriptor *desc; 1065 1059 int ret; 1066 1060 1067 - if (size > sizeof(*desc)) 1068 - return -EINVAL; 1069 1061 desc = kmalloc(sizeof(*desc), GFP_NOIO); 1070 1062 if (!desc) 1071 - return -ENOMEM; 1063 + return ERR_PTR(-ENOMEM); 1072 1064 1073 - ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size); 1065 + ret = usb_get_descriptor(udev, USB_DT_DEVICE, 0, desc, sizeof(*desc)); 1066 + if (ret == sizeof(*desc)) 1067 + return desc; 1068 + 1074 1069 if (ret >= 0) 1075 - memcpy(&dev->descriptor, desc, size); 1070 + ret = -EMSGSIZE; 1076 1071 kfree(desc); 1077 - return ret; 1072 + return ERR_PTR(ret); 1078 1073 } 1079 1074 1080 1075 /*
+2 -2
drivers/usb/core/usb.h
··· 43 43 struct usb_endpoint_descriptor *epd); 44 44 extern int usb_remove_device(struct usb_device *udev); 45 45 46 - extern int usb_get_device_descriptor(struct usb_device *dev, 47 - unsigned int size); 46 + extern struct usb_device_descriptor *usb_get_device_descriptor( 47 + struct usb_device *udev); 48 48 extern int usb_set_isoch_delay(struct usb_device *dev); 49 49 extern int usb_get_bos_descriptor(struct usb_device *dev); 50 50 extern void usb_release_bos_descriptor(struct usb_device *dev);