mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Avoid usb reset crashes by making tty_io cdevs truly dynamic
Avoid usb reset crashes by making tty_io cdevs truly dynamic Signed-off-by: Richard Watts <rrw@kynesim.co.uk> Reported-by: Duncan Mackintosh <DMackintosh@cbnl.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									458e2c82c5
								
							
						
					
					
						commit
						a3a10ce342
					
				
					 2 changed files with 17 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -3152,9 +3152,12 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
 | 
			
		|||
		unsigned int index, unsigned int count)
 | 
			
		||||
{
 | 
			
		||||
	/* init here, since reused cdevs cause crashes */
 | 
			
		||||
	cdev_init(&driver->cdevs[index], &tty_fops);
 | 
			
		||||
	driver->cdevs[index].owner = driver->owner;
 | 
			
		||||
	return cdev_add(&driver->cdevs[index], dev, count);
 | 
			
		||||
	driver->cdevs[index] = cdev_alloc();
 | 
			
		||||
	if (!driver->cdevs[index])
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	cdev_init(driver->cdevs[index], &tty_fops);
 | 
			
		||||
	driver->cdevs[index]->owner = driver->owner;
 | 
			
		||||
	return cdev_add(driver->cdevs[index], dev, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -3260,8 +3263,10 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
 | 
			
		|||
 | 
			
		||||
error:
 | 
			
		||||
	put_device(dev);
 | 
			
		||||
	if (cdev)
 | 
			
		||||
		cdev_del(&driver->cdevs[index]);
 | 
			
		||||
	if (cdev) {
 | 
			
		||||
		cdev_del(driver->cdevs[index]);
 | 
			
		||||
		driver->cdevs[index] = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	return ERR_PTR(retval);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(tty_register_device_attr);
 | 
			
		||||
| 
						 | 
				
			
			@ -3281,8 +3286,10 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
 | 
			
		|||
{
 | 
			
		||||
	device_destroy(tty_class,
 | 
			
		||||
		MKDEV(driver->major, driver->minor_start) + index);
 | 
			
		||||
	if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC))
 | 
			
		||||
		cdev_del(&driver->cdevs[index]);
 | 
			
		||||
	if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
 | 
			
		||||
		cdev_del(driver->cdevs[index]);
 | 
			
		||||
		driver->cdevs[index] = NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(tty_unregister_device);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3347,6 +3354,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
 | 
			
		|||
	kfree(driver->ports);
 | 
			
		||||
	kfree(driver->ttys);
 | 
			
		||||
	kfree(driver->termios);
 | 
			
		||||
	kfree(driver->cdevs);
 | 
			
		||||
	kfree(driver);
 | 
			
		||||
	return ERR_PTR(err);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3375,7 +3383,7 @@ static void destruct_tty_driver(struct kref *kref)
 | 
			
		|||
		}
 | 
			
		||||
		proc_tty_unregister_driver(driver);
 | 
			
		||||
		if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
 | 
			
		||||
			cdev_del(&driver->cdevs[0]);
 | 
			
		||||
			cdev_del(driver->cdevs[0]);
 | 
			
		||||
	}
 | 
			
		||||
	kfree(driver->cdevs);
 | 
			
		||||
	kfree(driver->ports);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -296,7 +296,7 @@ struct tty_operations {
 | 
			
		|||
struct tty_driver {
 | 
			
		||||
	int	magic;		/* magic number for this structure */
 | 
			
		||||
	struct kref kref;	/* Reference management */
 | 
			
		||||
	struct cdev *cdevs;
 | 
			
		||||
	struct cdev **cdevs;
 | 
			
		||||
	struct module	*owner;
 | 
			
		||||
	const char	*driver_name;
 | 
			
		||||
	const char	*name;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue