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>
This commit is contained in:
parent
ca4383a394
commit
2deb96b5d4
@ -38,15 +38,6 @@ static int usb_serial_device_match(struct device *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t port_number_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct usb_serial_port *port = to_usb_serial_port(dev);
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", port->port_number);
|
|
||||||
}
|
|
||||||
static DEVICE_ATTR_RO(port_number);
|
|
||||||
|
|
||||||
static int usb_serial_device_probe(struct device *dev)
|
static int usb_serial_device_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
struct usb_serial_driver *driver;
|
struct usb_serial_driver *driver;
|
||||||
@ -73,18 +64,10 @@ static int usb_serial_device_probe(struct device *dev)
|
|||||||
goto exit_with_autopm;
|
goto exit_with_autopm;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = device_create_file(dev, &dev_attr_port_number);
|
|
||||||
if (retval) {
|
|
||||||
if (driver->port_remove)
|
|
||||||
driver->port_remove(port);
|
|
||||||
goto exit_with_autopm;
|
|
||||||
}
|
|
||||||
|
|
||||||
minor = port->minor;
|
minor = port->minor;
|
||||||
tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
|
tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
|
||||||
if (IS_ERR(tty_dev)) {
|
if (IS_ERR(tty_dev)) {
|
||||||
retval = PTR_ERR(tty_dev);
|
retval = PTR_ERR(tty_dev);
|
||||||
device_remove_file(dev, &dev_attr_port_number);
|
|
||||||
if (driver->port_remove)
|
if (driver->port_remove)
|
||||||
driver->port_remove(port);
|
driver->port_remove(port);
|
||||||
goto exit_with_autopm;
|
goto exit_with_autopm;
|
||||||
@ -123,8 +106,6 @@ static int usb_serial_device_remove(struct device *dev)
|
|||||||
minor = port->minor;
|
minor = port->minor;
|
||||||
tty_unregister_device(usb_serial_tty_driver, minor);
|
tty_unregister_device(usb_serial_tty_driver, minor);
|
||||||
|
|
||||||
device_remove_file(&port->dev, &dev_attr_port_number);
|
|
||||||
|
|
||||||
driver = port->serial->type;
|
driver = port->serial->type;
|
||||||
if (driver->port_remove)
|
if (driver->port_remove)
|
||||||
retval = driver->port_remove(port);
|
retval = driver->port_remove(port);
|
||||||
|
@ -687,6 +687,21 @@ static void serial_port_dtr_rts(struct tty_port *port, int on)
|
|||||||
drv->dtr_rts(p, on);
|
drv->dtr_rts(p, on);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t port_number_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = to_usb_serial_port(dev);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u\n", port->port_number);
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RO(port_number);
|
||||||
|
|
||||||
|
static struct attribute *usb_serial_port_attrs[] = {
|
||||||
|
&dev_attr_port_number.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
ATTRIBUTE_GROUPS(usb_serial_port);
|
||||||
|
|
||||||
static const struct tty_port_operations serial_port_ops = {
|
static const struct tty_port_operations serial_port_ops = {
|
||||||
.carrier_raised = serial_port_carrier_raised,
|
.carrier_raised = serial_port_carrier_raised,
|
||||||
.dtr_rts = serial_port_dtr_rts,
|
.dtr_rts = serial_port_dtr_rts,
|
||||||
@ -902,6 +917,7 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|||||||
port->dev.driver = NULL;
|
port->dev.driver = NULL;
|
||||||
port->dev.bus = &usb_serial_bus_type;
|
port->dev.bus = &usb_serial_bus_type;
|
||||||
port->dev.release = &usb_serial_port_release;
|
port->dev.release = &usb_serial_port_release;
|
||||||
|
port->dev.groups = usb_serial_port_groups;
|
||||||
device_initialize(&port->dev);
|
device_initialize(&port->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user