* [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes
@ 2026-10-23 19:55 Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 01/11] media: intel/ipu6: move busy check to ipu6_isys_vidioc_s_fmt_vid_cap() Valerii Sokolov
` (11 more replies)
0 siblings, 12 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
This series fixes bugs in the Intel IPU6 input system (ISYS), Buttress,
DMA/MMU and firmware interface code:
1 Move the vb2_is_busy() check from VIDIOC_TRY_FMT to VIDIOC_S_FMT, so
TRY_FMT never returns -EBUSY and S_FMT can no longer overwrite
av->pix_fmt with an unvalidated format while buffers are allocated.
2 Return firmware message buffers to the free pool when sending a
stream start or capture command fails.
3 Bound the number of input and output pins in
ipu6_isys_fw_pin_cfg().
4 Clamp the crop top offset in ipu6_isys_csi2_set_sel().
5 Only call auxiliary device ISRs for interrupts that belong to them.
6 Release the firmware context when ipu6_fw_com_open() fails.
7-10 DMA/MMU fixes: an IOVA leak and a silently ignored mapping failure
in the scatterlist mapping helpers, a missing DMA unmap of the dummy
L2 page table, and a dev_err(NULL, ...).
11 Log the correct frame sequence number on EOF (debug only).
Patches 1, 3, 4 and 8 are tagged for stable. The other fixes address
bounded leaks or cosmetic issues.
The IPU7 code recently added to this driver appears to have the same
issues as patches 3 and 11 (ipu7_isys_fw_pin_cfg() and
ipu7_isys_isr_one()). I have left those alone as I have no IPU7 hardware
to test on.
Testing: each patch was build-tested with W=1 on top of
media-committers/next, and the series was runtime-tested on a Raptor
Lake laptop (Lenovo ThinkPad X1 Carbon Gen 11, OV2740 sensor).
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
Valerii Sokolov (11):
media: intel/ipu6: move busy check to ipu6_isys_vidioc_s_fmt_vid_cap()
media: intel/ipu6: fix firmware message buffer leak on send failure
media: intel/ipu6: check pin bounds in ipu6_isys_fw_pin_cfg()
media: intel/ipu6: clamp crop top offset in ipu6_isys_csi2_set_sel()
media: intel/ipu6: check irq_status mask before calling subdevice ISR
media: intel/ipu6: clean up fwctx on ipu6_fw_com_open() failure
media: intel/ipu6: fix IOVA leak on first entry failure in
ipu6_dma_map_sg()
media: intel/ipu6: return an error from ipu6_dma_map_sgtable() on
failure
media: intel/ipu6: unmap the dummy L2 page table in ipu6_mmu_destroy()
media: intel/ipu6: pass the device to dev_err() in ipu6_mmu_unmap()
media: intel/ipu6: fix EOF sequence logging in ipu6_isys_isr_one()
drivers/media/pci/intel/ipu6/ipu6-buttress.c | 3 ++-
drivers/media/pci/intel/ipu6/ipu6-dma.c | 9 ++++++---
drivers/media/pci/intel/ipu6/ipu6-fw-isys.c | 10 ++++++++--
drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 2 ++
drivers/media/pci/intel/ipu6/ipu6-isys-queue.c | 4 +++-
drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 7 ++++---
drivers/media/pci/intel/ipu6/ipu6-mmu.c | 5 +++--
7 files changed, 28 insertions(+), 12 deletions(-)
base-commit: d7e7bca7169873b46e857c025c10f3336c1258d8
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 01/11] media: intel/ipu6: move busy check to ipu6_isys_vidioc_s_fmt_vid_cap()
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 02/11] media: intel/ipu6: fix firmware message buffer leak on send failure Valerii Sokolov
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
ipu6_isys_vidioc_try_fmt_vid_cap() rejected calls with -EBUSY when
buffers were allocated on the queue (vb2_is_busy()), although the V4L2
specification states that VIDIOC_TRY_FMT can be called at any time and
never returns EBUSY.
Conversely, ipu6_isys_vidioc_s_fmt_vid_cap() lacked the vb2_is_busy()
check (unlike ipu6_isys_vidioc_s_fmt_meta_cap()) and ignored the return
value of ipu6_isys_vidioc_try_fmt_vid_cap(). As a result, when a client
issued VIDIOC_S_FMT while the queue was busy, try_fmt returned -EBUSY
before clamping fields or computing bytesperline and sizeimage, and
s_fmt copied the unvalidated user format into av->pix_fmt.
Corrupting av->pix_fmt while buffers are allocated breaks subsequent
buffer preparation in ipu6_isys_buf_prepare(): if user-space left
sizeimage as 0, the size > vb2_plane_size(vb, 0) check is bypassed and a
mismatched bytesperline * height passed to vb2_set_plane_payload() can
trigger WARN_ON_ONCE(size > vb->planes[plane_no].length), or if
VIDIOC_STREAMON follows, program the firmware to DMA a larger frame into
smaller buffers.
Move the vb2_is_busy() check from ipu6_isys_vidioc_try_fmt_vid_cap() to
ipu6_isys_vidioc_s_fmt_vid_cap(), matching the meta capture callbacks.
Fixes: 3c1dfb5a69cf ("media: intel/ipu6: input system video nodes and buffer queues")
Cc: stable@vger.kernel.org
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 129016e574..f394e78db6 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -290,9 +290,6 @@ static int ipu6_isys_vidioc_try_fmt_vid_cap(struct file *file, void *fh,
{
struct ipu6_isys_video *av = video_drvdata(file);
- if (vb2_is_busy(&av->aq.vbq))
- return -EBUSY;
-
__ipu6_isys_vidioc_try_fmt_vid_cap(av, f);
return 0;
@@ -324,6 +321,9 @@ static int ipu6_isys_vidioc_s_fmt_vid_cap(struct file *file, void *fh,
{
struct ipu6_isys_video *av = video_drvdata(file);
+ if (vb2_is_busy(&av->aq.vbq))
+ return -EBUSY;
+
ipu6_isys_vidioc_try_fmt_vid_cap(file, fh, f);
av->pix_fmt = f->fmt.pix;
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 02/11] media: intel/ipu6: fix firmware message buffer leak on send failure
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 01/11] media: intel/ipu6: move busy check to ipu6_isys_vidioc_s_fmt_vid_cap() Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 03/11] media: intel/ipu6: check pin bounds in ipu6_isys_fw_pin_cfg() Valerii Sokolov
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
ipu6_get_fw_msg_buf() moves a message buffer from isys->framebuflist to
isys->framebuflist_fw. Buffers carrying a frame capture command are
returned to the free pool when the firmware reports
IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_READY for them.
If sending the command fails, in ipu6_isys_start_stream_firmware() via
fw_ops->stream_start() or in buf_queue() via fw_ops->stream_capture(),
the firmware never sees it: both the IPU6 and the IPU7 send paths return
an error before committing a queue token. No PIN_DATA_READY response
will ever arrive, so the buffer stays on framebuflist_fw until
ipu6_cleanup_fw_msg_bufs() reclaims it on the next runtime resume, and
ipu6_get_fw_msg_buf() has to allocate new buffers in the meantime.
Return the buffer to the free pool when sending the command fails.
Buffers whose command was sent, but whose stream start then timed out or
failed, are deliberately left alone: the firmware may still own them,
and they are reclaimed on the next runtime resume.
Fixes: 3c1dfb5a69cf ("media: intel/ipu6: input system video nodes and buffer queues")
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-isys-queue.c | 4 +++-
drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index 23d00e1f89..7a38feb911 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -359,8 +359,10 @@ static void buf_queue(struct vb2_buffer *vb)
ipu6_isys_buffer_list_queue(&bl, IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0);
ret = fw_ops->stream_capture(stream->isys, stream->stream_handle, msg);
- if (ret < 0)
+ if (ret < 0) {
dev_err(dev, "send stream capture failed\n");
+ ipu6_put_fw_msg_buf(stream->isys, msg);
+ }
out:
mutex_unlock(&stream->mutex);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index f394e78db6..c7e2dc1311 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -538,6 +538,7 @@ int ipu6_isys_start_stream_firmware(struct ipu6_isys_stream *stream,
capture);
if (ret < 0) {
dev_err(dev, "can't start streaming (%d)\n", ret);
+ ipu6_put_fw_msg_buf(stream->isys, msg);
goto out_stream_close;
}
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 03/11] media: intel/ipu6: check pin bounds in ipu6_isys_fw_pin_cfg()
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 01/11] media: intel/ipu6: move busy check to ipu6_isys_vidioc_s_fmt_vid_cap() Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 02/11] media: intel/ipu6: fix firmware message buffer leak on send failure Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 04/11] media: intel/ipu6: clamp crop top offset in ipu6_isys_csi2_set_sel() Valerii Sokolov
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
In ipu6_isys_fw_pin_cfg(), cfg->nof_input_pins and cfg->nof_output_pins
are incremented without checking them against IPU6_MAX_IPINS and
IPU6_MAX_OPINS. If more video nodes are attached to a firmware stream
than the firmware ABI supports, the function writes past the end of
cfg->input_pins[] and cfg->output_pins[] in the firmware message buffer.
Validate cfg->nof_input_pins and cfg->nof_output_pins before
incrementing them.
Fixes: 3c1dfb5a69cf ("media: intel/ipu6: input system video nodes and buffer queues")
Cc: stable@vger.kernel.org
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-fw-isys.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
index 56bb67869b..a36d64bcb9 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
@@ -778,10 +778,15 @@ static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av,
ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
struct v4l2_rect v4l2_crop;
struct ipu6_isys *isys = av->isys;
- int input_pins = cfg->nof_input_pins++;
+ int input_pins;
int output_pins;
u32 src_stream;
+ if (cfg->nof_input_pins >= IPU6_MAX_IPINS ||
+ cfg->nof_output_pins >= IPU6_MAX_OPINS)
+ return -ENOSPC;
+
+ input_pins = cfg->nof_input_pins++;
src_stream = __ipu6_isys_get_src_stream_by_src_pad(state, src_pad->index);
fmt = v4l2_subdev_state_get_format(state, src_pad->index, src_stream);
v4l2_crop = *v4l2_subdev_state_get_crop(state, src_pad->index, src_stream);
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 04/11] media: intel/ipu6: clamp crop top offset in ipu6_isys_csi2_set_sel()
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (2 preceding siblings ...)
2026-10-23 19:55 ` [PATCH v1 03/11] media: intel/ipu6: check pin bounds in ipu6_isys_fw_pin_cfg() Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 05/11] media: intel/ipu6: check irq_status mask before calling subdevice ISR Valerii Sokolov
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
In ipu6_isys_csi2_set_sel(), sel->r.height is clamped with:
clamp(sel->r.height & ~1, IPU6_ISYS_MIN_HEIGHT,
sink_ffmt->height - sel->r.top);
However, user space supplies sel->r.top (__s32) without bounds checking,
while sink_ffmt->height is __u32. If sel->r.top is negative or greater
than sink_ffmt->height - IPU6_ISYS_MIN_HEIGHT, the unsigned upper bound
sink_ffmt->height - sel->r.top either becomes 0 (smaller than the lower
bound IPU6_ISYS_MIN_HEIGHT, violating clamp()'s lo <= hi invariant) or
wraps around in u32 to a value larger than sink_ffmt->height (allowing
sel->r.height to exceed sink_ffmt->height and storing an out-of-bounds
crop->top offset).
Clamp sel->r.top to [0, sink_ffmt->height - IPU6_ISYS_MIN_HEIGHT] before
aligning it and calculating the allowed crop height range.
Fixes: a11a5570a09d ("media: intel/ipu6: add IPU6 CSI2 receiver v4l2 sub-device")
Cc: stable@vger.kernel.org
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index 1525454279..a2491729d3 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -821,6 +821,8 @@ static int ipu6_isys_csi2_set_sel(struct v4l2_subdev *sd,
/* Only vertical cropping is supported */
sel->r.left = 0;
sel->r.width = sink_ffmt->width;
+ sel->r.top = clamp_t(s32, sel->r.top, 0,
+ sink_ffmt->height - IPU6_ISYS_MIN_HEIGHT);
/* Non-bayer formats can't be single line cropped */
if (!ipu6_isys_is_bayer_format(sink_ffmt->code))
sel->r.top &= ~1;
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 05/11] media: intel/ipu6: check irq_status mask before calling subdevice ISR
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (3 preceding siblings ...)
2026-10-23 19:55 ` [PATCH v1 04/11] media: intel/ipu6: clamp crop top offset in ipu6_isys_csi2_set_sel() Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 06/11] media: intel/ipu6: clean up fwctx on ipu6_fw_com_open() failure Valerii Sokolov
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
In ipu6_buttress_isr(), ipu6_buttress_call_isr(adev[i]) is called at the
start of each loop iteration, before checking whether irq_status has the
corresponding auxiliary device interrupt bit (adev_irq_mask[i]) set.
As a result, the ISYS and PSYS ISRs run on every Buttress interrupt
regardless of its source, and their return value is then discarded by
the continue statement. For the ISYS this means ipu6_isys_isr() taking a
runtime PM reference, masking and unmasking the UNISPART interrupts and
draining the firmware response queue on interrupts not meant for it.
Check irq_status against adev_irq_mask[i] before calling
ipu6_buttress_call_isr(adev[i]).
Fixes: ab29a2478e70 ("media: intel/ipu6: add IPU6 buttress interface driver")
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-buttress.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
index f1d236054c..debc4ac929 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
@@ -364,11 +364,12 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
writel(irq_status, isp->base + regs->irq_clear);
for (i = 0; i < ARRAY_SIZE(adev_irq_mask); i++) {
- irqreturn_t r = ipu6_buttress_call_isr(adev[i]);
+ irqreturn_t r;
if (!(irq_status & adev_irq_mask[i]))
continue;
+ r = ipu6_buttress_call_isr(adev[i]);
if (r == IRQ_WAKE_THREAD) {
ret = IRQ_WAKE_THREAD;
disable_irqs |= adev_irq_mask[i];
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 06/11] media: intel/ipu6: clean up fwctx on ipu6_fw_com_open() failure
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (4 preceding siblings ...)
2026-10-23 19:55 ` [PATCH v1 05/11] media: intel/ipu6: check irq_status mask before calling subdevice ISR Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 07/11] media: intel/ipu6: fix IOVA leak on first entry failure in ipu6_dma_map_sg() Valerii Sokolov
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
In ipu6_fw_isys_init(), if ipu6_fw_com_open(isys->fwctx) fails after
ipu6_fw_com_prepare() has allocated the syscom context and its DMA
buffer, the function returns the error without calling
ipu6_fw_isys_cleanup(isys), leaving isys->fwctx allocated until the next
runtime resume attempt cleans it up.
Call ipu6_fw_isys_cleanup(isys) when ipu6_fw_com_open() fails.
Fixes: f625e8d7ffc1 ("media: intel/ipu6: input system ABI between firmware and driver")
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-fw-isys.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
index a36d64bcb9..5d95fb9234 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
@@ -350,6 +350,7 @@ static int ipu6_fw_isys_init(struct ipu6_isys *isys, unsigned int num_streams)
ret = ipu6_fw_com_open(isys->fwctx);
if (ret) {
dev_err(dev, "isys fw com open failed %d\n", ret);
+ ipu6_fw_isys_cleanup(isys);
return ret;
}
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 07/11] media: intel/ipu6: fix IOVA leak on first entry failure in ipu6_dma_map_sg()
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (5 preceding siblings ...)
2026-10-23 19:55 ` [PATCH v1 06/11] media: intel/ipu6: clean up fwctx on ipu6_fw_com_open() failure Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 08/11] media: intel/ipu6: return an error from ipu6_dma_map_sgtable() on failure Valerii Sokolov
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
If ipu6_mmu_map() fails for the first scatterlist entry,
ipu6_dma_map_sg() calls ipu6_dma_unmap_sg() with nents == 0. That
returns immediately, so the IOVA range allocated with alloc_iova() is
never freed.
Free the IOVA directly when no entry has been mapped yet.
Fixes: 9163d83573e4 ("media: intel/ipu6: add IPU6 DMA mapping API and MMU table")
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-dma.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.c b/drivers/media/pci/intel/ipu6/ipu6-dma.c
index 90f530a937..a923a1e4bd 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-dma.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.c
@@ -444,7 +444,10 @@ int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
return nents;
out_fail:
- ipu6_dma_unmap_sg(sys, sglist, i, dir, attrs);
+ if (i)
+ ipu6_dma_unmap_sg(sys, sglist, i, dir, attrs);
+ else
+ __free_iova(&mmu->dmap->iovad, iova);
return 0;
}
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 08/11] media: intel/ipu6: return an error from ipu6_dma_map_sgtable() on failure
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (6 preceding siblings ...)
2026-10-23 19:55 ` [PATCH v1 07/11] media: intel/ipu6: fix IOVA leak on first entry failure in ipu6_dma_map_sg() Valerii Sokolov
@ 2026-10-23 19:55 ` Valerii Sokolov
2026-10-23 19:56 ` [PATCH v1 09/11] media: intel/ipu6: unmap the dummy L2 page table in ipu6_mmu_destroy() Valerii Sokolov
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:55 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
ipu6_dma_map_sg() returns 0 when ipu6_mmu_map() fails, but
ipu6_dma_map_sgtable() only treats negative values as errors. On failure
it therefore sets sgt->nents to 0 and returns success, and callers such
as ipu6_isys_buf_init() and ipu6_map_fw_region() go on to hand the
hardware an address that is not mapped in the IPU MMU.
Return -ENOMEM when ipu6_dma_map_sg() maps no entries.
Fixes: daabc5c64703 ("media: ipu6: not override the dma_ops of device in driver")
Cc: stable@vger.kernel.org
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-dma.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.c b/drivers/media/pci/intel/ipu6/ipu6-dma.c
index a923a1e4bd..37b5c25259 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-dma.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.c
@@ -459,8 +459,8 @@ int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
int nents;
nents = ipu6_dma_map_sg(sys, sgt->sgl, sgt->nents, dir, attrs);
- if (nents < 0)
- return nents;
+ if (nents <= 0)
+ return nents < 0 ? nents : -ENOMEM;
sgt->nents = nents;
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 09/11] media: intel/ipu6: unmap the dummy L2 page table in ipu6_mmu_destroy()
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (7 preceding siblings ...)
2026-10-23 19:55 ` [PATCH v1 08/11] media: intel/ipu6: return an error from ipu6_dma_map_sgtable() on failure Valerii Sokolov
@ 2026-10-23 19:56 ` Valerii Sokolov
2026-10-23 19:56 ` [PATCH v1 10/11] media: intel/ipu6: pass the device to dev_err() in ipu6_mmu_unmap() Valerii Sokolov
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:56 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
ipu6_mmu_destroy() frees mmu_info->dummy_l2_pt with free_page() instead
of the existing free_dummy_l2_pt() helper, so the streaming DMA mapping
of the dummy L2 page table (mmu_info->dummy_l2_pteval) is never unmapped
when the MMU is torn down.
Use free_dummy_l2_pt().
Fixes: 9163d83573e4 ("media: intel/ipu6: add IPU6 DMA mapping API and MMU table")
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-mmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
index 1a564ceb74..b1c34964ce 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-mmu.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
@@ -668,7 +668,7 @@ static void ipu6_mmu_destroy(struct ipu6_mmu *mmu)
free_dummy_page(mmu_info);
dma_unmap_single(mmu_info->dev, TBL_PHYS_ADDR(mmu_info->l1_pt_dma),
PAGE_SIZE, DMA_BIDIRECTIONAL);
- free_page((unsigned long)mmu_info->dummy_l2_pt);
+ free_dummy_l2_pt(mmu_info);
free_page((unsigned long)mmu_info->l1_pt);
kfree(mmu_info);
}
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 10/11] media: intel/ipu6: pass the device to dev_err() in ipu6_mmu_unmap()
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (8 preceding siblings ...)
2026-10-23 19:56 ` [PATCH v1 09/11] media: intel/ipu6: unmap the dummy L2 page table in ipu6_mmu_destroy() Valerii Sokolov
@ 2026-10-23 19:56 ` Valerii Sokolov
2026-10-23 19:56 ` [PATCH v1 11/11] media: intel/ipu6: fix EOF sequence logging in ipu6_isys_isr_one() Valerii Sokolov
2026-10-30 9:05 ` [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Antti Laakso
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:56 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
ipu6_mmu_unmap() reports unaligned unmap requests with dev_err(NULL, ...),
which prints "(NULL device *)" instead of identifying the device. Use
mmu_info->dev.
Fixes: 9163d83573e4 ("media: intel/ipu6: add IPU6 DMA mapping API and MMU table")
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-mmu.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
index b1c34964ce..f21f3a1e53 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-mmu.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
@@ -593,7 +593,8 @@ void ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
* by the hardware
*/
if (!IS_ALIGNED(iova | size, min_pagesz)) {
- dev_err(NULL, "unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n",
+ dev_err(mmu_info->dev,
+ "unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n",
iova, size, min_pagesz);
return;
}
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 11/11] media: intel/ipu6: fix EOF sequence logging in ipu6_isys_isr_one()
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (9 preceding siblings ...)
2026-10-23 19:56 ` [PATCH v1 10/11] media: intel/ipu6: pass the device to dev_err() in ipu6_mmu_unmap() Valerii Sokolov
@ 2026-10-23 19:56 ` Valerii Sokolov
2026-10-30 9:05 ` [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Antti Laakso
11 siblings, 0 replies; 13+ messages in thread
From: Valerii Sokolov @ 2026-10-23 19:56 UTC (permalink / raw)
To: Sakari Ailus
Cc: Antti Laakso, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel,
Valerii Sokolov
When handling IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF in ipu6_isys_isr_one(),
stream->seq[stream->seq_index] is populated with the current sequence
(atomic_read(&stream->sequence) - 1) and stream->seq_index is immediately
advanced to the next ring buffer slot.
Subsequently, when IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF arrives, logging
stream->seq[stream->seq_index].sequence reads the next slot in the ring
buffer rather than the slot written at SOF (logging a stale sequence
number from IPU6_ISYS_MAX_PARALLEL_SOF - 1 frames ago, or 0 on the first
frame).
Read atomic_read(&stream->sequence) - 1 directly so the EOF debug message
logs the current frame sequence number matching SOF.
Fixes: f50c4ca0a820 ("media: intel/ipu6: add the main input system driver")
Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
---
drivers/media/pci/intel/ipu6/ipu6-fw-isys.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
index 5d95fb9234..ad08506b32 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
@@ -651,7 +651,7 @@ int ipu6_isys_isr_one(struct ipu6_bus_device *adev)
dev_dbg(&adev->auxdev.dev,
"eof: handle %d: (index %u), timestamp 0x%16.16llx\n",
resp->stream_handle,
- stream->seq[stream->seq_index].sequence, ts);
+ atomic_read(&stream->sequence) - 1, ts);
break;
case IPU6_FW_ISYS_RESP_TYPE_STATS_DATA_READY:
break;
--
2.56.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
` (10 preceding siblings ...)
2026-10-23 19:56 ` [PATCH v1 11/11] media: intel/ipu6: fix EOF sequence logging in ipu6_isys_isr_one() Valerii Sokolov
@ 2026-10-30 9:05 ` Antti Laakso
11 siblings, 0 replies; 13+ messages in thread
From: Antti Laakso @ 2026-10-30 9:05 UTC (permalink / raw)
To: Valerii Sokolov
Cc: Sakari Ailus, Sarang Sapre, Divyamani Tripathi, Manik Bajpai,
Mauro Carvalho Chehab, linux-media, linux-kernel
Hi Valerii,
On Fri, Oct 23, 2026 at 07:55:28PM +0000, Valerii Sokolov wrote:
> This series fixes bugs in the Intel IPU6 input system (ISYS), Buttress,
> DMA/MMU and firmware interface code:
>
> 1 Move the vb2_is_busy() check from VIDIOC_TRY_FMT to VIDIOC_S_FMT, so
> TRY_FMT never returns -EBUSY and S_FMT can no longer overwrite
> av->pix_fmt with an unvalidated format while buffers are allocated.
> 2 Return firmware message buffers to the free pool when sending a
> stream start or capture command fails.
> 3 Bound the number of input and output pins in
> ipu6_isys_fw_pin_cfg().
> 4 Clamp the crop top offset in ipu6_isys_csi2_set_sel().
> 5 Only call auxiliary device ISRs for interrupts that belong to them.
> 6 Release the firmware context when ipu6_fw_com_open() fails.
> 7-10 DMA/MMU fixes: an IOVA leak and a silently ignored mapping failure
> in the scatterlist mapping helpers, a missing DMA unmap of the dummy
> L2 page table, and a dev_err(NULL, ...).
> 11 Log the correct frame sequence number on EOF (debug only).
>
> Patches 1, 3, 4 and 8 are tagged for stable. The other fixes address
> bounded leaks or cosmetic issues.
>
> The IPU7 code recently added to this driver appears to have the same
> issues as patches 3 and 11 (ipu7_isys_fw_pin_cfg() and
> ipu7_isys_isr_one()). I have left those alone as I have no IPU7 hardware
> to test on.
>
> Testing: each patch was build-tested with W=1 on top of
> media-committers/next, and the series was runtime-tested on a Raptor
> Lake laptop (Lenovo ThinkPad X1 Carbon Gen 11, OV2740 sensor).
>
> Signed-off-by: Valerii Sokolov <valerii.sokolov@pm.me>
>
> Valerii Sokolov (11):
> media: intel/ipu6: move busy check to ipu6_isys_vidioc_s_fmt_vid_cap()
> media: intel/ipu6: fix firmware message buffer leak on send failure
> media: intel/ipu6: check pin bounds in ipu6_isys_fw_pin_cfg()
> media: intel/ipu6: clamp crop top offset in ipu6_isys_csi2_set_sel()
> media: intel/ipu6: check irq_status mask before calling subdevice ISR
> media: intel/ipu6: clean up fwctx on ipu6_fw_com_open() failure
> media: intel/ipu6: fix IOVA leak on first entry failure in
> ipu6_dma_map_sg()
> media: intel/ipu6: return an error from ipu6_dma_map_sgtable() on
> failure
> media: intel/ipu6: unmap the dummy L2 page table in ipu6_mmu_destroy()
> media: intel/ipu6: pass the device to dev_err() in ipu6_mmu_unmap()
> media: intel/ipu6: fix EOF sequence logging in ipu6_isys_isr_one()
>
> drivers/media/pci/intel/ipu6/ipu6-buttress.c | 3 ++-
> drivers/media/pci/intel/ipu6/ipu6-dma.c | 9 ++++++---
> drivers/media/pci/intel/ipu6/ipu6-fw-isys.c | 10 ++++++++--
> drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 2 ++
> drivers/media/pci/intel/ipu6/ipu6-isys-queue.c | 4 +++-
> drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 7 ++++---
> drivers/media/pci/intel/ipu6/ipu6-mmu.c | 5 +++--
> 7 files changed, 28 insertions(+), 12 deletions(-)
>
>
> base-commit: d7e7bca7169873b46e857c025c10f3336c1258d8
> --
> 2.56.0
>
>
Reviewed-by: Antti Laakso <antti.laakso@linux.intel.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-10-30 9:05 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-23 19:55 [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 01/11] media: intel/ipu6: move busy check to ipu6_isys_vidioc_s_fmt_vid_cap() Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 02/11] media: intel/ipu6: fix firmware message buffer leak on send failure Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 03/11] media: intel/ipu6: check pin bounds in ipu6_isys_fw_pin_cfg() Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 04/11] media: intel/ipu6: clamp crop top offset in ipu6_isys_csi2_set_sel() Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 05/11] media: intel/ipu6: check irq_status mask before calling subdevice ISR Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 06/11] media: intel/ipu6: clean up fwctx on ipu6_fw_com_open() failure Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 07/11] media: intel/ipu6: fix IOVA leak on first entry failure in ipu6_dma_map_sg() Valerii Sokolov
2026-10-23 19:55 ` [PATCH v1 08/11] media: intel/ipu6: return an error from ipu6_dma_map_sgtable() on failure Valerii Sokolov
2026-10-23 19:56 ` [PATCH v1 09/11] media: intel/ipu6: unmap the dummy L2 page table in ipu6_mmu_destroy() Valerii Sokolov
2026-10-23 19:56 ` [PATCH v1 10/11] media: intel/ipu6: pass the device to dev_err() in ipu6_mmu_unmap() Valerii Sokolov
2026-10-23 19:56 ` [PATCH v1 11/11] media: intel/ipu6: fix EOF sequence logging in ipu6_isys_isr_one() Valerii Sokolov
2026-10-30 9:05 ` [PATCH v1 00/11] media: intel/ipu6: bounds, leak, and error handling fixes Antti Laakso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®