summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/loopback.c
diff options
context:
space:
mode:
authorBryan O'Donoghue2015-09-04 17:53:31 +0200
committerGreg Kroah-Hartman2015-09-04 23:50:39 +0200
commitff477d073f2e71a1fa59f86cb44bd9d48674a71b (patch)
tree1d67eeeace9652b867b20bbf633c6c59efec52b1 /drivers/staging/greybus/loopback.c
parentgreybus: es2: update the bulk_ep_set value accepted by map_to_cpor_ep() (diff)
downloadkernel-qcow2-linux-ff477d073f2e71a1fa59f86cb44bd9d48674a71b.tar.gz
kernel-qcow2-linux-ff477d073f2e71a1fa59f86cb44bd9d48674a71b.tar.xz
kernel-qcow2-linux-ff477d073f2e71a1fa59f86cb44bd9d48674a71b.zip
greybus: loopback: make sure to list_del on connection_exit
gb_loopback_connection_exit does a kfree on a data structure associated with a loopback connection but fails to do a corresponding list_del(). On subsequent enumerations this can lead to a NULL pointer dereference. Each list_add in gb_loopback_connection_init() must have a corresponding list_del in gb_loopback_connection_exit(), this patch adds the relevant list_del() and ensures that an appropriate mutex protecting gb_dev.list is held while doing so. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reported-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/loopback.c')
-rw-r--r--drivers/staging/greybus/loopback.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c
index 8dd648cc0796..231d1d4c1104 100644
--- a/drivers/staging/greybus/loopback.c
+++ b/drivers/staging/greybus/loopback.c
@@ -944,18 +944,23 @@ static void gb_loopback_connection_exit(struct gb_connection *connection)
struct gb_loopback *gb = connection->private;
struct kobject *kobj = &connection->bundle->intf->module->dev.kobj;
- gb_dev.count--;
- connection->private = NULL;
if (!IS_ERR_OR_NULL(gb->task))
kthread_stop(gb->task);
+ mutex_lock(&gb_dev.mutex);
+
+ connection->private = NULL;
kfifo_free(&gb->kfifo_lat);
kfifo_free(&gb->kfifo_ts);
if (!gb_dev.count)
sysfs_remove_groups(kobj, loopback_dev_groups);
sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups);
debugfs_remove(gb->file);
+ list_del(&gb->entry);
kfree(gb);
+ gb_dev.count--;
+
+ mutex_unlock(&gb_dev.mutex);
}
static struct gb_protocol loopback_protocol = {