diff options
| author | Johan Hovold <johan@kernel.org> | 2015-02-17 22:34:52 -0500 |
|---|---|---|
| committer | Johan Hovold <johan@kernel.org> | 2015-02-26 11:12:46 -0500 |
| commit | 2deb96b5d4bb20a33bfaf80e30f38f3433653054 (patch) | |
| tree | d02b859829f986671780463141d4d227f991fbf3 | |
| parent | ca4383a3947a83286bc9b9c598a1f55e867871d7 (diff) | |
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>
| -rw-r--r-- | drivers/usb/serial/bus.c | 19 | ||||
| -rw-r--r-- | drivers/usb/serial/usb-serial.c | 16 |
2 files changed, 16 insertions, 19 deletions
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 6f91eb9ae81a..b53a28692226 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
| @@ -38,15 +38,6 @@ static int usb_serial_device_match(struct device *dev, | |||
| 38 | return 0; | 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 | static int usb_serial_device_probe(struct device *dev) | 41 | static int usb_serial_device_probe(struct device *dev) |
| 51 | { | 42 | { |
| 52 | struct usb_serial_driver *driver; | 43 | struct usb_serial_driver *driver; |
| @@ -73,18 +64,10 @@ static int usb_serial_device_probe(struct device *dev) | |||
| 73 | goto exit_with_autopm; | 64 | goto exit_with_autopm; |
| 74 | } | 65 | } |
| 75 | 66 | ||
| 76 | retval = device_create_file(dev, &dev_attr_port_number); | ||
| 77 | if (retval) { | ||
| 78 | if (driver->port_remove) | ||
| 79 | driver->port_remove(port); | ||
| 80 | goto exit_with_autopm; | ||
| 81 | } | ||
| 82 | |||
| 83 | minor = port->minor; | 67 | minor = port->minor; |
| 84 | tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); | 68 | tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); |
| 85 | if (IS_ERR(tty_dev)) { | 69 | if (IS_ERR(tty_dev)) { |
| 86 | retval = PTR_ERR(tty_dev); | 70 | retval = PTR_ERR(tty_dev); |
| 87 | device_remove_file(dev, &dev_attr_port_number); | ||
| 88 | if (driver->port_remove) | 71 | if (driver->port_remove) |
| 89 | driver->port_remove(port); | 72 | driver->port_remove(port); |
| 90 | goto exit_with_autopm; | 73 | goto exit_with_autopm; |
| @@ -123,8 +106,6 @@ static int usb_serial_device_remove(struct device *dev) | |||
| 123 | minor = port->minor; | 106 | minor = port->minor; |
| 124 | tty_unregister_device(usb_serial_tty_driver, minor); | 107 | tty_unregister_device(usb_serial_tty_driver, minor); |
| 125 | 108 | ||
| 126 | device_remove_file(&port->dev, &dev_attr_port_number); | ||
| 127 | |||
| 128 | driver = port->serial->type; | 109 | driver = port->serial->type; |
| 129 | if (driver->port_remove) | 110 | if (driver->port_remove) |
| 130 | retval = driver->port_remove(port); | 111 | retval = driver->port_remove(port); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 19842370a07f..529066bbc7e8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -687,6 +687,21 @@ static void serial_port_dtr_rts(struct tty_port *port, int on) | |||
| 687 | drv->dtr_rts(p, on); | 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 | static const struct tty_port_operations serial_port_ops = { | 705 | static const struct tty_port_operations serial_port_ops = { |
| 691 | .carrier_raised = serial_port_carrier_raised, | 706 | .carrier_raised = serial_port_carrier_raised, |
| 692 | .dtr_rts = serial_port_dtr_rts, | 707 | .dtr_rts = serial_port_dtr_rts, |
| @@ -902,6 +917,7 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
| 902 | port->dev.driver = NULL; | 917 | port->dev.driver = NULL; |
| 903 | port->dev.bus = &usb_serial_bus_type; | 918 | port->dev.bus = &usb_serial_bus_type; |
| 904 | port->dev.release = &usb_serial_port_release; | 919 | port->dev.release = &usb_serial_port_release; |
| 920 | port->dev.groups = usb_serial_port_groups; | ||
| 905 | device_initialize(&port->dev); | 921 | device_initialize(&port->dev); |
| 906 | } | 922 | } |
| 907 | 923 | ||
