On Wed Sep 17 17:57:42 2025 +0800, Duoming Zhou wrote:
> The state->timer is a cyclic timer that schedules work_i2c_poll and
> delayed_work_enable_hotplug, while rearming itself. Using timer_delete()
> fails to guarantee the timer isn't still running when destroyed, similarly
> cancel_delayed_work() cannot ensure delayed_work_enable_hotplug has
> terminated if already executing. During probe failure after timer
> initialization, these may continue running as orphans and reference the
> already-freed tc358743_state object through tc358743_irq_poll_timer.
> 
> The following is the trace captured by KASAN.
> 
> BUG: KASAN: slab-use-after-free in __run_timer_base.part.0+0x7d7/0x8c0
> Write of size 8 at addr ffff88800ded83c8 by task swapper/1/0
> ...
> Call Trace:
>  <IRQ>
>  dump_stack_lvl+0x55/0x70
>  print_report+0xcf/0x610
>  ? __pfx_sched_balance_find_src_group+0x10/0x10
>  ? __run_timer_base.part.0+0x7d7/0x8c0
>  kasan_report+0xb8/0xf0
>  ? __run_timer_base.part.0+0x7d7/0x8c0
>  __run_timer_base.part.0+0x7d7/0x8c0
>  ? rcu_sched_clock_irq+0xb06/0x27d0
>  ? __pfx___run_timer_base.part.0+0x10/0x10
>  ? try_to_wake_up+0xb15/0x1960
>  ? tmigr_update_events+0x280/0x740
>  ? _raw_spin_lock_irq+0x80/0xe0
>  ? __pfx__raw_spin_lock_irq+0x10/0x10
>  tmigr_handle_remote_up+0x603/0x7e0
>  ? __pfx_tmigr_handle_remote_up+0x10/0x10
>  ? sched_balance_trigger+0x98/0x9f0
>  ? sched_tick+0x221/0x5a0
>  ? _raw_spin_lock_irq+0x80/0xe0
>  ? __pfx__raw_spin_lock_irq+0x10/0x10
>  ? tick_nohz_handler+0x339/0x440
>  ? __pfx_tmigr_handle_remote_up+0x10/0x10
>  __walk_groups.isra.0+0x42/0x150
>  tmigr_handle_remote+0x1f4/0x2e0
>  ? __pfx_tmigr_handle_remote+0x10/0x10
>  ? ktime_get+0x60/0x140
>  ? lapic_next_event+0x11/0x20
>  ? clockevents_program_event+0x1d4/0x2a0
>  ? hrtimer_interrupt+0x322/0x780
>  handle_softirqs+0x16a/0x550
>  irq_exit_rcu+0xaf/0xe0
>  sysvec_apic_timer_interrupt+0x70/0x80
>  </IRQ>
> ...
> 
> Allocated by task 141:
>  kasan_save_stack+0x24/0x50
>  kasan_save_track+0x14/0x30
>  __kasan_kmalloc+0x7f/0x90
>  __kmalloc_node_track_caller_noprof+0x198/0x430
>  devm_kmalloc+0x7b/0x1e0
>  tc358743_probe+0xb7/0x610  i2c_device_probe+0x51d/0x880
>  really_probe+0x1ca/0x5c0
>  __driver_probe_device+0x248/0x310
>  driver_probe_device+0x44/0x120
>  __device_attach_driver+0x174/0x220
>  bus_for_each_drv+0x100/0x190
>  __device_attach+0x206/0x370
>  bus_probe_device+0x123/0x170
>  device_add+0xd25/0x1470
>  i2c_new_client_device+0x7a0/0xcd0
>  do_one_initcall+0x89/0x300
>  do_init_module+0x29d/0x7f0
>  load_module+0x4f48/0x69e0
>  init_module_from_file+0xe4/0x150
>  idempotent_init_module+0x320/0x670
>  __x64_sys_finit_module+0xbd/0x120
>  do_syscall_64+0xac/0x280
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> 
> Freed by task 141:
>  kasan_save_stack+0x24/0x50
>  kasan_save_track+0x14/0x30
>  kasan_save_free_info+0x3a/0x60
>  __kasan_slab_free+0x3f/0x50
>  kfree+0x137/0x370
>  release_nodes+0xa4/0x100
>  devres_release_group+0x1b2/0x380
>  i2c_device_probe+0x694/0x880
>  really_probe+0x1ca/0x5c0
>  __driver_probe_device+0x248/0x310
>  driver_probe_device+0x44/0x120
>  __device_attach_driver+0x174/0x220
>  bus_for_each_drv+0x100/0x190
>  __device_attach+0x206/0x370
>  bus_probe_device+0x123/0x170
>  device_add+0xd25/0x1470
>  i2c_new_client_device+0x7a0/0xcd0
>  do_one_initcall+0x89/0x300
>  do_init_module+0x29d/0x7f0
>  load_module+0x4f48/0x69e0
>  init_module_from_file+0xe4/0x150
>  idempotent_init_module+0x320/0x670
>  __x64_sys_finit_module+0xbd/0x120
>  do_syscall_64+0xac/0x280
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> ...
> 
> Replace timer_delete() with timer_delete_sync() and cancel_delayed_work()
> with cancel_delayed_work_sync() to ensure proper termination of timer and
> work items before resource cleanup.
> 
> This bug was initially identified through static analysis. For reproduction
> and testing, I created a functional emulation of the tc358743 device via a
> kernel module and introduced faults through the debugfs interface.
> 
> Fixes: 869f38ae07f7 ("media: i2c: tc358743: Fix crash in the probe error path 
> when using polling")
> Fixes: d32d98642de6 ("[media] Driver for Toshiba TC358743 HDMI to CSI-2 
> bridge")
> Cc: [email protected]
> Signed-off-by: Duoming Zhou <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/i2c/tc358743.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

---

diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index aa02a5a6ae3e..a0ca19359c43 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -2326,10 +2326,10 @@ static int tc358743_probe(struct i2c_client *client)
 err_work_queues:
        cec_unregister_adapter(state->cec_adap);
        if (!state->i2c_client->irq) {
-               timer_delete(&state->timer);
+               timer_delete_sync(&state->timer);
                flush_work(&state->work_i2c_poll);
        }
-       cancel_delayed_work(&state->delayed_work_enable_hotplug);
+       cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
        mutex_destroy(&state->confctl_mutex);
 err_hdl:
        media_entity_cleanup(&sd->entity);

Reply via email to