diff options
| author | Martin Fuzzey <mfuzzey@parkeon.com> | 2015-02-19 09:17:44 -0500 |
|---|---|---|
| committer | Jonathan Cameron <jic23@kernel.org> | 2015-03-14 14:54:14 -0400 |
| commit | c1b03ab5e886760bdd38c9c7a27af149046ffe01 (patch) | |
| tree | ad8d671b87c667e8eeb4e6ae97811132cecfddbe | |
| parent | af5e1a68318e2ed2de22fc2d7a02f2882abe073c (diff) | |
iio: core: Fix double free.
When an error occurred during event registration memory was freed twice
resulting in kernel memory corruption and a crash in unrelated code.
The problem was caused by
iio_device_unregister_eventset()
iio_device_unregister_sysfs()
being called twice, once on the error path and then
again via iio_dev_release().
Fix this by making these two functions idempotent so they
may be called multiple times.
The problem was observed before applying
78b33216 iio:core: Handle error when mask type is not separate
Signed-off-by: Martin Fuzzey <mfuzzey@parkeon.com>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
| -rw-r--r-- | drivers/iio/industrialio-core.c | 5 | ||||
| -rw-r--r-- | drivers/iio/industrialio-event.c | 1 |
2 files changed, 4 insertions, 2 deletions
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index aaba9d3d980e..4df97f650e44 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c | |||
| @@ -847,8 +847,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, | |||
| 847 | * @attr_list: List of IIO device attributes | 847 | * @attr_list: List of IIO device attributes |
| 848 | * | 848 | * |
| 849 | * This function frees the memory allocated for each of the IIO device | 849 | * This function frees the memory allocated for each of the IIO device |
| 850 | * attributes in the list. Note: if you want to reuse the list after calling | 850 | * attributes in the list. |
| 851 | * this function you have to reinitialize it using INIT_LIST_HEAD(). | ||
| 852 | */ | 851 | */ |
| 853 | void iio_free_chan_devattr_list(struct list_head *attr_list) | 852 | void iio_free_chan_devattr_list(struct list_head *attr_list) |
| 854 | { | 853 | { |
| @@ -856,6 +855,7 @@ void iio_free_chan_devattr_list(struct list_head *attr_list) | |||
| 856 | 855 | ||
| 857 | list_for_each_entry_safe(p, n, attr_list, l) { | 856 | list_for_each_entry_safe(p, n, attr_list, l) { |
| 858 | kfree(p->dev_attr.attr.name); | 857 | kfree(p->dev_attr.attr.name); |
| 858 | list_del(&p->l); | ||
| 859 | kfree(p); | 859 | kfree(p); |
| 860 | } | 860 | } |
| 861 | } | 861 | } |
| @@ -936,6 +936,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) | |||
| 936 | 936 | ||
| 937 | iio_free_chan_devattr_list(&indio_dev->channel_attr_list); | 937 | iio_free_chan_devattr_list(&indio_dev->channel_attr_list); |
| 938 | kfree(indio_dev->chan_attr_group.attrs); | 938 | kfree(indio_dev->chan_attr_group.attrs); |
| 939 | indio_dev->chan_attr_group.attrs = NULL; | ||
| 939 | } | 940 | } |
| 940 | 941 | ||
| 941 | static void iio_dev_release(struct device *device) | 942 | static void iio_dev_release(struct device *device) |
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index a4b397048f71..a99692ba91bc 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c | |||
| @@ -500,6 +500,7 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) | |||
| 500 | error_free_setup_event_lines: | 500 | error_free_setup_event_lines: |
| 501 | iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); | 501 | iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); |
| 502 | kfree(indio_dev->event_interface); | 502 | kfree(indio_dev->event_interface); |
| 503 | indio_dev->event_interface = NULL; | ||
| 503 | return ret; | 504 | return ret; |
| 504 | } | 505 | } |
| 505 | 506 | ||
