staging:iio:dummy: Fix potential NULL pointer dereference
If the config contains CONFIG_IIO_BUFFER=y and CONFIG_IIO_SIMPLE_DUMMY_BUFFER=n iio_simple_dummy_configure_buffer() is stubbed out and iio_buffer_register() is not. As a result we try to register a buffer which has not been configured. This will causes a NULL pointer deref in iio_buffer_register. To solve this issue move the iio_buffer_register() call to iio_simple_dummy_configure_buffer(), so it will only be called if iio_simple_dummy_configure_buffer() has been called. Reported-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
parent
e60fea794e
commit
3fff227436
|
@ -445,26 +445,20 @@ static int __devinit iio_dummy_probe(int index)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_free_device;
|
goto error_free_device;
|
||||||
|
|
||||||
/* Configure buffered capture support. */
|
/*
|
||||||
ret = iio_simple_dummy_configure_buffer(indio_dev);
|
* Configure buffered capture support and register the channels with the
|
||||||
|
* buffer, but avoid the output channel being registered by reducing the
|
||||||
|
* number of channels by 1.
|
||||||
|
*/
|
||||||
|
ret = iio_simple_dummy_configure_buffer(indio_dev, iio_dummy_channels, 5);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_unregister_events;
|
goto error_unregister_events;
|
||||||
|
|
||||||
/*
|
ret = iio_device_register(indio_dev);
|
||||||
* Register the channels with the buffer, but avoid the output
|
|
||||||
* channel being registered by reducing the number of channels by 1.
|
|
||||||
*/
|
|
||||||
ret = iio_buffer_register(indio_dev, iio_dummy_channels, 5);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_unconfigure_buffer;
|
goto error_unconfigure_buffer;
|
||||||
|
|
||||||
ret = iio_device_register(indio_dev);
|
|
||||||
if (ret < 0)
|
|
||||||
goto error_unregister_buffer;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
error_unregister_buffer:
|
|
||||||
iio_buffer_unregister(indio_dev);
|
|
||||||
error_unconfigure_buffer:
|
error_unconfigure_buffer:
|
||||||
iio_simple_dummy_unconfigure_buffer(indio_dev);
|
iio_simple_dummy_unconfigure_buffer(indio_dev);
|
||||||
error_unregister_events:
|
error_unregister_events:
|
||||||
|
@ -499,7 +493,6 @@ static int iio_dummy_remove(int index)
|
||||||
/* Device specific code to power down etc */
|
/* Device specific code to power down etc */
|
||||||
|
|
||||||
/* Buffered capture related cleanup */
|
/* Buffered capture related cleanup */
|
||||||
iio_buffer_unregister(indio_dev);
|
|
||||||
iio_simple_dummy_unconfigure_buffer(indio_dev);
|
iio_simple_dummy_unconfigure_buffer(indio_dev);
|
||||||
|
|
||||||
ret = iio_simple_dummy_events_unregister(indio_dev);
|
ret = iio_simple_dummy_events_unregister(indio_dev);
|
||||||
|
@ -530,6 +523,7 @@ static __init int iio_dummy_init(void)
|
||||||
instances = 1;
|
instances = 1;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fake a bus */
|
/* Fake a bus */
|
||||||
iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs),
|
iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
|
@ -95,10 +95,12 @@ enum iio_simple_dummy_scan_elements {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER
|
#ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER
|
||||||
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev);
|
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev,
|
||||||
|
const struct iio_chan_spec *channels, unsigned int num_channels);
|
||||||
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev);
|
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev);
|
||||||
#else
|
#else
|
||||||
static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
|
static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev,
|
||||||
|
const struct iio_chan_spec *channels, unsigned int num_channels)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -126,7 +126,8 @@ static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = {
|
||||||
.predisable = &iio_triggered_buffer_predisable,
|
.predisable = &iio_triggered_buffer_predisable,
|
||||||
};
|
};
|
||||||
|
|
||||||
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
|
int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev,
|
||||||
|
const struct iio_chan_spec *channels, unsigned int num_channels)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct iio_buffer *buffer;
|
struct iio_buffer *buffer;
|
||||||
|
@ -182,8 +183,15 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
|
||||||
* driven by a trigger.
|
* driven by a trigger.
|
||||||
*/
|
*/
|
||||||
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
|
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
|
||||||
|
|
||||||
|
ret = iio_buffer_register(indio_dev, channels, num_channels);
|
||||||
|
if (ret)
|
||||||
|
goto error_dealloc_pollfunc;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_dealloc_pollfunc:
|
||||||
|
iio_dealloc_pollfunc(indio_dev->pollfunc);
|
||||||
error_free_buffer:
|
error_free_buffer:
|
||||||
iio_kfifo_free(indio_dev->buffer);
|
iio_kfifo_free(indio_dev->buffer);
|
||||||
error_ret:
|
error_ret:
|
||||||
|
@ -197,6 +205,7 @@ error_ret:
|
||||||
*/
|
*/
|
||||||
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev)
|
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
|
iio_buffer_unregister(indio_dev);
|
||||||
iio_dealloc_pollfunc(indio_dev->pollfunc);
|
iio_dealloc_pollfunc(indio_dev->pollfunc);
|
||||||
iio_kfifo_free(indio_dev->buffer);
|
iio_kfifo_free(indio_dev->buffer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue