diff mbox series

ntb: ntb_hw_switchtec: Fix use after free vulnerability in switchtec_ntb_remove due to race condition

Message ID 20240909172007.1863-1-kxwang23@m.fudan.edu.cn (mailing list archive)
State Handled Elsewhere
Delegated to: Krzysztof Wilczyński
Headers show
Series ntb: ntb_hw_switchtec: Fix use after free vulnerability in switchtec_ntb_remove due to race condition | expand

Commit Message

Kaixin Wang Sept. 9, 2024, 5:20 p.m. UTC
In the switchtec_ntb_add function, it can call switchtec_ntb_init_sndev
function, then &sndev->check_link_status_work is bound with
check_link_status_work. switchtec_ntb_link_notification may be called
to start the work.

If we remove the module which will call switchtec_ntb_remove to make
cleanup, it will free sndev through kfree(sndev), while the work
mentioned above will be used. The sequence of operations that may lead
to a UAF bug is as follows:

CPU0                                 CPU1

                        | check_link_status_work
switchtec_ntb_remove    |
kfree(sndev);           |
                        | if (sndev->link_force_down)
                        | // use sndev

Fix it by ensuring that the work is canceled before proceeding with
the cleanup in switchtec_ntb_remove.

Signed-off-by: Kaixin Wang <kxwang23@m.fudan.edu.cn>
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Logan Gunthorpe Sept. 9, 2024, 6:17 p.m. UTC | #1
On 2024-09-09 11:20, Kaixin Wang wrote:
> In the switchtec_ntb_add function, it can call switchtec_ntb_init_sndev
> function, then &sndev->check_link_status_work is bound with
> check_link_status_work. switchtec_ntb_link_notification may be called
> to start the work.
> 
> If we remove the module which will call switchtec_ntb_remove to make
> cleanup, it will free sndev through kfree(sndev), while the work
> mentioned above will be used. The sequence of operations that may lead
> to a UAF bug is as follows:
> 
> CPU0                                 CPU1
> 
>                         | check_link_status_work
> switchtec_ntb_remove    |
> kfree(sndev);           |
>                         | if (sndev->link_force_down)
>                         | // use sndev
> 
> Fix it by ensuring that the work is canceled before proceeding with
> the cleanup in switchtec_ntb_remove.

Thank you, this looks good to me.

Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Kaixin Wang Sept. 12, 2024, 4:47 p.m. UTC | #2
At 2024-09-10 02:17:57, "Logan Gunthorpe" <logang@deltatee.com> wrote:
>
>
>On 2024-09-09 11:20, Kaixin Wang wrote:
>> In the switchtec_ntb_add function, it can call switchtec_ntb_init_sndev
>> function, then &sndev->check_link_status_work is bound with
>> check_link_status_work. switchtec_ntb_link_notification may be called
>> to start the work.
>> 
>> If we remove the module which will call switchtec_ntb_remove to make
>> cleanup, it will free sndev through kfree(sndev), while the work
>> mentioned above will be used. The sequence of operations that may lead
>> to a UAF bug is as follows:
>> 
>> CPU0                                 CPU1
>> 
>>                         | check_link_status_work
>> switchtec_ntb_remove    |
>> kfree(sndev);           |
>>                         | if (sndev->link_force_down)
>>                         | // use sndev
>> 
>> Fix it by ensuring that the work is canceled before proceeding with
>> the cleanup in switchtec_ntb_remove.
>
>Thank you, this looks good to me.
>
>Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
>

Thanks for the review!

Best regards,
Kaixin Wang
diff mbox series

Patch

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 31946387badf..ad1786be2554 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1554,6 +1554,7 @@  static void switchtec_ntb_remove(struct device *dev)
 	switchtec_ntb_deinit_db_msg_irq(sndev);
 	switchtec_ntb_deinit_shared_mw(sndev);
 	switchtec_ntb_deinit_crosslink(sndev);
+	cancel_work_sync(&sndev->check_link_status_work);
 	kfree(sndev);
 	dev_info(dev, "ntb device unregistered\n");
 }