]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Oct 2025 10:23:28 +0000 (12:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Oct 2025 10:23:28 +0000 (12:23 +0200)
added patches:
media-i2c-tc358743-fix-use-after-free-bugs-caused-by-orphan-timer-in-probe.patch
media-imon-grab-lock-earlier-in-imon_ir_change_protocol.patch
media-imon-reorganize-serialization.patch
media-rc-add-support-for-another-imon-0xffdc-device.patch
media-rc-fix-races-with-imon_disconnect.patch
media-tuner-xc5000-fix-use-after-free-in-xc5000_release.patch
media-tunner-xc5000-refactor-firmware-load.patch

queue-5.4/media-i2c-tc358743-fix-use-after-free-bugs-caused-by-orphan-timer-in-probe.patch [new file with mode: 0644]
queue-5.4/media-imon-grab-lock-earlier-in-imon_ir_change_protocol.patch [new file with mode: 0644]
queue-5.4/media-imon-reorganize-serialization.patch [new file with mode: 0644]
queue-5.4/media-rc-add-support-for-another-imon-0xffdc-device.patch [new file with mode: 0644]
queue-5.4/media-rc-fix-races-with-imon_disconnect.patch [new file with mode: 0644]
queue-5.4/media-tuner-xc5000-fix-use-after-free-in-xc5000_release.patch [new file with mode: 0644]
queue-5.4/media-tunner-xc5000-refactor-firmware-load.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/media-i2c-tc358743-fix-use-after-free-bugs-caused-by-orphan-timer-in-probe.patch b/queue-5.4/media-i2c-tc358743-fix-use-after-free-bugs-caused-by-orphan-timer-in-probe.patch
new file mode 100644 (file)
index 0000000..a760726
--- /dev/null
@@ -0,0 +1,149 @@
+From stable+bounces-183326-greg=kroah.com@vger.kernel.org Fri Oct  3 22:43:33 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Oct 2025 16:43:23 -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: <20251003204323.3377744-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
+@@ -2200,10 +2200,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);
diff --git a/queue-5.4/media-imon-grab-lock-earlier-in-imon_ir_change_protocol.patch b/queue-5.4/media-imon-grab-lock-earlier-in-imon_ir_change_protocol.patch
new file mode 100644 (file)
index 0000000..11f0eae
--- /dev/null
@@ -0,0 +1,59 @@
+From stable+bounces-183334-greg=kroah.com@vger.kernel.org Fri Oct  3 22:55:48 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Oct 2025 16:55:36 -0400
+Subject: media: imon: grab lock earlier in imon_ir_change_protocol()
+To: stable@vger.kernel.org
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>, Sean Young <sean@mess.org>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251003205537.3386848-3-sashal@kernel.org>
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+[ Upstream commit 7019553ab850ce1d3f0e512e16d14ab153f91c04 ]
+
+Move mutex_trylock() in imon_ir_change_protocol() to the beginning,
+for memcpy() which modifies ictx->usb_tx_buf should be protected by
+ictx->lock.
+
+Also, verify at the beginning of send_packet() that ictx->lock is held
+in case send_packet() is by error called from imon_ir_change_protocol()
+when mutex_trylock() failed due to concurrent requests.
+
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Stable-dep-of: fa0f61cc1d82 ("media: rc: fix races with imon_disconnect()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/rc/imon.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -598,6 +598,8 @@ static int send_packet(struct imon_conte
+       int retval = 0;
+       struct usb_ctrlrequest *control_req = NULL;
++      lockdep_assert_held(&ictx->lock);
++
+       /* Check if we need to use control or interrupt urb */
+       if (!ictx->tx_control) {
+               pipe = usb_sndintpipe(ictx->usbdev_intf0,
+@@ -1126,7 +1128,7 @@ static int imon_ir_change_protocol(struc
+       int retval;
+       struct imon_context *ictx = rc->priv;
+       struct device *dev = ictx->dev;
+-      bool unlock = false;
++      const bool unlock = mutex_trylock(&ictx->lock);
+       unsigned char ir_proto_packet[] = {
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
+@@ -1153,8 +1155,6 @@ static int imon_ir_change_protocol(struc
+       memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
+-      unlock = mutex_trylock(&ictx->lock);
+-
+       retval = send_packet(ictx);
+       if (retval)
+               goto out;
diff --git a/queue-5.4/media-imon-reorganize-serialization.patch b/queue-5.4/media-imon-reorganize-serialization.patch
new file mode 100644 (file)
index 0000000..a54fd88
--- /dev/null
@@ -0,0 +1,343 @@
+From stable+bounces-183333-greg=kroah.com@vger.kernel.org Fri Oct  3 22:55:46 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Oct 2025 16:55:35 -0400
+Subject: media: imon: reorganize serialization
+To: stable@vger.kernel.org
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>, syzbot <syzbot+c558267ad910fc494497@syzkaller.appspotmail.com>, Alan Stern <stern@rowland.harvard.edu>, Sean Young <sean@mess.org>, Mauro Carvalho Chehab <mchehab@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251003205537.3386848-2-sashal@kernel.org>
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+[ Upstream commit db264d4c66c0fe007b5d19fd007707cd0697603d ]
+
+Since usb_register_dev() from imon_init_display() from imon_probe() holds
+minor_rwsem while display_open() which holds driver_lock and ictx->lock is
+called with minor_rwsem held from usb_open(), holding driver_lock or
+ictx->lock when calling usb_register_dev() causes circular locking
+dependency problem.
+
+Since usb_deregister_dev() from imon_disconnect() holds minor_rwsem while
+display_open() which holds driver_lock is called with minor_rwsem held,
+holding driver_lock when calling usb_deregister_dev() also causes circular
+locking dependency problem.
+
+Sean Young explained that the problem is there are imon devices which have
+two usb interfaces, even though it is one device. The probe and disconnect
+function of both usb interfaces can run concurrently.
+
+Alan Stern responded that the driver and USB cores guarantee that when an
+interface is probed, both the interface and its USB device are locked.
+Ditto for when the disconnect callback gets run. So concurrent probing/
+disconnection of multiple interfaces on the same device is not possible.
+
+Therefore, we don't need locks for handling race between imon_probe() and
+imon_disconnect(). But we still need to handle race between display_open()
+/vfd_write()/lcd_write()/display_close() and imon_disconnect(), for
+disconnect event can happen while file descriptors are in use.
+
+Since "struct file"->private_data is set by display_open(), vfd_write()/
+lcd_write()/display_close() can assume that "struct file"->private_data
+is not NULL even after usb_set_intfdata(interface, NULL) was called.
+
+Replace insufficiently held driver_lock with refcount_t based management.
+Add a boolean flag for recording whether imon_disconnect() was already
+called. Use RCU for accessing this boolean flag and refcount_t.
+
+Since the boolean flag for imon_disconnect() is shared, disconnect event
+on either intf0 or intf1 affects both interfaces. But I assume that this
+change does not matter, for usually disconnect event would not happen
+while interfaces are in use.
+
+Link: https://syzkaller.appspot.com/bug?extid=c558267ad910fc494497
+
+Reported-by: syzbot <syzbot+c558267ad910fc494497@syzkaller.appspotmail.com>
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Tested-by: syzbot <syzbot+c558267ad910fc494497@syzkaller.appspotmail.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Stable-dep-of: fa0f61cc1d82 ("media: rc: fix races with imon_disconnect()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/rc/imon.c |   99 ++++++++++++++++++++++--------------------------
+ 1 file changed, 47 insertions(+), 52 deletions(-)
+
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -153,6 +153,24 @@ struct imon_context {
+       const struct imon_usb_dev_descr *dev_descr;
+                                       /* device description with key */
+                                       /* table for front panels */
++      /*
++       * Fields for deferring free_imon_context().
++       *
++       * Since reference to "struct imon_context" is stored into
++       * "struct file"->private_data, we need to remember
++       * how many file descriptors might access this "struct imon_context".
++       */
++      refcount_t users;
++      /*
++       * Use a flag for telling display_open()/vfd_write()/lcd_write() that
++       * imon_disconnect() was already called.
++       */
++      bool disconnected;
++      /*
++       * We need to wait for RCU grace period in order to allow
++       * display_open() to safely check ->disconnected and increment ->users.
++       */
++      struct rcu_head rcu;
+ };
+ #define TOUCH_TIMEOUT (HZ/30)
+@@ -160,18 +178,18 @@ struct imon_context {
+ /* vfd character device file operations */
+ static const struct file_operations vfd_fops = {
+       .owner          = THIS_MODULE,
+-      .open           = &display_open,
+-      .write          = &vfd_write,
+-      .release        = &display_close,
++      .open           = display_open,
++      .write          = vfd_write,
++      .release        = display_close,
+       .llseek         = noop_llseek,
+ };
+ /* lcd character device file operations */
+ static const struct file_operations lcd_fops = {
+       .owner          = THIS_MODULE,
+-      .open           = &display_open,
+-      .write          = &lcd_write,
+-      .release        = &display_close,
++      .open           = display_open,
++      .write          = lcd_write,
++      .release        = display_close,
+       .llseek         = noop_llseek,
+ };
+@@ -439,9 +457,6 @@ static struct usb_driver imon_driver = {
+       .id_table       = imon_usb_id_table,
+ };
+-/* to prevent races between open() and disconnect(), probing, etc */
+-static DEFINE_MUTEX(driver_lock);
+-
+ /* Module bookkeeping bits */
+ MODULE_AUTHOR(MOD_AUTHOR);
+ MODULE_DESCRIPTION(MOD_DESC);
+@@ -481,9 +496,11 @@ static void free_imon_context(struct imo
+       struct device *dev = ictx->dev;
+       usb_free_urb(ictx->tx_urb);
++      WARN_ON(ictx->dev_present_intf0);
+       usb_free_urb(ictx->rx_urb_intf0);
++      WARN_ON(ictx->dev_present_intf1);
+       usb_free_urb(ictx->rx_urb_intf1);
+-      kfree(ictx);
++      kfree_rcu(ictx, rcu);
+       dev_dbg(dev, "%s: iMON context freed\n", __func__);
+ }
+@@ -499,9 +516,6 @@ static int display_open(struct inode *in
+       int subminor;
+       int retval = 0;
+-      /* prevent races with disconnect */
+-      mutex_lock(&driver_lock);
+-
+       subminor = iminor(inode);
+       interface = usb_find_interface(&imon_driver, subminor);
+       if (!interface) {
+@@ -509,13 +523,16 @@ static int display_open(struct inode *in
+               retval = -ENODEV;
+               goto exit;
+       }
+-      ictx = usb_get_intfdata(interface);
+-      if (!ictx) {
++      rcu_read_lock();
++      ictx = usb_get_intfdata(interface);
++      if (!ictx || ictx->disconnected || !refcount_inc_not_zero(&ictx->users)) {
++              rcu_read_unlock();
+               pr_err("no context found for minor %d\n", subminor);
+               retval = -ENODEV;
+               goto exit;
+       }
++      rcu_read_unlock();
+       mutex_lock(&ictx->lock);
+@@ -533,8 +550,10 @@ static int display_open(struct inode *in
+       mutex_unlock(&ictx->lock);
++      if (retval && refcount_dec_and_test(&ictx->users))
++              free_imon_context(ictx);
++
+ exit:
+-      mutex_unlock(&driver_lock);
+       return retval;
+ }
+@@ -544,16 +563,9 @@ exit:
+  */
+ static int display_close(struct inode *inode, struct file *file)
+ {
+-      struct imon_context *ictx = NULL;
++      struct imon_context *ictx = file->private_data;
+       int retval = 0;
+-      ictx = file->private_data;
+-
+-      if (!ictx) {
+-              pr_err("no context for device\n");
+-              return -ENODEV;
+-      }
+-
+       mutex_lock(&ictx->lock);
+       if (!ictx->display_supported) {
+@@ -568,6 +580,8 @@ static int display_close(struct inode *i
+       }
+       mutex_unlock(&ictx->lock);
++      if (refcount_dec_and_test(&ictx->users))
++              free_imon_context(ictx);
+       return retval;
+ }
+@@ -936,15 +950,12 @@ static ssize_t vfd_write(struct file *fi
+       int offset;
+       int seq;
+       int retval = 0;
+-      struct imon_context *ictx;
++      struct imon_context *ictx = file->private_data;
+       static const unsigned char vfd_packet6[] = {
+               0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+-      ictx = file->private_data;
+-      if (!ictx) {
+-              pr_err_ratelimited("no context for device\n");
++      if (ictx->disconnected)
+               return -ENODEV;
+-      }
+       if (mutex_lock_interruptible(&ictx->lock))
+               return -ERESTARTSYS;
+@@ -1021,13 +1032,10 @@ static ssize_t lcd_write(struct file *fi
+                        size_t n_bytes, loff_t *pos)
+ {
+       int retval = 0;
+-      struct imon_context *ictx;
++      struct imon_context *ictx = file->private_data;
+-      ictx = file->private_data;
+-      if (!ictx) {
+-              pr_err_ratelimited("no context for device\n");
++      if (ictx->disconnected)
+               return -ENODEV;
+-      }
+       mutex_lock(&ictx->lock);
+@@ -2402,7 +2410,6 @@ static int imon_probe(struct usb_interfa
+       int ifnum, sysfs_err;
+       int ret = 0;
+       struct imon_context *ictx = NULL;
+-      struct imon_context *first_if_ctx = NULL;
+       u16 vendor, product;
+       usbdev     = usb_get_dev(interface_to_usbdev(interface));
+@@ -2414,17 +2421,12 @@ static int imon_probe(struct usb_interfa
+       dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
+               __func__, vendor, product, ifnum);
+-      /* prevent races probing devices w/multiple interfaces */
+-      mutex_lock(&driver_lock);
+-
+       first_if = usb_ifnum_to_if(usbdev, 0);
+       if (!first_if) {
+               ret = -ENODEV;
+               goto fail;
+       }
+-      first_if_ctx = usb_get_intfdata(first_if);
+-
+       if (ifnum == 0) {
+               ictx = imon_init_intf0(interface, id);
+               if (!ictx) {
+@@ -2432,9 +2434,11 @@ static int imon_probe(struct usb_interfa
+                       ret = -ENODEV;
+                       goto fail;
+               }
++              refcount_set(&ictx->users, 1);
+       } else {
+               /* this is the secondary interface on the device */
++              struct imon_context *first_if_ctx = usb_get_intfdata(first_if);
+               /* fail early if first intf failed to register */
+               if (!first_if_ctx) {
+@@ -2448,14 +2452,13 @@ static int imon_probe(struct usb_interfa
+                       ret = -ENODEV;
+                       goto fail;
+               }
++              refcount_inc(&ictx->users);
+       }
+       usb_set_intfdata(interface, ictx);
+       if (ifnum == 0) {
+-              mutex_lock(&ictx->lock);
+-
+               if (product == 0xffdc && ictx->rf_device) {
+                       sysfs_err = sysfs_create_group(&interface->dev.kobj,
+                                                      &imon_rf_attr_group);
+@@ -2466,21 +2469,17 @@ static int imon_probe(struct usb_interfa
+               if (ictx->display_supported)
+                       imon_init_display(ictx, interface);
+-
+-              mutex_unlock(&ictx->lock);
+       }
+       dev_info(dev, "iMON device (%04x:%04x, intf%d) on usb<%d:%d> initialized\n",
+                vendor, product, ifnum,
+                usbdev->bus->busnum, usbdev->devnum);
+-      mutex_unlock(&driver_lock);
+       usb_put_dev(usbdev);
+       return 0;
+ fail:
+-      mutex_unlock(&driver_lock);
+       usb_put_dev(usbdev);
+       dev_err(dev, "unable to register, err %d\n", ret);
+@@ -2496,10 +2495,8 @@ static void imon_disconnect(struct usb_i
+       struct device *dev;
+       int ifnum;
+-      /* prevent races with multi-interface device probing and display_open */
+-      mutex_lock(&driver_lock);
+-
+       ictx = usb_get_intfdata(interface);
++      ictx->disconnected = true;
+       dev = ictx->dev;
+       ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
+@@ -2540,11 +2537,9 @@ static void imon_disconnect(struct usb_i
+               }
+       }
+-      if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1)
++      if (refcount_dec_and_test(&ictx->users))
+               free_imon_context(ictx);
+-      mutex_unlock(&driver_lock);
+-
+       dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n",
+               __func__, ifnum);
+ }
diff --git a/queue-5.4/media-rc-add-support-for-another-imon-0xffdc-device.patch b/queue-5.4/media-rc-add-support-for-another-imon-0xffdc-device.patch
new file mode 100644 (file)
index 0000000..389fc5d
--- /dev/null
@@ -0,0 +1,157 @@
+From stable+bounces-183332-greg=kroah.com@vger.kernel.org Fri Oct  3 22:55:46 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Oct 2025 16:55:34 -0400
+Subject: media: rc: Add support for another iMON 0xffdc device
+To: stable@vger.kernel.org
+Cc: Flavius Georgescu <pretoriano.mp@gmail.com>, Chris Vandomelen <chris@sightworks.com>, Sean Young <sean@mess.org>, Mauro Carvalho Chehab <mchehab+samsung@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251003205537.3386848-1-sashal@kernel.org>
+
+From: Flavius Georgescu <pretoriano.mp@gmail.com>
+
+[ Upstream commit cf330691668a3bee37b8ac8212709b3ccdd87997 ]
+
+The device it's an iMON UltraBay (0x98 in config byte) with LCD,
+IR and dual-knobs front panel.
+
+To work properly the device also require its own key table,
+and repeat suppression for all buttons.
+
+Signed-off-by: Flavius Georgescu <pretoriano.mp@gmail.com>
+Co-developed-by: Chris Vandomelen <chris@sightworks.com>
+Signed-off-by: Chris Vandomelen <chris@sightworks.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Stable-dep-of: fa0f61cc1d82 ("media: rc: fix races with imon_disconnect()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/rc/imon.c |   61 ++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 51 insertions(+), 10 deletions(-)
+
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -83,6 +83,7 @@ struct imon_usb_dev_descr {
+       __u16 flags;
+ #define IMON_NO_FLAGS 0
+ #define IMON_NEED_20MS_PKT_DELAY 1
++#define IMON_SUPPRESS_REPEATED_KEYS 2
+       struct imon_panel_key_table key_table[];
+ };
+@@ -149,8 +150,9 @@ struct imon_context {
+       struct timer_list ttimer;       /* touch screen timer */
+       int touch_x;                    /* x coordinate on touchscreen */
+       int touch_y;                    /* y coordinate on touchscreen */
+-      struct imon_usb_dev_descr *dev_descr; /* device description with key
+-                                               table for front panels */
++      const struct imon_usb_dev_descr *dev_descr;
++                                      /* device description with key */
++                                      /* table for front panels */
+ };
+ #define TOUCH_TIMEOUT (HZ/30)
+@@ -315,6 +317,32 @@ static const struct imon_usb_dev_descr i
+       }
+ };
++/* imon ultrabay front panel key table */
++static const struct imon_usb_dev_descr ultrabay_table = {
++      .flags = IMON_SUPPRESS_REPEATED_KEYS,
++      .key_table = {
++              { 0x0000000f0000ffeell, KEY_MEDIA },      /* Go */
++              { 0x000000000100ffeell, KEY_UP },
++              { 0x000000000001ffeell, KEY_DOWN },
++              { 0x000000160000ffeell, KEY_ENTER },
++              { 0x0000001f0000ffeell, KEY_AUDIO },      /* Music */
++              { 0x000000200000ffeell, KEY_VIDEO },      /* Movie */
++              { 0x000000210000ffeell, KEY_CAMERA },     /* Photo */
++              { 0x000000270000ffeell, KEY_DVD },        /* DVD */
++              { 0x000000230000ffeell, KEY_TV },         /* TV */
++              { 0x000000050000ffeell, KEY_PREVIOUS },   /* Previous */
++              { 0x000000070000ffeell, KEY_REWIND },
++              { 0x000000040000ffeell, KEY_STOP },
++              { 0x000000020000ffeell, KEY_PLAYPAUSE },
++              { 0x000000080000ffeell, KEY_FASTFORWARD },
++              { 0x000000060000ffeell, KEY_NEXT },       /* Next */
++              { 0x000100000000ffeell, KEY_VOLUMEUP },
++              { 0x010000000000ffeell, KEY_VOLUMEDOWN },
++              { 0x000000010000ffeell, KEY_MUTE },
++              { 0, KEY_RESERVED },
++      }
++};
++
+ /*
+  * USB Device ID for iMON USB Control Boards
+  *
+@@ -1261,9 +1289,11 @@ static u32 imon_mce_key_lookup(struct im
+ static u32 imon_panel_key_lookup(struct imon_context *ictx, u64 code)
+ {
+-      int i;
++      const struct imon_panel_key_table *key_table;
+       u32 keycode = KEY_RESERVED;
+-      struct imon_panel_key_table *key_table = ictx->dev_descr->key_table;
++      int i;
++
++      key_table = ictx->dev_descr->key_table;
+       for (i = 0; key_table[i].hw_code != 0; i++) {
+               if (key_table[i].hw_code == (code | 0xffee)) {
+@@ -1547,7 +1577,6 @@ static void imon_incoming_packet(struct
+       u32 kc;
+       u64 scancode;
+       int press_type = 0;
+-      long msec;
+       ktime_t t;
+       static ktime_t prev_time;
+       u8 ktype;
+@@ -1649,14 +1678,16 @@ static void imon_incoming_packet(struct
+       spin_lock_irqsave(&ictx->kc_lock, flags);
+       t = ktime_get();
+-      /* KEY_MUTE repeats from knob need to be suppressed */
+-      if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
+-              msec = ktime_ms_delta(t, prev_time);
+-              if (msec < ictx->idev->rep[REP_DELAY]) {
++      /* KEY repeats from knob and panel that need to be suppressed */
++      if (ictx->kc == KEY_MUTE ||
++          ictx->dev_descr->flags & IMON_SUPPRESS_REPEATED_KEYS) {
++              if (ictx->kc == ictx->last_keycode &&
++                  ktime_ms_delta(t, prev_time) < ictx->idev->rep[REP_DELAY]) {
+                       spin_unlock_irqrestore(&ictx->kc_lock, flags);
+                       return;
+               }
+       }
++
+       prev_time = t;
+       kc = ictx->kc;
+@@ -1844,6 +1875,14 @@ static void imon_get_ffdc_type(struct im
+               dev_info(ictx->dev, "0xffdc iMON Inside, iMON IR");
+               ictx->display_supported = false;
+               break;
++      /* Soundgraph iMON UltraBay */
++      case 0x98:
++              dev_info(ictx->dev, "0xffdc iMON UltraBay, LCD + IR");
++              detected_display_type = IMON_DISPLAY_TYPE_LCD;
++              allowed_protos = RC_PROTO_BIT_IMON | RC_PROTO_BIT_RC6_MCE;
++              ictx->dev_descr = &ultrabay_table;
++              break;
++
+       default:
+               dev_info(ictx->dev, "Unknown 0xffdc device, defaulting to VFD and iMON IR");
+               detected_display_type = IMON_DISPLAY_TYPE_VFD;
+@@ -1975,10 +2014,12 @@ out:
+ static struct input_dev *imon_init_idev(struct imon_context *ictx)
+ {
+-      struct imon_panel_key_table *key_table = ictx->dev_descr->key_table;
++      const struct imon_panel_key_table *key_table;
+       struct input_dev *idev;
+       int ret, i;
++      key_table = ictx->dev_descr->key_table;
++
+       idev = input_allocate_device();
+       if (!idev)
+               goto out;
diff --git a/queue-5.4/media-rc-fix-races-with-imon_disconnect.patch b/queue-5.4/media-rc-fix-races-with-imon_disconnect.patch
new file mode 100644 (file)
index 0000000..ec70bef
--- /dev/null
@@ -0,0 +1,164 @@
+From stable+bounces-183335-greg=kroah.com@vger.kernel.org Fri Oct  3 22:55:49 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Oct 2025 16:55:37 -0400
+Subject: media: rc: fix races with imon_disconnect()
+To: stable@vger.kernel.org
+Cc: Larshin Sergey <Sergey.Larshin@kaspersky.com>, syzbot+f1a69784f6efe748c3bf@syzkaller.appspotmail.com, Sean Young <sean@mess.org>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251003205537.3386848-4-sashal@kernel.org>
+
+From: Larshin Sergey <Sergey.Larshin@kaspersky.com>
+
+[ Upstream commit fa0f61cc1d828178aa921475a9b786e7fbb65ccb ]
+
+Syzbot reports a KASAN issue as below:
+BUG: KASAN: use-after-free in __create_pipe include/linux/usb.h:1945 [inline]
+BUG: KASAN: use-after-free in send_packet+0xa2d/0xbc0 drivers/media/rc/imon.c:627
+Read of size 4 at addr ffff8880256fb000 by task syz-executor314/4465
+
+CPU: 2 PID: 4465 Comm: syz-executor314 Not tainted 6.0.0-rc1-syzkaller #0
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.14.0-2 04/01/2014
+Call Trace:
+ <TASK>
+__dump_stack lib/dump_stack.c:88 [inline]
+dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
+print_address_description mm/kasan/report.c:317 [inline]
+print_report.cold+0x2ba/0x6e9 mm/kasan/report.c:433
+kasan_report+0xb1/0x1e0 mm/kasan/report.c:495
+__create_pipe include/linux/usb.h:1945 [inline]
+send_packet+0xa2d/0xbc0 drivers/media/rc/imon.c:627
+vfd_write+0x2d9/0x550 drivers/media/rc/imon.c:991
+vfs_write+0x2d7/0xdd0 fs/read_write.c:576
+ksys_write+0x127/0x250 fs/read_write.c:631
+do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
+entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+The iMON driver improperly releases the usb_device reference in
+imon_disconnect without coordinating with active users of the
+device.
+
+Specifically, the fields usbdev_intf0 and usbdev_intf1 are not
+protected by the users counter (ictx->users). During probe,
+imon_init_intf0 or imon_init_intf1 increments the usb_device
+reference count depending on the interface. However, during
+disconnect, usb_put_dev is called unconditionally, regardless of
+actual usage.
+
+As a result, if vfd_write or other operations are still in
+progress after disconnect, this can lead to a use-after-free of
+the usb_device pointer.
+
+Thread 1 vfd_write                      Thread 2 imon_disconnect
+                                        ...
+                                        if
+                                          usb_put_dev(ictx->usbdev_intf0)
+                                        else
+                                          usb_put_dev(ictx->usbdev_intf1)
+...
+while
+  send_packet
+    if
+      pipe = usb_sndintpipe(
+        ictx->usbdev_intf0) UAF
+    else
+      pipe = usb_sndctrlpipe(
+        ictx->usbdev_intf0, 0) UAF
+
+Guard access to usbdev_intf0 and usbdev_intf1 after disconnect by
+checking ictx->disconnected in all writer paths. Add early return
+with -ENODEV in send_packet(), vfd_write(), lcd_write() and
+display_open() if the device is no longer present.
+
+Set and read ictx->disconnected under ictx->lock to ensure memory
+synchronization. Acquire the lock in imon_disconnect() before setting
+the flag to synchronize with any ongoing operations.
+
+Ensure writers exit early and safely after disconnect before the USB
+core proceeds with cleanup.
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Reported-by: syzbot+f1a69784f6efe748c3bf@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f1a69784f6efe748c3bf
+Fixes: 21677cfc562a ("V4L/DVB: ir-core: add imon driver")
+Cc: stable@vger.kernel.org
+
+Signed-off-by: Larshin Sergey <Sergey.Larshin@kaspersky.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/rc/imon.c |   27 ++++++++++++++++++++-------
+ 1 file changed, 20 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -536,7 +536,9 @@ static int display_open(struct inode *in
+       mutex_lock(&ictx->lock);
+-      if (!ictx->display_supported) {
++      if (ictx->disconnected) {
++              retval = -ENODEV;
++      } else if (!ictx->display_supported) {
+               pr_err("display not supported by device\n");
+               retval = -ENODEV;
+       } else if (ictx->display_isopen) {
+@@ -600,6 +602,9 @@ static int send_packet(struct imon_conte
+       lockdep_assert_held(&ictx->lock);
++      if (ictx->disconnected)
++              return -ENODEV;
++
+       /* Check if we need to use control or interrupt urb */
+       if (!ictx->tx_control) {
+               pipe = usb_sndintpipe(ictx->usbdev_intf0,
+@@ -956,12 +961,14 @@ static ssize_t vfd_write(struct file *fi
+       static const unsigned char vfd_packet6[] = {
+               0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+-      if (ictx->disconnected)
+-              return -ENODEV;
+-
+       if (mutex_lock_interruptible(&ictx->lock))
+               return -ERESTARTSYS;
++      if (ictx->disconnected) {
++              retval = -ENODEV;
++              goto exit;
++      }
++
+       if (!ictx->dev_present_intf0) {
+               pr_err_ratelimited("no iMON device present\n");
+               retval = -ENODEV;
+@@ -1036,11 +1043,13 @@ static ssize_t lcd_write(struct file *fi
+       int retval = 0;
+       struct imon_context *ictx = file->private_data;
+-      if (ictx->disconnected)
+-              return -ENODEV;
+-
+       mutex_lock(&ictx->lock);
++      if (ictx->disconnected) {
++              retval = -ENODEV;
++              goto exit;
++      }
++
+       if (!ictx->display_supported) {
+               pr_err_ratelimited("no iMON display present\n");
+               retval = -ENODEV;
+@@ -2496,7 +2505,11 @@ static void imon_disconnect(struct usb_i
+       int ifnum;
+       ictx = usb_get_intfdata(interface);
++
++      mutex_lock(&ictx->lock);
+       ictx->disconnected = true;
++      mutex_unlock(&ictx->lock);
++
+       dev = ictx->dev;
+       ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
diff --git a/queue-5.4/media-tuner-xc5000-fix-use-after-free-in-xc5000_release.patch b/queue-5.4/media-tuner-xc5000-fix-use-after-free-in-xc5000_release.patch
new file mode 100644 (file)
index 0000000..8bf16a9
--- /dev/null
@@ -0,0 +1,59 @@
+From stable+bounces-183345-greg=kroah.com@vger.kernel.org Sat Oct  4 02:40:23 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Oct 2025 20:40:15 -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: <20251004004015.4039827-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);
+       }
diff --git a/queue-5.4/media-tunner-xc5000-refactor-firmware-load.patch b/queue-5.4/media-tunner-xc5000-refactor-firmware-load.patch
new file mode 100644 (file)
index 0000000..4f51600
--- /dev/null
@@ -0,0 +1,113 @@
+From stable+bounces-183346-greg=kroah.com@vger.kernel.org Sat Oct  4 02:40:25 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Oct 2025 20:40:14 -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: <20251004004015.4039827-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);
+       }
index ca3b214cdf0a7f6b0a089d986336a32cc10774fb..0040022a6bdfa8e149256e324389f03c611175a7 100644 (file)
@@ -1,3 +1,10 @@
 scsi-target-target_core_configfs-add-length-check-to-avoid-buffer-overflow.patch
 media-b2c2-fix-use-after-free-causing-by-irq_check_work-in-flexcop_pci_remove.patch
 udp-fix-memory-accounting-leak.patch
+media-tunner-xc5000-refactor-firmware-load.patch
+media-tuner-xc5000-fix-use-after-free-in-xc5000_release.patch
+media-i2c-tc358743-fix-use-after-free-bugs-caused-by-orphan-timer-in-probe.patch
+media-rc-add-support-for-another-imon-0xffdc-device.patch
+media-imon-reorganize-serialization.patch
+media-imon-grab-lock-earlier-in-imon_ir_change_protocol.patch
+media-rc-fix-races-with-imon_disconnect.patch