The while loop in pluto_dma_end() scans the DMA buffer for MPEG-TS sync
bytes (0x47) at 188-byte intervals. However, it does not check the buffer
boundary. If the buffer contains 0x47 at every 188-byte offset, the loop
index will exceed the buffer size, causing an out-of-bounds read.
Add a check to ensure the index stays within TS_DMA_BYTES.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: c7cadb3a02b5 ("[PATCH] dvb: add Pluto2 driver")
Signed-off-by: Dmitriy Chumachenko <Dmitry.Chumachenko(a)cyberprotect.ru>
---
drivers/media/pci/pluto2/pluto2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c
index 6ac9b9bd7435..fd7f8d8b85a8 100644
--- a/drivers/media/pci/pluto2/pluto2.c
+++ b/drivers/media/pci/pluto2/pluto2.c
@@ -291,7 +291,7 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
*/
if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
unsigned int i = 0;
- while (pluto->dma_buf[i] == 0x47)
+ while (i < TS_DMA_BYTES && pluto->dma_buf[i] == 0x47)
i += 188;
nbpackets = i / 188;
if (i == 0) {
--
2.49.0
In case of a refcounting bug dma_fence_release() can be called before the
fence was even signaled.
Previously the dma_fence framework then force signaled the fence to make
sure to unblock waiters, but that can potentially lead to random memory
corruption when the DMA operation continues. So be more defensive here and
pick the lesser evil.
Instead of force signaling the fence set an error code on the fence,
re-initialize the refcount to something large and taint the kernel.
This will leak memory and eventually can cause a deadlock when the fence
is never signaled, but at least we won't run into an use after free or
random memory corruption.
Signed-off-by: Christian König <christian.koenig(a)amd.com>
---
drivers/dma-buf/dma-fence.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index 1826ba73094c..8bf07685a053 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -593,14 +593,24 @@ void dma_fence_release(struct kref *kref)
/*
* Failed to signal before release, likely a refcounting issue.
*
- * This should never happen, but if it does make sure that we
- * don't leave chains dangling. We set the error flag first
- * so that the callbacks know this signal is due to an error.
+ * This should never happen, but if try to be defensive and take
+ * the lesser evil. Initialize the refcount to something large,
+ * but not so large that it can overflow.
+ *
+ * That will leak memory and could deadlock if the fence never
+ * signals, but at least it doesn't cause an use after free or
+ * random memory corruption.
+ *
+ * Also taint the kernel to note that it is rather unreliable to
+ * continue.
*/
dma_fence_lock_irqsave(fence, flags);
fence->error = -EDEADLK;
- dma_fence_signal_locked(fence);
+ refcount_set(&fence->refcount.refcount, INT_MAX);
dma_fence_unlock_irqrestore(fence, flags);
+ rcu_read_unlock();
+ add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
+ return;
}
ops = rcu_dereference(fence->ops);
--
2.43.0
When a caller already guards a tracepoint with an explicit enabled check:
if (trace_foo_enabled() && cond)
trace_foo(args);
trace_foo() internally re-evaluates the static_branch_unlikely() key.
Since static branches are patched binary instructions the compiler cannot
fold the two evaluations, so every such site pays the cost twice.
This series introduces trace_invoke_##name() as a companion to
trace_##name(). It calls __do_trace_##name() directly, bypassing the
redundant static-branch re-check, while preserving all other correctness
properties of the normal path (RCU-watching assertion, might_fault() for
syscall tracepoints). The internal __do_trace_##name() symbol is not
leaked to call sites; trace_invoke_##name() is the only new public API.
if (trace_foo_enabled() && cond)
trace_invoke_foo(args); /* calls __do_trace_foo() directly */
The first patch adds the three-location change to
include/linux/tracepoint.h (__DECLARE_TRACE, __DECLARE_TRACE_SYSCALL,
and the !TRACEPOINTS_ENABLED stub). The remaining 14 patches
mechanically convert all guarded call sites found in the tree:
kernel/, io_uring/, net/, accel/habanalabs, cpufreq/, devfreq/,
dma-buf/, fsi/, drm/, HID, i2c/, spi/, scsi/ufs/, and btrfs/.
This series is motivated by Peter Zijlstra's observation in the discussion
around Dmitry Ilvokhin's locking tracepoint instrumentation series, where
he noted that compilers cannot optimize static branches and that guarded
call sites end up evaluating the static branch twice for no reason, and
by Steven Rostedt's suggestion to add a proper API instead of exposing
internal implementation details like __do_trace_##name() directly to
call sites:
https://lore.kernel.org/linux-trace-kernel/8298e098d3418cb446ef396f119edac5…
Suggested-by: Steven Rostedt <rostedt(a)goodmis.org>
Suggested-by: Peter Zijlstra <peterz(a)infradead.org>
Vineeth Pillai (Google) (15):
tracepoint: Add trace_invoke_##name() API
kernel: Use trace_invoke_##name() at guarded tracepoint call sites
io_uring: Use trace_invoke_##name() at guarded tracepoint call sites
net: Use trace_invoke_##name() at guarded tracepoint call sites
accel/habanalabs: Use trace_invoke_##name() at guarded tracepoint call
sites
cpufreq: Use trace_invoke_##name() at guarded tracepoint call sites
devfreq: Use trace_invoke_##name() at guarded tracepoint call sites
dma-buf: Use trace_invoke_##name() at guarded tracepoint call sites
fsi: Use trace_invoke_##name() at guarded tracepoint call sites
drm: Use trace_invoke_##name() at guarded tracepoint call sites
HID: Use trace_invoke_##name() at guarded tracepoint call sites
i2c: Use trace_invoke_##name() at guarded tracepoint call sites
spi: Use trace_invoke_##name() at guarded tracepoint call sites
scsi: ufs: Use trace_invoke_##name() at guarded tracepoint call sites
btrfs: Use trace_invoke_##name() at guarded tracepoint call sites
drivers/accel/habanalabs/common/device.c | 12 ++++++------
drivers/accel/habanalabs/common/mmu/mmu.c | 3 ++-
drivers/accel/habanalabs/common/pci/pci.c | 4 ++--
drivers/cpufreq/amd-pstate.c | 10 +++++-----
drivers/cpufreq/cpufreq.c | 2 +-
drivers/cpufreq/intel_pstate.c | 2 +-
drivers/devfreq/devfreq.c | 2 +-
drivers/dma-buf/dma-fence.c | 4 ++--
drivers/fsi/fsi-master-aspeed.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 4 ++--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
drivers/gpu/drm/scheduler/sched_entity.c | 4 ++--
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 2 +-
drivers/i2c/i2c-core-slave.c | 2 +-
drivers/spi/spi-axi-spi-engine.c | 4 ++--
drivers/ufs/core/ufshcd.c | 12 ++++++------
fs/btrfs/extent_map.c | 4 ++--
fs/btrfs/raid56.c | 4 ++--
include/linux/tracepoint.h | 11 +++++++++++
io_uring/io_uring.h | 2 +-
kernel/irq_work.c | 2 +-
kernel/sched/ext.c | 2 +-
kernel/smp.c | 2 +-
net/core/dev.c | 2 +-
net/core/xdp.c | 2 +-
net/openvswitch/actions.c | 2 +-
net/openvswitch/datapath.c | 2 +-
net/sctp/outqueue.c | 2 +-
net/tipc/node.c | 2 +-
30 files changed, 62 insertions(+), 50 deletions(-)
--
2.53.0
Almighty Cryptocurrency Recovery is a private investigation, asset recovery, and financial regulator. We specialize in instances involving recovery scams, cryptocurrency, fake investment schemes, and ethical hacking. We examine the factors influencing your score and are also experts in credit repair. removing criminal records, school grades, and jobs involving phone and social media hacking.
Every piece of software required to carry out recoveries from beginning to end is available.
The writers and offenders band together to establish a syndicate, so be wary of false reviews and testimonials on the internet.To get started, send an email to our support team at the address below as soon as you can.
almightyrecoverycoin(a)mail.com and whatsapp +53 51 55 6969
Visit website; almightyrecoveryco.wixsite.com/almighty-recovery-co
Stay Safe!
This is the next version of the shmem backed GEM objects series
originally from Asahi, previously posted by Daniel Almeida.
One of the major changes in this patch series is a much better interface
around vmaps, which we achieve by introducing a new set of rust bindings
for iosys_map.
The previous version of the patch series can be found here:
https://patchwork.freedesktop.org/series/156093/
This patch series may be applied on top of the
driver-core/driver-core-testing branch:
https://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git…
Changelogs are per-patch
Asahi Lina (2):
rust: helpers: Add bindings/wrappers for dma_resv_lock
rust: drm: gem: shmem: Add DRM shmem helper abstraction
Lyude Paul (5):
rust: drm: Add gem::impl_aref_for_gem_obj!
rust: drm: gem: Add raw_dma_resv() function
rust: gem: Introduce DriverObject::Args
rust: drm: gem: Introduce shmem::SGTable
rust: drm/gem: Add vmap functions to shmem bindings
drivers/gpu/drm/nova/gem.rs | 5 +-
drivers/gpu/drm/tyr/gem.rs | 3 +-
rust/bindings/bindings_helper.h | 3 +
rust/helpers/dma-resv.c | 13 +
rust/helpers/drm.c | 56 +++-
rust/helpers/helpers.c | 1 +
rust/kernel/drm/gem/mod.rs | 79 +++--
rust/kernel/drm/gem/shmem.rs | 529 ++++++++++++++++++++++++++++++++
8 files changed, 667 insertions(+), 22 deletions(-)
create mode 100644 rust/helpers/dma-resv.c
create mode 100644 rust/kernel/drm/gem/shmem.rs
--
2.53.0
On Sun, Mar 8, 2026 at 7:08 PM Jason Gunthorpe <jgg(a)ziepe.ca> wrote:
>
> On Sun, Mar 08, 2026 at 02:55:27PM +0100, Julian Orth wrote:
> > A user reported memory corruption in the Jay wayland compositor [1]. The
> > corruption started when archlinux enabled
> > CONFIG_TRANSPARENT_HUGEPAGE_SHMEM_HUGE_WITHIN_SIZE in kernel 6.19.5.
> >
> > The compositor uses udmabuf to upload memory from memfds to the GPU.
> > When running an affected kernel, the following warnings are logged:
> >
> > a - addrs >= max_entries
> > WARNING: drivers/gpu/drm/drm_prime.c:1089 at drm_prime_sg_to_dma_addr_array+0x86/0xc0, CPU#31: jay/1864
> > [...]
> > Call Trace:
> > <TASK>
> > amdgpu_bo_move+0x188/0x800 [amdgpu 3b451640234948027c09e9b39e6520bc7e5471cf]
> >
> > Disabling the use of huge pages at runtime via
> > /sys/kernel/mm/transparent_hugepage/shmem_enabled fixes the issue.
> >
> > udmabuf allocates a scatterlist with buffer_size/PAGE_SIZE entries. Each
> > entry has a length of PAGE_SIZE. With huge pages disabled, it appears
> > that sg->offset is always 0. With huge pages enabled, sg->offset is
> > incremented by PAGE_SIZE until the end of the huge page.
>
> This was broken by 0c8b91ef5100 ("udmabuf: add back support for
> mapping hugetlb pages") which switched from a working
> sg_alloc_table_from_pages() to a messed up sg_set_pages loop:
>
> + for_each_sg(sg->sgl, sgl, ubuf->pagecount, i)
> + sg_set_page(sgl, ubuf->pages[i], PAGE_SIZE, ubuf->offsets[i]);
> [..]
> + ubuf->offsets[*pgbuf] = subpgoff << PAGE_SHIFT;
>
> Which is just the wrong way to use the scatterlist API.
>
> This was later changed to sg_set_folio() which I'm also suspecting has
> a bug, it should be setting page_link to the proper tail page because
> as you observe page_offset must fall within 0 to PAGE_SIZE-1 to make
> the iterator work.
>
> I think the whole design here in udmabuf makes very little sense. It
> starts out with an actual list of folios then expands them to a per-4K
> double array of folio/offset. This is nonsensical, if it wants to
> build a way to direct index the mapping for mmap it should just build
> itself a page * array like the code used to do and continue to use
> sg_alloc_table_from_pages() which builds properly formed scatterlists.
>
> This would save memory, use the APIs properly and build a correct and
> optimized scatterlist to boot. It uses vmf_insert_pfn() and
> vm_map_ram() anyhow so it doesn't even use a folio :\
>
> Here, a few mins of AI shows what I think udmabuf should look like. If
> you wish to persue this please add my signed-off-by and handle testing
> it and getting it merged. I reviewed it enough to see it was showing
> what I wanted.
I don't know enough about folios or udmabuf to efficiently work on this.
If offset is supposed to be in [0, PAGE_SIZE-1], then my patch is
incorrect and it's probably better if some of the udmabuf maintainers
take a look at this. I've added them to CC.
>
> Jason
>
> diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
> index 94b8ecb892bb17..5d687860445137 100644
> --- a/drivers/dma-buf/udmabuf.c
> +++ b/drivers/dma-buf/udmabuf.c
> @@ -26,10 +26,10 @@ MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in megabytes. Default is
>
> struct udmabuf {
> pgoff_t pagecount;
> - struct folio **folios;
> + struct page **pages;
>
> /**
> - * Unlike folios, pinned_folios is only used for unpin.
> + * Unlike pages, pinned_folios is only used for unpin.
> * So, nr_pinned is not the same to pagecount, the pinned_folios
> * only set each folio which already pinned when udmabuf_create.
> * Note that, since a folio may be pinned multiple times, each folio
> @@ -41,7 +41,6 @@ struct udmabuf {
>
> struct sg_table *sg;
> struct miscdevice *device;
> - pgoff_t *offsets;
> };
>
> static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf)
> @@ -55,8 +54,7 @@ static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf)
> if (pgoff >= ubuf->pagecount)
> return VM_FAULT_SIGBUS;
>
> - pfn = folio_pfn(ubuf->folios[pgoff]);
> - pfn += ubuf->offsets[pgoff] >> PAGE_SHIFT;
> + pfn = page_to_pfn(ubuf->pages[pgoff]);
>
> ret = vmf_insert_pfn(vma, vmf->address, pfn);
> if (ret & VM_FAULT_ERROR)
> @@ -73,8 +71,7 @@ static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf)
> if (WARN_ON(pgoff >= ubuf->pagecount))
> break;
>
> - pfn = folio_pfn(ubuf->folios[pgoff]);
> - pfn += ubuf->offsets[pgoff] >> PAGE_SHIFT;
> + pfn = page_to_pfn(ubuf->pages[pgoff]);
>
> /**
> * If the below vmf_insert_pfn() fails, we do not return an
> @@ -109,22 +106,11 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
> static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
> {
> struct udmabuf *ubuf = buf->priv;
> - struct page **pages;
> void *vaddr;
> - pgoff_t pg;
>
> dma_resv_assert_held(buf->resv);
>
> - pages = kvmalloc_objs(*pages, ubuf->pagecount);
> - if (!pages)
> - return -ENOMEM;
> -
> - for (pg = 0; pg < ubuf->pagecount; pg++)
> - pages[pg] = folio_page(ubuf->folios[pg],
> - ubuf->offsets[pg] >> PAGE_SHIFT);
> -
> - vaddr = vm_map_ram(pages, ubuf->pagecount, -1);
> - kvfree(pages);
> + vaddr = vm_map_ram(ubuf->pages, ubuf->pagecount, -1);
> if (!vaddr)
> return -EINVAL;
>
> @@ -146,22 +132,18 @@ static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf,
> {
> struct udmabuf *ubuf = buf->priv;
> struct sg_table *sg;
> - struct scatterlist *sgl;
> - unsigned int i = 0;
> int ret;
>
> sg = kzalloc_obj(*sg);
> if (!sg)
> return ERR_PTR(-ENOMEM);
>
> - ret = sg_alloc_table(sg, ubuf->pagecount, GFP_KERNEL);
> + ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->pagecount, 0,
> + ubuf->pagecount << PAGE_SHIFT,
> + GFP_KERNEL);
> if (ret < 0)
> goto err_alloc;
>
> - for_each_sg(sg->sgl, sgl, ubuf->pagecount, i)
> - sg_set_folio(sgl, ubuf->folios[i], PAGE_SIZE,
> - ubuf->offsets[i]);
> -
> ret = dma_map_sgtable(dev, sg, direction, 0);
> if (ret < 0)
> goto err_map;
> @@ -207,12 +189,8 @@ static void unpin_all_folios(struct udmabuf *ubuf)
>
> static __always_inline int init_udmabuf(struct udmabuf *ubuf, pgoff_t pgcnt)
> {
> - ubuf->folios = kvmalloc_objs(*ubuf->folios, pgcnt);
> - if (!ubuf->folios)
> - return -ENOMEM;
> -
> - ubuf->offsets = kvzalloc_objs(*ubuf->offsets, pgcnt);
> - if (!ubuf->offsets)
> + ubuf->pages = kvmalloc_objs(*ubuf->pages, pgcnt);
> + if (!ubuf->pages)
> return -ENOMEM;
>
> ubuf->pinned_folios = kvmalloc_objs(*ubuf->pinned_folios, pgcnt);
> @@ -225,8 +203,7 @@ static __always_inline int init_udmabuf(struct udmabuf *ubuf, pgoff_t pgcnt)
> static __always_inline void deinit_udmabuf(struct udmabuf *ubuf)
> {
> unpin_all_folios(ubuf);
> - kvfree(ubuf->offsets);
> - kvfree(ubuf->folios);
> + kvfree(ubuf->pages);
> }
>
> static void release_udmabuf(struct dma_buf *buf)
> @@ -344,8 +321,8 @@ static long udmabuf_pin_folios(struct udmabuf *ubuf, struct file *memfd,
> ubuf->pinned_folios[nr_pinned++] = folios[cur_folio];
>
> for (; subpgoff < fsize; subpgoff += PAGE_SIZE) {
> - ubuf->folios[upgcnt] = folios[cur_folio];
> - ubuf->offsets[upgcnt] = subpgoff;
> + ubuf->pages[upgcnt] = folio_page(folios[cur_folio],
> + subpgoff >> PAGE_SHIFT);
> ++upgcnt;
>
> if (++cur_pgcnt >= pgcnt)
>
Use clear_pages() and clear_highpage() properly in the
DMA heap allocator.
Signed-off-by: Linus Walleij <linusw(a)kernel.org>
---
Changes in v2:
- Added a second patch to use the clear_highpage() helper.
- Link to v1: https://lore.kernel.org/r/20260304-cma-heap-clear-pages-v1-1-6ff59da716d3@k…
---
Linus Walleij (2):
dma-buf: heaps: Clear CMA pages with clear_pages()
dma-buf: heaps: Clear CMA highages using helper
drivers/dma-buf/heaps/cma_heap.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260303-cma-heap-clear-pages-540f3ac9f734
Best regards,
--
Linus Walleij <linusw(a)kernel.org>