Thread (16 messages) flat view 16 messages, 2 authors, 3d ago

Re: [PATCH v7 6/9] media: chips-media: wave6: Improve debugging capabilities

From: sashiko-bot@kernel.org
Date: 2026-09-04 07:02:33

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] Lockless call to `vb2_get_num_buffers()` in debugfs read leads to use-after-free on `q->bufs_bitmap`.
- [Medium] Multiplication can overflow 32-bit bounds before assignment to a 64-bit variable in the debugfs FPS calculation.
- [Low] Direct use of 64-bit division and modulo operators (`/` and `%`) will cause build failures on 32-bit architectures.

Pre-existing issues:
- [High] Unprotected iteration over V4L2 mem2mem ready queues without holding `rdy_spinlock` leads to list corruption.
--

commit a789f4b587c983369a5ba74d2b58395c60628047
Author: Nas Chung [off-list ref]

media: chips-media: wave6: Improve debugging capabilities

This commit adds debugfs entries and trace events to provide detailed
debugging information for the Wave6 core driver.

Tested-by: Ming Qian <redacted>
Tested-by: Marek Vasut <redacted>
quoted hunk ↗ jump to hunk
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
new file mode 100644
index 0000000000000..ae71edeae0888
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
[ ... ]
+	vq = v4l2_m2m_get_src_vq(inst->v4l2_fh.m2m_ctx);
+	seq_printf(s, "output (%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+		   vb2_is_streaming(vq),
+		   vb2_get_num_buffers(vq),
[Severity: High]
Does this locklessly access `q->bufs_bitmap`? Concurrently, an application
can execute `VIDIOC_REQBUFS` with count=0, which acquires the queue lock,
frees `q->bufs_bitmap`, and sets the pointer to NULL. Because this read
doesn't hold `m2m_ctx->q_lock` or equivalent synchronization, it could read
a non-NULL pointer right before it is freed by `REQBUFS`, executing
`bitmap_weight()` on a freed pointer and causing a use-after-free.
+		   inst->src_fmt.pixelformat,
[ ... ]
+	vq = v4l2_m2m_get_dst_vq(inst->v4l2_fh.m2m_ctx);
+	seq_printf(s, "capture(%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+		   vb2_is_streaming(vq),
+		   vb2_get_num_buffers(vq),
[Severity: High]
This appears to have the same lockless access concern as the source queue
above. Does this need queue lock protection to prevent a use-after-free
if `VIDIOC_REQBUFS` is called concurrently?
+		   inst->dst_fmt.pixelformat,
[ ... ]
+	seq_puts(s, "fps");
+	tmp = MSEC_PER_SEC * inst->processed_buf_num;
[Severity: Medium]
Will this operation overflow on 32-bit architectures? `MSEC_PER_SEC` is
typically defined as `1000L` (a 32-bit signed integer on 32-bit systems) and
`inst->processed_buf_num` is a `u32`. If the buffer count exceeds ~4.29
million, the 32-bit multiplication might overflow before it is assigned and
sign-extended into the 64-bit `tmp` variable.
+	if (perf->ts_last > perf->ts_first + NSEC_PER_MSEC) {
+		fps = DIV_ROUND_CLOSEST(tmp, (perf->ts_last - perf->ts_first) / NSEC_PER_MSEC);
[Severity: Low]
Does this cause a build failure on 32-bit architectures? `DIV_ROUND_CLOSEST`
internally expands to a division operation (`/`), and the denominator here
also uses direct division. Using direct 64-bit division on `s64` variables
emits calls to undefined functions like `__divdi3` on 32-bit systems. Should
explicit 64-bit math helpers like `div64_s64()` be used here instead?
+		seq_printf(s, " actual: %lld;", fps);
+	}
+	duration = perf->total_sw_time / NSEC_PER_MSEC;
[Severity: Low]
Similar to the above, this performs direct 64-bit division on a `u64`
variable, which can break 32-bit builds due to missing math symbols.
+	if (duration > 0) {
+		fps = DIV_ROUND_CLOSEST(tmp, duration);
+		seq_printf(s, " sw: %lld;", fps);
+	}
+	duration = perf->total_hw_time / NSEC_PER_MSEC;
[Severity: Low]
Another instance of direct 64-bit division that might break 32-bit builds.
+	if (duration > 0) {
+		fps = DIV_ROUND_CLOSEST(tmp, duration);
+		seq_printf(s, " hw: %lld", fps);
+	}
+	seq_putc(s, '\n');
+
+	seq_printf(s, "latency(ms) first: %llu.%06llu, max %llu.%06llu, setup %llu.%06llu\n",
+		   perf->latency_first / NSEC_PER_MSEC,
+		   perf->latency_first % NSEC_PER_MSEC,
[Severity: Low]
This performs direct 64-bit division and modulo on an `s64` variable, which
is known to cause linking errors (like `__moddi3` and `__moddi3`) on 32-bit
architectures. Should this use explicit math helpers like `div64_s64_rem()`?


[Severity: High]
This is a pre-existing issue, but the series iterates over the V4L2 m2m ready
queues locklessly using `v4l2_m2m_for_each_src_buf` and
`v4l2_m2m_for_each_dst_buf` without holding `rdy_spinlock`.

For example, in drivers/media/platform/chips-media/wave6/wave6-vpu-enc.c:

wave6_get_valid_src_buf() {
    ...
    v4l2_m2m_for_each_src_buf(inst->v4l2_fh.m2m_ctx, v4l2_m2m_buf) {
    ...
}

And in drivers/media/platform/chips-media/wave6/wave6-vpu-v4l2.c:

wave6_get_dst_buf_by_addr() {
    ...
    v4l2_m2m_for_each_dst_buf(inst->v4l2_fh.m2m_ctx, v4l2_m2m_buf) {
    ...
}

Are these list traversals vulnerable to data races? These macros wrap
`list_for_each_entry`, and they appear to be called from the m2m framework's
worker thread without holding `rdy_spinlock`. Concurrently, userspace can
call `VIDIOC_QBUF`, which dynamically adds elements to the `rdy_queue` while
holding the lock. Modifying a linked list while a separate thread traverses
it unprotected can result in structural data races and list pointer
corruption, potentially leading to a use-after-free or kernel panic.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1788496816.git.nas.chung@chipsnmedia.com?part=6
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help