lkml.org 
[lkml]   [2022]   [May]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 019/158] rtc: fix use-after-free on device removal
    Date
    From: Vincent Whitchurch <vincent.whitchurch@axis.com>

    [ Upstream commit c8fa17d9f08a448184f03d352145099b5beb618e ]

    If the irqwork is still scheduled or running while the RTC device is
    removed, a use-after-free occurs in rtc_timer_do_work(). Cleanup the
    timerqueue and ensure the work is stopped to fix this.

    BUG: KASAN: use-after-free in mutex_lock+0x94/0x110
    Write of size 8 at addr ffffff801d846338 by task kworker/3:1/41

    Workqueue: events rtc_timer_do_work
    Call trace:
    mutex_lock+0x94/0x110
    rtc_timer_do_work+0xec/0x630
    process_one_work+0x5fc/0x1344
    ...

    Allocated by task 551:
    kmem_cache_alloc_trace+0x384/0x6e0
    devm_rtc_allocate_device+0xf0/0x574
    devm_rtc_device_register+0x2c/0x12c
    ...

    Freed by task 572:
    kfree+0x114/0x4d0
    rtc_device_release+0x64/0x80
    device_release+0x8c/0x1f4
    kobject_put+0x1c4/0x4b0
    put_device+0x20/0x30
    devm_rtc_release_device+0x1c/0x30
    devm_action_release+0x54/0x90
    release_nodes+0x124/0x310
    devres_release_group+0x170/0x240
    i2c_device_remove+0xd8/0x314
    ...

    Last potentially related work creation:
    insert_work+0x5c/0x330
    queue_work_on+0xcc/0x154
    rtc_set_time+0x188/0x5bc
    rtc_dev_ioctl+0x2ac/0xbd0
    ...

    Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
    Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
    Link: https://lore.kernel.org/r/20211210160951.7718-1-vincent.whitchurch@axis.com
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/rtc/class.c | 9 +++++++++
    1 file changed, 9 insertions(+)

    diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
    index 4b460c61f1d8..40d504dac1a9 100644
    --- a/drivers/rtc/class.c
    +++ b/drivers/rtc/class.c
    @@ -26,6 +26,15 @@ struct class *rtc_class;
    static void rtc_device_release(struct device *dev)
    {
    struct rtc_device *rtc = to_rtc_device(dev);
    + struct timerqueue_head *head = &rtc->timerqueue;
    + struct timerqueue_node *node;
    +
    + mutex_lock(&rtc->ops_lock);
    + while ((node = timerqueue_getnext(head)))
    + timerqueue_del(head, node);
    + mutex_unlock(&rtc->ops_lock);
    +
    + cancel_work_sync(&rtc->irqwork);

    ida_simple_remove(&rtc_ida, rtc->id);
    mutex_destroy(&rtc->ops_lock);
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-05-23 19:49    [W:4.196 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site