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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct usb_serial_driver *driver;
|
||||
|
@ -73,18 +64,10 @@ static int usb_serial_device_probe(struct device *dev)
|
|||
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;
|
||||
tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
|
||||
if (IS_ERR(tty_dev)) {
|
||||
retval = PTR_ERR(tty_dev);
|
||||
device_remove_file(dev, &dev_attr_port_number);
|
||||
if (driver->port_remove)
|
||||
driver->port_remove(port);
|
||||
goto exit_with_autopm;
|
||||
|
@ -123,8 +106,6 @@ static int usb_serial_device_remove(struct device *dev)
|
|||
minor = port->minor;
|
||||
tty_unregister_device(usb_serial_tty_driver, minor);
|
||||
|
||||
device_remove_file(&port->dev, &dev_attr_port_number);
|
||||
|
||||
driver = port->serial->type;
|
||||
if (driver->port_remove)
|
||||
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);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.carrier_raised = serial_port_carrier_raised,
|
||||
.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.bus = &usb_serial_bus_type;
|
||||
port->dev.release = &usb_serial_port_release;
|
||||
port->dev.groups = usb_serial_port_groups;
|
||||
device_initialize(&port->dev);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue