--- /dev/null
+From stable+bounces-183317-greg=kroah.com@vger.kernel.org Fri Oct 3 21:03:05 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Oct 2025 15:02:57 -0400
+Subject: media: i2c: tc358743: Fix use-after-free bugs caused by orphan timer in probe
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251003190257.3301728-1-sashal@kernel.org>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+[ Upstream commit 79d10f4f21a92e459b2276a77be62c59c1502c9d ]
+
+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: stable@vger.kernel.org
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+[ replaced del_timer() instead of timer_delete() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/i2c/tc358743.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/i2c/tc358743.c
++++ b/drivers/media/i2c/tc358743.c
+@@ -2201,10 +2201,10 @@ static int tc358743_probe(struct i2c_cli
+ err_work_queues:
+ cec_unregister_adapter(state->cec_adap);
+ if (!state->i2c_client->irq) {
+- del_timer(&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);
--- /dev/null
+From stable+bounces-183331-greg=kroah.com@vger.kernel.org Fri Oct 3 22:55:00 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Oct 2025 16:54:47 -0400
+Subject: media: tuner: xc5000: Fix use-after-free in xc5000_release
+To: stable@vger.kernel.org
+Cc: Duoming Zhou <duoming@zju.edu.cn>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251003205447.3385896-2-sashal@kernel.org>
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+[ Upstream commit 40b7a19f321e65789612ebaca966472055dab48c ]
+
+The original code uses cancel_delayed_work() in xc5000_release(), which
+does not guarantee that the delayed work item timer_sleep has fully
+completed if it was already running. This leads to use-after-free scenarios
+where xc5000_release() may free the xc5000_priv while timer_sleep is still
+active and attempts to dereference the xc5000_priv.
+
+A typical race condition is illustrated below:
+
+CPU 0 (release thread) | CPU 1 (delayed work callback)
+xc5000_release() | xc5000_do_timer_sleep()
+ cancel_delayed_work() |
+ hybrid_tuner_release_state(priv) |
+ kfree(priv) |
+ | priv = container_of() // UAF
+
+Replace cancel_delayed_work() with cancel_delayed_work_sync() to ensure
+that the timer_sleep is properly canceled before the xc5000_priv memory
+is deallocated.
+
+A deadlock concern was considered: xc5000_release() is called in a process
+context and is not holding any locks that the timer_sleep work item might
+also need. Therefore, the use of the _sync() variant is safe here.
+
+This bug was initially identified through static analysis.
+
+Fixes: f7a27ff1fb77 ("[media] xc5000: delay tuner sleep to 5 seconds")
+Cc: stable@vger.kernel.org
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+[hverkuil: fix typo in Subject: tunner -> tuner]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/tuners/xc5000.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/tuners/xc5000.c
++++ b/drivers/media/tuners/xc5000.c
+@@ -1304,7 +1304,7 @@ static void xc5000_release(struct dvb_fr
+ mutex_lock(&xc5000_list_mutex);
+
+ if (priv) {
+- cancel_delayed_work(&priv->timer_sleep);
++ cancel_delayed_work_sync(&priv->timer_sleep);
+ hybrid_tuner_release_state(priv);
+ }
+
--- /dev/null
+From stable+bounces-183330-greg=kroah.com@vger.kernel.org Fri Oct 3 22:54:57 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Oct 2025 16:54:46 -0400
+Subject: media: tunner: xc5000: Refactor firmware load
+To: stable@vger.kernel.org
+Cc: Ricardo Ribalda <ribalda@chromium.org>, Shuah Khan <shuah.kh@samsung.com>, Hans Verkuil <hverkuil-cisco@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251003205447.3385896-1-sashal@kernel.org>
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 8e1f5da59dd4a1966f859639860b803a7e8b8bfb ]
+
+Make sure the firmware is released when we leave
+xc_load_fw_and_init_tuner()
+
+This change makes smatch happy:
+drivers/media/tuners/xc5000.c:1213 xc_load_fw_and_init_tuner() warn: 'fw' from request_firmware() not released on lines: 1213.
+
+Cc: Shuah Khan <shuah.kh@samsung.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 40b7a19f321e ("media: tuner: xc5000: Fix use-after-free in xc5000_release")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/tuners/xc5000.c | 41 ++++++++++++++++++-----------------------
+ 1 file changed, 18 insertions(+), 23 deletions(-)
+
+--- a/drivers/media/tuners/xc5000.c
++++ b/drivers/media/tuners/xc5000.c
+@@ -58,7 +58,7 @@ struct xc5000_priv {
+ struct dvb_frontend *fe;
+ struct delayed_work timer_sleep;
+
+- const struct firmware *firmware;
++ bool inited;
+ };
+
+ /* Misc Defines */
+@@ -1110,23 +1110,19 @@ static int xc_load_fw_and_init_tuner(str
+ if (!force && xc5000_is_firmware_loaded(fe) == 0)
+ return 0;
+
+- if (!priv->firmware) {
+- ret = request_firmware(&fw, desired_fw->name,
+- priv->i2c_props.adap->dev.parent);
+- if (ret) {
+- pr_err("xc5000: Upload failed. rc %d\n", ret);
+- return ret;
+- }
+- dprintk(1, "firmware read %zu bytes.\n", fw->size);
+-
+- if (fw->size != desired_fw->size) {
+- pr_err("xc5000: Firmware file with incorrect size\n");
+- release_firmware(fw);
+- return -EINVAL;
+- }
+- priv->firmware = fw;
+- } else
+- fw = priv->firmware;
++ ret = request_firmware(&fw, desired_fw->name,
++ priv->i2c_props.adap->dev.parent);
++ if (ret) {
++ pr_err("xc5000: Upload failed. rc %d\n", ret);
++ return ret;
++ }
++ dprintk(1, "firmware read %zu bytes.\n", fw->size);
++
++ if (fw->size != desired_fw->size) {
++ pr_err("xc5000: Firmware file with incorrect size\n");
++ release_firmware(fw);
++ return -EINVAL;
++ }
+
+ /* Try up to 5 times to load firmware */
+ for (i = 0; i < 5; i++) {
+@@ -1204,6 +1200,7 @@ static int xc_load_fw_and_init_tuner(str
+ }
+
+ err:
++ release_firmware(fw);
+ if (!ret)
+ printk(KERN_INFO "xc5000: Firmware %s loaded and running.\n",
+ desired_fw->name);
+@@ -1274,7 +1271,7 @@ static int xc5000_resume(struct dvb_fron
+
+ /* suspended before firmware is loaded.
+ Avoid firmware load in resume path. */
+- if (!priv->firmware)
++ if (!priv->inited)
+ return 0;
+
+ return xc5000_set_params(fe);
+@@ -1293,6 +1290,8 @@ static int xc5000_init(struct dvb_fronte
+ if (debug)
+ xc_debug_dump(priv);
+
++ priv->inited = true;
++
+ return 0;
+ }
+
+@@ -1306,10 +1305,6 @@ static void xc5000_release(struct dvb_fr
+
+ if (priv) {
+ cancel_delayed_work(&priv->timer_sleep);
+- if (priv->firmware) {
+- release_firmware(priv->firmware);
+- priv->firmware = NULL;
+- }
+ hybrid_tuner_release_state(priv);
+ }
+