forked from mirrors/linux
		
	staging:iio:core set the iio_dev.info pointer to null on unregister under lock.
This prevents use of provider callbacks after it has been unregistered. Note that all code using this that can be called from a consumer *must* check the pointer before using and hold the info_exist_lock throughout the usage of the callbacks in info. Signed-off-by: Jonathan Cameron <jic23@kernel.org> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									08cd9ef4ec
								
							
						
					
					
						commit
						ac917a8111
					
				
					 2 changed files with 6 additions and 0 deletions
				
			
		| 
						 | 
					@ -310,6 +310,7 @@ struct iio_buffer_setup_ops {
 | 
				
			||||||
 * @chan_attr_group:	[INTERN] group for all attrs in base directory
 | 
					 * @chan_attr_group:	[INTERN] group for all attrs in base directory
 | 
				
			||||||
 * @name:		[DRIVER] name of the device.
 | 
					 * @name:		[DRIVER] name of the device.
 | 
				
			||||||
 * @info:		[DRIVER] callbacks and constant info from driver
 | 
					 * @info:		[DRIVER] callbacks and constant info from driver
 | 
				
			||||||
 | 
					 * @info_exist_lock:	[INTERN] lock to prevent use during removal
 | 
				
			||||||
 * @chrdev:		[INTERN] associated character device
 | 
					 * @chrdev:		[INTERN] associated character device
 | 
				
			||||||
 * @groups:		[INTERN] attribute groups
 | 
					 * @groups:		[INTERN] attribute groups
 | 
				
			||||||
 * @groupcounter:	[INTERN] index of next attribute group
 | 
					 * @groupcounter:	[INTERN] index of next attribute group
 | 
				
			||||||
| 
						 | 
					@ -340,6 +341,7 @@ struct iio_dev {
 | 
				
			||||||
	struct attribute_group		chan_attr_group;
 | 
						struct attribute_group		chan_attr_group;
 | 
				
			||||||
	const char			*name;
 | 
						const char			*name;
 | 
				
			||||||
	const struct iio_info		*info;
 | 
						const struct iio_info		*info;
 | 
				
			||||||
 | 
						struct mutex			info_exist_lock;
 | 
				
			||||||
	const struct iio_buffer_setup_ops	*setup_ops;
 | 
						const struct iio_buffer_setup_ops	*setup_ops;
 | 
				
			||||||
	struct cdev			chrdev;
 | 
						struct cdev			chrdev;
 | 
				
			||||||
#define IIO_MAX_GROUPS 6
 | 
					#define IIO_MAX_GROUPS 6
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -594,6 +594,7 @@ struct iio_dev *iio_allocate_device(int sizeof_priv)
 | 
				
			||||||
		device_initialize(&dev->dev);
 | 
							device_initialize(&dev->dev);
 | 
				
			||||||
		dev_set_drvdata(&dev->dev, (void *)dev);
 | 
							dev_set_drvdata(&dev->dev, (void *)dev);
 | 
				
			||||||
		mutex_init(&dev->mlock);
 | 
							mutex_init(&dev->mlock);
 | 
				
			||||||
 | 
							mutex_init(&dev->info_exist_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
 | 
							dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
 | 
				
			||||||
		if (dev->id < 0) {
 | 
							if (dev->id < 0) {
 | 
				
			||||||
| 
						 | 
					@ -718,6 +719,9 @@ EXPORT_SYMBOL(iio_device_register);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void iio_device_unregister(struct iio_dev *indio_dev)
 | 
					void iio_device_unregister(struct iio_dev *indio_dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						mutex_lock(&indio_dev->info_exist_lock);
 | 
				
			||||||
 | 
						indio_dev->info = NULL;
 | 
				
			||||||
 | 
						mutex_unlock(&indio_dev->info_exist_lock);
 | 
				
			||||||
	device_unregister(&indio_dev->dev);
 | 
						device_unregister(&indio_dev->dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(iio_device_unregister);
 | 
					EXPORT_SYMBOL(iio_device_unregister);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue