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

USB: serial: fix port attribute-creation race

Fix attribute-creation race with userspace by using the port device
groups field to create the port attributes.

Also use %u when printing the port number, which is unsigned, even
though we do not currently support more than 128 ports per device.

Reported-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Johan Hovold <johan@kernel.org>
Acked-by: Greg Kroah-Hartman <greg@kroah.com>

+16 -19
-19
drivers/usb/serial/bus.c
··· 38 38 return 0; 39 39 } 40 40 41 - static ssize_t port_number_show(struct device *dev, 42 - struct device_attribute *attr, char *buf) 43 - { 44 - struct usb_serial_port *port = to_usb_serial_port(dev); 45 - 46 - return sprintf(buf, "%d\n", port->port_number); 47 - } 48 - static DEVICE_ATTR_RO(port_number); 49 - 50 41 static int usb_serial_device_probe(struct device *dev) 51 42 { 52 43 struct usb_serial_driver *driver; ··· 64 73 goto exit_with_autopm; 65 74 } 66 75 67 - retval = device_create_file(dev, &dev_attr_port_number); 68 - if (retval) { 69 - if (driver->port_remove) 70 - driver->port_remove(port); 71 - goto exit_with_autopm; 72 - } 73 - 74 76 minor = port->minor; 75 77 tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); 76 78 if (IS_ERR(tty_dev)) { 77 79 retval = PTR_ERR(tty_dev); 78 - device_remove_file(dev, &dev_attr_port_number); 79 80 if (driver->port_remove) 80 81 driver->port_remove(port); 81 82 goto exit_with_autopm; ··· 105 122 106 123 minor = port->minor; 107 124 tty_unregister_device(usb_serial_tty_driver, minor); 108 - 109 - device_remove_file(&port->dev, &dev_attr_port_number); 110 125 111 126 driver = port->serial->type; 112 127 if (driver->port_remove)
+16
drivers/usb/serial/usb-serial.c
··· 687 687 drv->dtr_rts(p, on); 688 688 } 689 689 690 + static ssize_t port_number_show(struct device *dev, 691 + struct device_attribute *attr, char *buf) 692 + { 693 + struct usb_serial_port *port = to_usb_serial_port(dev); 694 + 695 + return sprintf(buf, "%u\n", port->port_number); 696 + } 697 + static DEVICE_ATTR_RO(port_number); 698 + 699 + static struct attribute *usb_serial_port_attrs[] = { 700 + &dev_attr_port_number.attr, 701 + NULL 702 + }; 703 + ATTRIBUTE_GROUPS(usb_serial_port); 704 + 690 705 static const struct tty_port_operations serial_port_ops = { 691 706 .carrier_raised = serial_port_carrier_raised, 692 707 .dtr_rts = serial_port_dtr_rts, ··· 917 902 port->dev.driver = NULL; 918 903 port->dev.bus = &usb_serial_bus_type; 919 904 port->dev.release = &usb_serial_port_release; 905 + port->dev.groups = usb_serial_port_groups; 920 906 device_initialize(&port->dev); 921 907 } 922 908