]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Apr 2026 15:10:10 +0000 (17:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Apr 2026 15:10:10 +0000 (17:10 +0200)
added patches:
media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_probe.patch
media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch
media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch
nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch

queue-6.12/media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_probe.patch [new file with mode: 0644]
queue-6.12/media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch [new file with mode: 0644]
queue-6.12/media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch [new file with mode: 0644]
queue-6.12/nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_probe.patch b/queue-6.12/media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_probe.patch
new file mode 100644 (file)
index 0000000..b389afd
--- /dev/null
@@ -0,0 +1,70 @@
+From 8bd29dbe03fc5b0f039ab2395ff37b64236d2f0c Mon Sep 17 00:00:00 2001
+From: Jeongjun Park <aha310510@gmail.com>
+Date: Sun, 11 Jan 2026 00:17:53 +0900
+Subject: media: as102: fix to not free memory after the device is registered in as102_usb_probe()
+
+From: Jeongjun Park <aha310510@gmail.com>
+
+commit 8bd29dbe03fc5b0f039ab2395ff37b64236d2f0c upstream.
+
+In as102_usb driver, the following race condition occurs:
+```
+               CPU0                                            CPU1
+as102_usb_probe()
+  kzalloc(); // alloc as102_dev_t
+  ....
+  usb_register_dev();
+                                               fd = sys_open("/path/to/dev"); // open as102 fd
+                                               ....
+  usb_deregister_dev();
+  ....
+  kfree(); // free as102_dev_t
+  ....
+                                               sys_close(fd);
+                                                 as102_release() // UAF!!
+                                                   as102_usb_release()
+                                                     kfree(); // DFB!!
+```
+
+When a USB character device registered with usb_register_dev() is later
+unregistered (via usb_deregister_dev() or disconnect), the device node is
+removed so new open() calls fail. However, file descriptors that are
+already open do not go away immediately: they remain valid until the last
+reference is dropped and the driver's .release() is invoked.
+
+In as102, as102_usb_probe() calls usb_register_dev() and then, on an
+error path, does usb_deregister_dev() and frees as102_dev_t right away.
+If userspace raced a successful open() before the deregistration, that
+open FD will later hit as102_release() --> as102_usb_release() and access
+or free as102_dev_t again, occur a race to use-after-free and
+double-free vuln.
+
+The fix is to never kfree(as102_dev_t) directly once usb_register_dev()
+has succeeded. After deregistration, defer freeing memory to .release().
+
+In other words, let release() perform the last kfree when the final open
+FD is closed.
+
+Cc: <stable@vger.kernel.org>
+Reported-by: syzbot+47321e8fd5a4c84088db@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=47321e8fd5a4c84088db
+Fixes: cd19f7d3e39b ("[media] as102: fix leaks at failure paths in as102_usb_probe()")
+Signed-off-by: Jeongjun Park <aha310510@gmail.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/usb/as102/as102_usb_drv.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/media/usb/as102/as102_usb_drv.c
++++ b/drivers/media/usb/as102/as102_usb_drv.c
+@@ -403,7 +403,9 @@ static int as102_usb_probe(struct usb_in
+ failed_dvb:
+       as102_free_usb_stream_buffer(as102_dev);
+ failed_stream:
++      usb_set_intfdata(intf, NULL);
+       usb_deregister_dev(intf, &as102_usb_class_driver);
++      return ret;
+ failed:
+       usb_put_dev(as102_dev->bus_adap.usb_dev);
+       usb_set_intfdata(intf, NULL);
diff --git a/queue-6.12/media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch b/queue-6.12/media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch
new file mode 100644 (file)
index 0000000..70436e6
--- /dev/null
@@ -0,0 +1,87 @@
+From 3b7da2b4d0fe014eff181ed37e3bf832eb8ed258 Mon Sep 17 00:00:00 2001
+From: Jeongjun Park <aha310510@gmail.com>
+Date: Sat, 10 Jan 2026 23:58:29 +0900
+Subject: media: hackrf: fix to not free memory after the device is registered in hackrf_probe()
+
+From: Jeongjun Park <aha310510@gmail.com>
+
+commit 3b7da2b4d0fe014eff181ed37e3bf832eb8ed258 upstream.
+
+In hackrf driver, the following race condition occurs:
+```
+               CPU0                                            CPU1
+hackrf_probe()
+  kzalloc(); // alloc hackrf_dev
+  ....
+  v4l2_device_register();
+  ....
+                                               fd = sys_open("/path/to/dev"); // open hackrf fd
+                                               ....
+  v4l2_device_unregister();
+  ....
+  kfree(); // free hackrf_dev
+  ....
+                                               sys_ioctl(fd, ...);
+                                                 v4l2_ioctl();
+                                                   video_is_registered() // UAF!!
+                                               ....
+                                               sys_close(fd);
+                                                 v4l2_release() // UAF!!
+                                                   hackrf_video_release()
+                                                     kfree(); // DFB!!
+```
+
+When a V4L2 or video device is unregistered, the device node is removed so
+new open() calls are blocked.
+
+However, file descriptors that are already open-and any in-flight I/O-do
+not terminate immediately; they remain valid until the last reference is
+dropped and the driver's release() is invoked.
+
+Therefore, freeing device memory on the error path after hackrf_probe()
+has registered dev it will lead to a race to use-after-free vuln, since
+those already-open handles haven't been released yet.
+
+And since release() free memory too, race to use-after-free and
+double-free vuln occur.
+
+To prevent this, if device is registered from probe(), it should be
+modified to free memory only through release() rather than calling
+kfree() directly.
+
+Cc: <stable@vger.kernel.org>
+Reported-by: syzbot+6ffd76b5405c006a46b7@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=6ffd76b5405c006a46b7
+Reported-by: syzbot+f1b20958f93d2d250727@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f1b20958f93d2d250727
+Fixes: 8bc4a9ed8504 ("[media] hackrf: add support for transmitter")
+Signed-off-by: Jeongjun Park <aha310510@gmail.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/usb/hackrf/hackrf.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/usb/hackrf/hackrf.c
++++ b/drivers/media/usb/hackrf/hackrf.c
+@@ -1486,7 +1486,7 @@ static int hackrf_probe(struct usb_inter
+       if (ret) {
+               dev_err(dev->dev,
+                       "Failed to register as video device (%d)\n", ret);
+-              goto err_v4l2_device_unregister;
++              goto err_v4l2_device_put;
+       }
+       dev_info(dev->dev, "Registered as %s\n",
+                video_device_node_name(&dev->rx_vdev));
+@@ -1515,8 +1515,9 @@ static int hackrf_probe(struct usb_inter
+       return 0;
+ err_video_unregister_device_rx:
+       video_unregister_device(&dev->rx_vdev);
+-err_v4l2_device_unregister:
+-      v4l2_device_unregister(&dev->v4l2_dev);
++err_v4l2_device_put:
++      v4l2_device_put(&dev->v4l2_dev);
++      return ret;
+ err_v4l2_ctrl_handler_free_tx:
+       v4l2_ctrl_handler_free(&dev->tx_ctrl_handler);
+ err_v4l2_ctrl_handler_free_rx:
diff --git a/queue-6.12/media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch b/queue-6.12/media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch
new file mode 100644 (file)
index 0000000..33abe98
--- /dev/null
@@ -0,0 +1,176 @@
+From 5f8e73bde67e931468bc2a1860d78d72f0c6ba41 Mon Sep 17 00:00:00 2001
+From: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
+Date: Sat, 21 Feb 2026 13:56:18 +0100
+Subject: media: vidtv: fix pass-by-value structs causing MSAN warnings
+
+From: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
+
+commit 5f8e73bde67e931468bc2a1860d78d72f0c6ba41 upstream.
+
+vidtv_ts_null_write_into() and vidtv_ts_pcr_write_into() take their
+argument structs by value, causing MSAN to report uninit-value warnings.
+While only vidtv_ts_null_write_into() has triggered a report so far,
+both functions share the same issue.
+
+Fix by passing both structs by const pointer instead, avoiding the
+stack copy of the struct along with its MSAN shadow and origin metadata.
+The functions do not modify the structs, which is enforced by the const
+qualifier.
+
+Fixes: f90cf6079bf67 ("media: vidtv: add a bridge driver")
+Cc: stable@vger.kernel.org
+Reported-by: syzbot+96f901260a0b2d29cd1a@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=96f901260a0b2d29cd1a
+Tested-by: syzbot+96f901260a0b2d29cd1a@syzkaller.appspotmail.com
+Suggested-by: Yihan Ding <dingyihan@uniontech.com>
+Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/test-drivers/vidtv/vidtv_mux.c |    4 +-
+ drivers/media/test-drivers/vidtv/vidtv_ts.c  |   50 +++++++++++++--------------
+ drivers/media/test-drivers/vidtv/vidtv_ts.h  |    4 +-
+ 3 files changed, 29 insertions(+), 29 deletions(-)
+
+--- a/drivers/media/test-drivers/vidtv/vidtv_mux.c
++++ b/drivers/media/test-drivers/vidtv/vidtv_mux.c
+@@ -233,7 +233,7 @@ static u32 vidtv_mux_push_pcr(struct vid
+       /* the 27Mhz clock will feed both parts of the PCR bitfield */
+       args.pcr = m->timing.clk;
+-      nbytes += vidtv_ts_pcr_write_into(args);
++      nbytes += vidtv_ts_pcr_write_into(&args);
+       m->mux_buf_offset += nbytes;
+       m->num_streamed_pcr++;
+@@ -363,7 +363,7 @@ static u32 vidtv_mux_pad_with_nulls(stru
+       args.continuity_counter = &ctx->cc;
+       for (i = 0; i < npkts; ++i) {
+-              m->mux_buf_offset += vidtv_ts_null_write_into(args);
++              m->mux_buf_offset += vidtv_ts_null_write_into(&args);
+               args.dest_offset  = m->mux_buf_offset;
+       }
+--- a/drivers/media/test-drivers/vidtv/vidtv_ts.c
++++ b/drivers/media/test-drivers/vidtv/vidtv_ts.c
+@@ -48,7 +48,7 @@ void vidtv_ts_inc_cc(u8 *continuity_coun
+               *continuity_counter = 0;
+ }
+-u32 vidtv_ts_null_write_into(struct null_packet_write_args args)
++u32 vidtv_ts_null_write_into(const struct null_packet_write_args *args)
+ {
+       u32 nbytes = 0;
+       struct vidtv_mpeg_ts ts_header = {};
+@@ -56,21 +56,21 @@ u32 vidtv_ts_null_write_into(struct null
+       ts_header.sync_byte          = TS_SYNC_BYTE;
+       ts_header.bitfield           = cpu_to_be16(TS_NULL_PACKET_PID);
+       ts_header.payload            = 1;
+-      ts_header.continuity_counter = *args.continuity_counter;
++      ts_header.continuity_counter = *args->continuity_counter;
+       /* copy TS header */
+-      nbytes += vidtv_memcpy(args.dest_buf,
+-                             args.dest_offset + nbytes,
+-                             args.buf_sz,
++      nbytes += vidtv_memcpy(args->dest_buf,
++                             args->dest_offset + nbytes,
++                             args->buf_sz,
+                              &ts_header,
+                              sizeof(ts_header));
+-      vidtv_ts_inc_cc(args.continuity_counter);
++      vidtv_ts_inc_cc(args->continuity_counter);
+       /* fill the rest with empty data */
+-      nbytes += vidtv_memset(args.dest_buf,
+-                             args.dest_offset + nbytes,
+-                             args.buf_sz,
++      nbytes += vidtv_memset(args->dest_buf,
++                             args->dest_offset + nbytes,
++                             args->buf_sz,
+                              TS_FILL_BYTE,
+                              TS_PACKET_LEN - nbytes);
+@@ -83,17 +83,17 @@ u32 vidtv_ts_null_write_into(struct null
+       return nbytes;
+ }
+-u32 vidtv_ts_pcr_write_into(struct pcr_write_args args)
++u32 vidtv_ts_pcr_write_into(const struct pcr_write_args *args)
+ {
+       u32 nbytes = 0;
+       struct vidtv_mpeg_ts ts_header = {};
+       struct vidtv_mpeg_ts_adaption ts_adap = {};
+       ts_header.sync_byte     = TS_SYNC_BYTE;
+-      ts_header.bitfield      = cpu_to_be16(args.pid);
++      ts_header.bitfield      = cpu_to_be16(args->pid);
+       ts_header.scrambling    = 0;
+       /* cc is not incremented, but it is needed. see 13818-1 clause 2.4.3.3 */
+-      ts_header.continuity_counter = *args.continuity_counter;
++      ts_header.continuity_counter = *args->continuity_counter;
+       ts_header.payload            = 0;
+       ts_header.adaptation_field   = 1;
+@@ -102,27 +102,27 @@ u32 vidtv_ts_pcr_write_into(struct pcr_w
+       ts_adap.PCR    = 1;
+       /* copy TS header */
+-      nbytes += vidtv_memcpy(args.dest_buf,
+-                             args.dest_offset + nbytes,
+-                             args.buf_sz,
++      nbytes += vidtv_memcpy(args->dest_buf,
++                             args->dest_offset + nbytes,
++                             args->buf_sz,
+                              &ts_header,
+                              sizeof(ts_header));
+       /* write the adap after the TS header */
+-      nbytes += vidtv_memcpy(args.dest_buf,
+-                             args.dest_offset + nbytes,
+-                             args.buf_sz,
++      nbytes += vidtv_memcpy(args->dest_buf,
++                             args->dest_offset + nbytes,
++                             args->buf_sz,
+                              &ts_adap,
+                              sizeof(ts_adap));
+       /* write the PCR optional */
+-      nbytes += vidtv_ts_write_pcr_bits(args.dest_buf,
+-                                        args.dest_offset + nbytes,
+-                                        args.pcr);
+-
+-      nbytes += vidtv_memset(args.dest_buf,
+-                             args.dest_offset + nbytes,
+-                             args.buf_sz,
++      nbytes += vidtv_ts_write_pcr_bits(args->dest_buf,
++                                        args->dest_offset + nbytes,
++                                        args->pcr);
++
++      nbytes += vidtv_memset(args->dest_buf,
++                             args->dest_offset + nbytes,
++                             args->buf_sz,
+                              TS_FILL_BYTE,
+                              TS_PACKET_LEN - nbytes);
+--- a/drivers/media/test-drivers/vidtv/vidtv_ts.h
++++ b/drivers/media/test-drivers/vidtv/vidtv_ts.h
+@@ -90,7 +90,7 @@ void vidtv_ts_inc_cc(u8 *continuity_coun
+  *
+  * Return: The number of bytes written into the buffer.
+  */
+-u32 vidtv_ts_null_write_into(struct null_packet_write_args args);
++u32 vidtv_ts_null_write_into(const struct null_packet_write_args *args);
+ /**
+  * vidtv_ts_pcr_write_into - Write a PCR  packet into a buffer.
+@@ -101,6 +101,6 @@ u32 vidtv_ts_null_write_into(struct null
+  *
+  * Return: The number of bytes written into the buffer.
+  */
+-u32 vidtv_ts_pcr_write_into(struct pcr_write_args args);
++u32 vidtv_ts_pcr_write_into(const struct pcr_write_args *args);
+ #endif //VIDTV_TS_H
diff --git a/queue-6.12/nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch b/queue-6.12/nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch
new file mode 100644 (file)
index 0000000..0f3ee0d
--- /dev/null
@@ -0,0 +1,47 @@
+From 4a4e0328edd9e9755843787d28f16dd4165f8b48 Mon Sep 17 00:00:00 2001
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+Date: Tue, 31 Mar 2026 09:47:21 +0900
+Subject: nilfs2: fix NULL i_assoc_inode dereference in nilfs_mdt_save_to_shadow_map
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+commit 4a4e0328edd9e9755843787d28f16dd4165f8b48 upstream.
+
+The DAT inode's btree node cache (i_assoc_inode) is initialized lazily
+during btree operations. However, nilfs_mdt_save_to_shadow_map()
+assumes i_assoc_inode is already initialized when copying dirty pages
+to the shadow map during GC.
+
+If NILFS_IOCTL_CLEAN_SEGMENTS is called immediately after mount before
+any btree operation has occurred on the DAT inode, i_assoc_inode is
+NULL leading to a general protection fault.
+
+Fix this by calling nilfs_attach_btree_node_cache() on the DAT inode
+in nilfs_dat_read() at mount time, ensuring i_assoc_inode is always
+initialized before any GC operation can use it.
+
+Reported-by: syzbot+4b4093b1f24ad789bf37@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=4b4093b1f24ad789bf37
+Tested-by: syzbot+4b4093b1f24ad789bf37@syzkaller.appspotmail.com
+Fixes: e897be17a441 ("nilfs2: fix lockdep warnings in page operations for btree nodes")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/dat.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/nilfs2/dat.c
++++ b/fs/nilfs2/dat.c
+@@ -523,6 +523,9 @@ int nilfs_dat_read(struct super_block *s
+       if (err)
+               goto failed;
++      err = nilfs_attach_btree_node_cache(dat);
++      if (err)
++              goto failed;
+       err = nilfs_read_inode_common(dat, raw_inode);
+       if (err)
+               goto failed;
index e85f602c9e6ea3bd1d9cb50526ea42ce21ab7892..e65bac3ddd1b28e9d6c10dd61746a5fa68cac6c8 100644 (file)
@@ -149,3 +149,7 @@ media-em28xx-fix-use-after-free-in-em28xx_v4l2_open.patch
 hwmon-powerz-fix-use-after-free-on-usb-disconnect.patch
 alsa-6fire-fix-use-after-free-on-disconnect.patch
 bcache-fix-cached_dev.sb_bio-use-after-free-and-crash.patch
+media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_probe.patch
+nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch
+media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch
+media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch