From accb884b32e82f943340688c9cd30290531e73e0 Mon Sep 17 00:00:00 2001 From: Chao Bi Date: Wed, 12 Feb 2014 21:27:25 +0200 Subject: [PATCH] mei: set client's read_cb to NULL when flow control fails In mei_cl_read_start(), if it fails to send flow control request, it will release "cl->read_cb" but forget to set pointer to NULL, leaving "cl->read_cb" still pointing to random memory, next time this client is operated like mei_release(), it has chance to refer to this wrong pointer. Fixes: PANIC at kfree in mei_release() [228781.826904] Call Trace: [228781.829737] [] ? mei_cl_unlink+0x48/0xa0 [228781.835283] [] mei_io_cb_free+0x17/0x30 [228781.840733] [] mei_release+0xa8/0x180 [228781.845989] [] ? __fsnotify_parent+0xa0/0xf0 [228781.851925] [] __fput+0xd9/0x200 [228781.856696] [] ____fput+0xd/0x10 [228781.861467] [] task_work_run+0x81/0xb0 [228781.866821] [] do_exit+0x283/0xa00 [228781.871786] [] ? kprobe_flush_task+0x66/0xc0 [228781.877722] [] ? __dequeue_signal+0x18/0x1a0 [228781.883657] [] ? dequeue_signal+0x32/0x190 [228781.889397] [] do_group_exit+0x34/0xa0 [228781.894750] [] get_signal_to_deliver+0x206/0x610 [228781.901075] [] do_signal+0x38/0x100 [228781.906136] [] ? mei_read+0x42c/0x4e0 [228781.911393] [] ? wake_up_bit+0x30/0x30 [228781.916745] [] ? mei_poll+0x120/0x120 [228781.922001] [] ? vfs_read+0x89/0x160 [228781.927158] [] ? mei_poll+0x120/0x120 [228781.932414] [] ? fget_light+0x44/0xe0 [228781.937670] [] ? SyS_read+0x68/0x80 [228781.942730] [] do_notify_resume+0x55/0x70 [228781.948376] [] work_notifysig+0x29/0x30 [228781.953827] [] ? bad_area+0x5/0x3e Cc: stable # 3.9+ Signed-off-by: Chao Bi Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 9b809cfc2899..89a557972d1b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -666,7 +666,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) goto err; cb->fop_type = MEI_FOP_READ; - cl->read_cb = cb; if (dev->hbuf_is_ready) { dev->hbuf_is_ready = false; if (mei_hbm_cl_flow_control_req(dev, cl)) { @@ -678,6 +677,9 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) } else { list_add_tail(&cb->list, &dev->ctrl_wr_list.list); } + + cl->read_cb = cb; + return rets; err: mei_io_cb_free(cb);