]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
e244f615057760e538a9cce40ab090aa5c0122d8
[thirdparty/kernel/stable-queue.git] /
1 From 609366e7a06d035990df78f1562291c3bf0d4a12 Mon Sep 17 00:00:00 2001
2 From: Kaixin Wang <kxwang23@m.fudan.edu.cn>
3 Date: Wed, 11 Sep 2024 23:35:44 +0800
4 Subject: i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master Driver Due to Race Condition
5
6 From: Kaixin Wang <kxwang23@m.fudan.edu.cn>
7
8 commit 609366e7a06d035990df78f1562291c3bf0d4a12 upstream.
9
10 In the cdns_i3c_master_probe function, &master->hj_work is bound with
11 cdns_i3c_master_hj. And cdns_i3c_master_interrupt can call
12 cnds_i3c_master_demux_ibis function to start the work.
13
14 If we remove the module which will call cdns_i3c_master_remove to
15 make cleanup, it will free master->base through i3c_master_unregister
16 while the work mentioned above will be used. The sequence of operations
17 that may lead to a UAF bug is as follows:
18
19 CPU0 CPU1
20
21 | cdns_i3c_master_hj
22 cdns_i3c_master_remove |
23 i3c_master_unregister(&master->base) |
24 device_unregister(&master->dev) |
25 device_release |
26 //free master->base |
27 | i3c_master_do_daa(&master->base)
28 | //use master->base
29
30 Fix it by ensuring that the work is canceled before proceeding with
31 the cleanup in cdns_i3c_master_remove.
32
33 Signed-off-by: Kaixin Wang <kxwang23@m.fudan.edu.cn>
34 Link: https://lore.kernel.org/r/20240911153544.848398-1-kxwang23@m.fudan.edu.cn
35 Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
36 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
37 ---
38 drivers/i3c/master/i3c-master-cdns.c | 1 +
39 1 file changed, 1 insertion(+)
40
41 --- a/drivers/i3c/master/i3c-master-cdns.c
42 +++ b/drivers/i3c/master/i3c-master-cdns.c
43 @@ -1667,6 +1667,7 @@ static int cdns_i3c_master_remove(struct
44 {
45 struct cdns_i3c_master *master = platform_get_drvdata(pdev);
46
47 + cancel_work_sync(&master->hj_work);
48 i3c_master_unregister(&master->base);
49
50 clk_disable_unprepare(master->sysclk);