Skip to content

Commit 34f1166

Browse files
Tomas Winklergregkh
authored andcommitted
mei: bus: need to unlink client before freeing
In case a client fails to connect in mei_cldev_enable(), the caller won't call the mei_cldev_disable leaving the client in a linked stated. Upon driver unload the client structure will be freed in mei_cl_bus_dev_release(), leaving a stale pointer on a fail_list. This will eventually end up in crash during power down flow in mei_cl_set_disonnected(). RIP: mei_cl_set_disconnected+0x5/0x260[mei] Call trace: mei_cl_all_disconnect+0x22/0x30 mei_reset+0x194/0x250 __synchronize_hardirq+0x43/0x50 _cond_resched+0x15/0x30 mei_me_intr_clear+0x20/0x100 mei_stop+0x76/0xb0 mei_me_shutdown+0x3f/0x80 pci_device_shutdown+0x34/0x60 kernel_restart+0x0e/0x30 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=200455 Fixes: 'c110cdb17148 ("mei: bus: make a client pointer always available")' Cc: <[email protected]> 4.10+ Tested-by: Georg Müller <[email protected]> Signed-off-by: Tomas Winkler <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 69bf531 commit 34f1166

File tree

1 file changed

+4
-5
lines changed

1 file changed

+4
-5
lines changed

drivers/misc/mei/bus.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -521,17 +521,15 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
521521

522522
cl = cldev->cl;
523523

524+
mutex_lock(&bus->device_lock);
524525
if (cl->state == MEI_FILE_UNINITIALIZED) {
525-
mutex_lock(&bus->device_lock);
526526
ret = mei_cl_link(cl);
527-
mutex_unlock(&bus->device_lock);
528527
if (ret)
529-
return ret;
528+
goto out;
530529
/* update pointers */
531530
cl->cldev = cldev;
532531
}
533532

534-
mutex_lock(&bus->device_lock);
535533
if (mei_cl_is_connected(cl)) {
536534
ret = 0;
537535
goto out;
@@ -875,12 +873,13 @@ static void mei_cl_bus_dev_release(struct device *dev)
875873

876874
mei_me_cl_put(cldev->me_cl);
877875
mei_dev_bus_put(cldev->bus);
876+
mei_cl_unlink(cldev->cl);
878877
kfree(cldev->cl);
879878
kfree(cldev);
880879
}
881880

882881
static const struct device_type mei_cl_device_type = {
883-
.release = mei_cl_bus_dev_release,
882+
.release = mei_cl_bus_dev_release,
884883
};
885884

886885
/**

0 commit comments

Comments
 (0)