Linux Media Controller development
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 6.18-5.10] media: em28xx: use vb2_video_unregister_device
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
@ 2026-10-19 13:46 ` Sasha Levin
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: requeue buffers if start_streaming fails Sasha Levin
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
  To: patches, stable
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Sasha Levin, mchehab,
	linux-media, linux-kernel

From: Hans Verkuil <hverkuil+cisco@kernel.org>

[ Upstream commit 7c8bf63b79371f5b57da1bd1401bd420180ac6e6 ]

Use vb2_video_unregister_device instead of video_unregister_device
to ensure any streaming is correctly stopped at unregister time.

Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit message forensics

**Step 1.1: Subject line**
Record: `[media: em28xx] [use] switch unregister to
vb2_video_unregister_device so streaming is stopped at unbind`

**Step 1.2: Tags**
Record:
- `Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (author;
  V4L2/videobuf2 maintainer)
- `Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (author tested;
  not an independent tester)
- `Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>`
  (media maintainer)
- No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable`, `Reviewed-by:`, or
  `Acked-by:`
- Absence of `Fixes:` / `Cc: stable` is expected for this review and is
  not treated as a negative

**Step 1.3: Body**
Record:
- Bug: `video_unregister_device()` does not stop an active vb2 queue, so
  streaming can continue after the video node is unregistered.
- Symptom: capture still running across USB unbind / module unload /
  probe rollback.
- Root cause (from message + helper docs): drivers that use
  `_vb2_fop_release()` must use `vb2_video_unregister_device()` so the
  queue is released at unregister time.
- No stack trace, reproducer, or version range in the message.

**Step 1.4: Hidden bug fix?**
Record: Yes. “Use helper X” is a correctness fix, not a feature. The
cover letter for the series is titled “fix lifecycle issues” and says
this patch “ensures all streaming is stopped when the video device is
unregistered.”

## Phase 2: Diff analysis

**Step 2.1: Inventory**
Record:
- File: `drivers/media/usb/em28xx/em28xx-video.c` (+6 / -6)
- Functions: `em28xx_v4l2_fini()`, `em28xx_v4l2_init()` error path
  `unregister_dev`
- Six call sites: radio / VBI / video, in both fini and probe-error
  teardown
- Scope: single-file surgical substitution

**Step 2.2: Code flow**
Record:
- Before: `video_unregister_device()` only removes the node; the vb2
  queue can remain in STREAMING.
- After: `vb2_video_unregister_device()` unregisters, then
  `vb2_queue_release()` (under the queue lock) which runs
  `stop_streaming` and returns buffers.
- Paths: USB disconnect / module unload (`em28xx_v4l2_fini`) and init
  failure (`unregister_dev`).

**Step 2.3: Bug mechanism**
Record: `[logic / lifecycle] [use-after-unbind]`
Verified disconnect order in this tree:

1. `em28xx_usb_disconnect()` sets `disconnected`, then
   `em28xx_close_extension()` → `em28xx_v4l2_fini()`.
2. fini already calls `em28xx_uninit_usb_xfer()`, then unregisters
   nodes.
3. Then `em28xx_release_resources()` unregisters I2C and
   `usb_put_dev()`.
4. Userspace may still hold the fd. Close calls `em28xx_v4l2_close()` →
   `_vb2_fop_release()` → `vb2_queue_release()` →
   `em28xx_stop_streaming()`.
5. `em28xx_stop_streaming()` does `v4l2_device_call_all(..., video,
   s_stream, 0)` and `em28xx_uninit_usb_xfer()`. That runs **after**
   I2C/USB teardown if the queue was not stopped in fini.

Stopping the queue in fini keeps `stop_streaming` on the unbind side of
I2C/USB teardown.

**Step 2.4: Fix quality**
Record:
- For video and VBI this is the documented vb2 pattern
  (`include/media/videobuf2-v4l2.h`: drivers using `_vb2_fop_release()`
  should use this helper). `em28xx_v4l2_close()` does call
  `_vb2_fop_release()`.
- Video/VBI set `vdev->queue` (`vb_vidq` / `vb_vbiq`).
- Radio never sets `vdev->queue`. The helper does
  `WARN_ON(!vdev->queue)` then still calls `video_unregister_device()`.
  Two boards have radio (`EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE`,
  `EM2860_BOARD_KAIOMY_TVNPC_U2`).
- Probe error path: `vdev->queue` is assigned **before**
  `em28xx_vb2_setup()` / `vb2_queue_init()`. `unregister_dev` after a
  later `video_register_device()` or media-graph failure can call
  `vb2_queue_release()` on a zeroed queue (`mutex_lock(&q->mmap_lock)`
  in `vb2_core_queue_release()`). That is a real, but rare, teardown
  hazard.
- No API/feature additions. Regression risk is low on the disconnect
  path (queue is initialized); radio WARN_ON and probe-error queue
  release are the main nits.

## Phase 3: Git history

**Step 3.1: Blame**
Record:
- `video_unregister_device()` on these nodes comes from the
  embedded-`video_device` era (`d4352f3639d780`, 2015) and older Mauro
  unregister paths (2008/2013).
- Bug is long-standing, not new in 7.3.

**Step 3.2: Fixes: tag**
Record: None. Helper introduced in `f729ef5796d82` (2020, around v5.10).
`git merge-base --is-ancestor f729ef5796d82 HEAD` succeeds.

**Step 3.3: File history**
Record: Same-day series on this file:
1. `288254383674b` media: em28xx: use v4l2_device release callback
2. `de626073dfcbb` media: em28xx: drop 'users' field
3. `7c8bf63b79371` **this commit**
4. Later: `c132b07f7e585` (use-after-free of `dev->intf` in free),
   `67f87b104f4ef` (requeue on start_streaming failure)

This is standalone at the diff level (only a symbol change). Series
context: patch 1 deferred `v4l2_device_unregister()` until last close,
which makes a late `stop_streaming()` after I2C teardown more likely.
This tree already contains patches 1 and 2.

**Step 3.4: Author**
Record: Hans Verkuil is the V4L2/videobuf2 maintainer. He added the
helper in 2020 and converted au0828/usbtv/cxusb then (`24b5836dbd45b`).
em28xx was not in that conversion.

**Step 3.5: Prerequisites**
Record: Needs `vb2_video_unregister_device()` (present). Needs em28xx
vb2 video/VBI (present). `em28xx.h` already includes `videobuf2-v4l2.h`.
Can apply standalone. This tree already has the helper and the driver.

## Phase 4: Mailing list / external

**Step 4.1: Original discussion**
Record: `b4 dig -c 7c8bf63b79371` → https://patch.msgid.link/ad61b2c30cd
477599312e9d5c12045dcd05c8ecd.1779191683.git.hverkuil+cisco@kernel.org
Saved thread: `/tmp/em28xx-thread.mbox` (cover + 3 patches, **no
replies**).
`b4 dig -a`: **v1 only**. Cover: `[PATCH 0/3] media: em28xx: fix
lifecycle issues`. Quote: “the last patch switches
video_unregister_device to vb2_video_unregister_device: this ensures all
streaming is stopped when the video device is unregistered.” Also: “All
this still needs to be tested on real hardware” at send time; the merged
commit later has `Tested-by: Hans Verkuil`. No NAK, no `Cc: stable` in
review (there was no review mail).

WebFetch of lore returned 403. Thread content was recovered via `b4 dig
-m`.

**Step 4.2: Recipients (`b4 dig -w`)**
Record: Hans Verkuil, `linux-media@vger.kernel.org`, Mauricio Faria de
Oliveira `<mfo@igalia.com>`. No review mail in the mbox. Mauro applied
it.

**Step 4.3: Bug report**
Record: No `Reported-by` / syzbot / bugzilla. No independent user report
found in the thread.

**Step 4.4: Series**
Record: Explicit 3/3 of a lifecycle series. This hunk does not need
patches 1–2 to compile. Those two are already in this tree.

**Step 4.5: Stable list**
Record: UNVERIFIED. lore.kernel.org/stable was blocked (Anubis bot-
check). No stable discussion in the captured media thread.

## Phase 5: Semantic / call graph

**Step 5.1: Functions**
Record: `em28xx_v4l2_fini`, `em28xx_v4l2_init` (`unregister_dev`).
Callee: `vb2_video_unregister_device` → `video_unregister_device` +
`vb2_queue_release` → `em28xx_stop_streaming` /
`em28xx_stop_vbi_streaming`.

**Step 5.2: Callers**
Record:
- `em28xx_v4l2_fini` ← `em28xx_close_extension()` (`em28xx-core.c`) ←
  `em28xx_usb_disconnect()` (unplug) and `em28xx_unregister_extension()`
  (module unload).
- `unregister_dev` ← probe/init failures after a node is registered.

**Step 5.3: Callees**
Record: queue release, `stop_streaming`, `em28xx_uninit_usb_xfer`,
`v4l2_device_call_all(..., s_stream, 0)`.

**Step 5.4: Reachability**
Record: Yes. Unplug or `rmmod` while an analog capture app is streaming
is a normal USB-TV / webcam path. Unprivileged userspace can hold the
device open; unplug is a physical event.

**Step 5.5: Similar patterns**
Record: Same helper is used across USB/PCI/platform V4L2 drivers (uvc,
au0828, usbtv, saa7134, vivid, …). em28xx was a leftover vs the 2020 USB
conversion.

semcode MCP tools: not available; used `git grep` / file reads.

## Phase 6: This tree

**Step 6.1: Local tree and buggy code**
Record:
- `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`
- `make kernelversion` / Makefile → **7.3.0-rc4** (mainline, not an LTS
  branch)
- `git merge-base --is-ancestor 7c8bf63b79371 HEAD` → yes (already in
  this checkout)
- Driver, helper, and `_vb2_fop_release()` close path all exist here
- Bug class (unregister without stopping vb2) has been in em28xx since
  ~2015; it was not introduced after this tree

**Step 6.2: Backport difficulty**
Record: Clean apply on this codebase (already applied). Helper and
includes are present. No conflicting refactor of these call sites beyond
the same series.

**Step 6.3: Related fixes already here**
Record: Lifetime callback + drop-`users` are already here. No alternate
fix of these six call sites. Follow-up `67f87b104f4ef` is a different
start_streaming WARN, not a replacement for this change.

## Phase 7: Subsystem

**Step 7.1**
Record: `[drivers/media/usb/em28xx] [IMPORTANT]` — USB analog capture,
not core mm/net, but a long-lived in-tree driver with real hardware
users (`CONFIG_VIDEO_EM28XX` / `VIDEO_EM28XX_V4L2`).

**Step 7.2**
Record: Mature driver; recent work is lifecycle/vb2 correctness from the
V4L2 maintainer, not a new subsystem.

## Phase 8: Impact and risk

**Step 8.1: Who is affected**
Record: Users of em28xx USB capture sticks (Hauppauge, Empia, etc.),
analog video/VBI. Radio-only extra is two board entries.

**Step 8.2: Trigger**
Record: Unplug or unload while `/dev/video*` or VBI is streaming (or
open with a live queue). Common for USB TV/webcam. Unprivileged process
can keep the fd; disconnect is the trigger.

**Step 8.3: Failure mode**
Record: `stop_streaming` after I2C unregister / `usb_put_dev` → use of
torn-down USB/I2C, hung DQBUF, possible UAF. Severity **HIGH**. Not a
guaranteed panic on every unplug (URBs are already killed in fini), but
the decoder `s_stream(0)` and second uninit run too late.

**Step 8.4: Risk/benefit**
Record:
- Benefit: high for em28xx users who unplug while capturing; matches the
  documented vb2 unbind contract.
- Risk: low on the disconnect path (6 substitutions, helper used since
  2020). Medium-low on probe-error (uninitialized queue) and radio
  (`WARN_ON`).
- Ratio: benefit of stopping the queue at unbind outweighs those edge
  nits.

## Phase 9: Synthesis

**Step 9.1: Evidence**

FOR:
- Real unbind/lifecycle bug: vb2 stays STREAMING after node unregister;
  `stop_streaming` can run after I2C/USB teardown.
- Driver already uses `_vb2_fop_release()`; helper is the required API.
- Small (6 lines), no new API, helper present in this tree since 2020.
- V4L2 maintainer authored and tested; media maintainer applied.
- USB unplug while capturing is a realistic user path.
- Same conversion already done for sibling USB drivers.

AGAINST:
- No user crash log / syzbot.
- Patch 3/3 of a lifecycle series (self-contained, but series-scoped).
- Radio `WARN_ON(!queue)` on two boards.
- Probe `unregister_dev` can `vb2_queue_release()` before
  `vb2_queue_init()`.
- Cover letter originally said hardware testing was still pending (later
  `Tested-by` is the author).

UNRESOLVED:
- lore.kernel.org HTTP 403 / stable list Anubis block; no independent
  stable-thread confirmation beyond the mbox (which had no replies).

**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** for video/VBI disconnect; nits
   on radio/probe-error do not make the core change wrong. Tested-by
   author.
2. Real bug affecting users? **PASS** — verified disconnect vs close
   ordering.
3. Important (crash/UAF/unbind)? **PASS** — HIGH, use-after-unbind /
   late `s_stream` on torn-down I2C/USB.
4. Small and contained? **PASS** — 6 lines, one file.
5. No new features/APIs? **PASS**.
6. Applies to this tree? **PASS** — helper, includes, and call sites
   exist here.

**Step 9.3: Exception category**
Record: None (not an ID/quirk/DT/build/docs exception). It is a normal
small bugfix.

**Step 9.4: Decision**
This tree is 7.3-rc4 and already contains the helper and em28xx vb2
video. The change is a small, maintainer-tested fix for a real USB-
unbind lifecycle hole: without it, analog streaming is not stopped when
the node is unregistered, so `stop_streaming` can run after I2C/USB
teardown. That is in scope for this codebase and meets the stable bar.
Radio WARN_ON and a rare probe-error queue release are residual nits,
not reasons to keep the disconnect bug.

### What the commit solves for this tree
On em28xx analog capture, `em28xx_v4l2_fini()` (USB disconnect / module
unload) unregisters video/VBI with `video_unregister_device()` while the
vb2 queue can still be STREAMING. Close later stops the queue via
`_vb2_fop_release()`, but by then `em28xx_release_resources()` has
already dropped I2C and the USB device. Switching to
`vb2_video_unregister_device()` stops streaming during fini, while those
objects are still valid.

### Risk vs benefit
Benefit is a real unbind UAF/use-after-teardown hole on a commonly
unplugged USB capture driver. Risk is six call-site substitutions
through a helper that has been in this tree for years. Residual radio
WARN_ON and probe-error queue release are limited.

### Verification
- [Phase 1] Tags: author SOB + Tested-by Hans Verkuil, Mauro SOB; no
  Fixes/Reported-by/Link/Cc:stable
- [Phase 2] Diff: 6 `video_unregister_device` →
  `vb2_video_unregister_device` in `em28xx_v4l2_fini` and
  `unregister_dev`
- [Phase 2] Helper: `vb2_video_unregister_device()` unregisters then
  `vb2_queue_release()`; `WARN_ON(!vdev->queue)` confirmed
- [Phase 2] `radio_dev` never assigns `.queue`; video/VBI do (`em28xx-
  video.c` init)
- [Phase 2] `em28xx_v4l2_close()` calls `_vb2_fop_release(filp, NULL)`
- [Phase 2] `em28xx_stop_streaming()` calls `s_stream(0)` and
  `em28xx_uninit_usb_xfer()`
- [Phase 3] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37;
  kernelversion 7.3.0-rc4
- [Phase 3] Commit `7c8bf63b79371` is ancestor of HEAD; helper
  `f729ef5796d82` is ancestor
- [Phase 3] Series: `288254383674b`, `de626073dfcbb`, this commit; 2020
  USB conversion `24b5836dbd45b` skipped em28xx
- [Phase 4] `b4 dig -c 7c8bf63b79371`: lore msgid
  ad61b2c30cd477599312e9d5c12045dcd05c8ecd…; v1-only 3-patch “fix
  lifecycle issues”
- [Phase 4] mbox: cover + 3 patches, zero replies; `b4 dig -w`: linux-
  media + Mauricio Faria de Oliveira
- [Phase 4] WebFetch lore 403; stable lore Anubis-blocked — UNVERIFIED
  beyond mbox
- [Phase 5] fini callers: `em28xx_close_extension` ←
  `em28xx_usb_disconnect` / `em28xx_unregister_extension`
- [Phase 6] `em28xx.h` includes `videobuf2-v4l2.h`; radio boards Leadtek
  Winfast USB II Deluxe, Kaiomy TVnPC U2
- [Phase 8] Disconnect then `em28xx_release_resources()` does
  `em28xx_i2c_unregister` + `usb_put_dev` before last close
- UNVERIFIED: independent hardware test besides author’s Tested-by; any
  stable@ thread

**YES**

 drivers/media/usb/em28xx/em28xx-video.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index e0a69309687b0..e2907b56220b7 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -2243,17 +2243,17 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
 	if (video_is_registered(&v4l2->radio_dev)) {
 		dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
 			 video_device_node_name(&v4l2->radio_dev));
-		video_unregister_device(&v4l2->radio_dev);
+		vb2_video_unregister_device(&v4l2->radio_dev);
 	}
 	if (video_is_registered(&v4l2->vbi_dev)) {
 		dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
 			 video_device_node_name(&v4l2->vbi_dev));
-		video_unregister_device(&v4l2->vbi_dev);
+		vb2_video_unregister_device(&v4l2->vbi_dev);
 	}
 	if (video_is_registered(&v4l2->vdev)) {
 		dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
 			 video_device_node_name(&v4l2->vdev));
-		video_unregister_device(&v4l2->vdev);
+		vb2_video_unregister_device(&v4l2->vdev);
 	}
 
 	v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
@@ -2901,19 +2901,19 @@ static int em28xx_v4l2_init(struct em28xx *dev)
 		dev_info(&dev->intf->dev,
 			 "V4L2 device %s deregistered\n",
 			 video_device_node_name(&v4l2->radio_dev));
-		video_unregister_device(&v4l2->radio_dev);
+		vb2_video_unregister_device(&v4l2->radio_dev);
 	}
 	if (video_is_registered(&v4l2->vbi_dev)) {
 		dev_info(&dev->intf->dev,
 			 "V4L2 device %s deregistered\n",
 			 video_device_node_name(&v4l2->vbi_dev));
-		video_unregister_device(&v4l2->vbi_dev);
+		vb2_video_unregister_device(&v4l2->vbi_dev);
 	}
 	if (video_is_registered(&v4l2->vdev)) {
 		dev_info(&dev->intf->dev,
 			 "V4L2 device %s deregistered\n",
 			 video_device_node_name(&v4l2->vdev));
-		video_unregister_device(&v4l2->vdev);
+		vb2_video_unregister_device(&v4l2->vdev);
 	}
 
 	v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: em28xx: requeue buffers if start_streaming fails
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: use vb2_video_unregister_device Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: cec: tegra_cec: don't break off msg on NACK Sasha Levin
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
  To: patches, stable
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Sasha Levin, mchehab,
	linux-media, linux-kernel

From: Hans Verkuil <hverkuil+cisco@kernel.org>

[ Upstream commit 67f87b104f4ef3108607ac9d8fa2075b13ed314d ]

If start_streaming fails, then all queued buffers must be
returned to vb2 in state QUEUED.

Otherwise it will trigger a WARN_ON.

Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
candidate is a real videobuf2 `start_streaming` error-path bug in
`em28xx`: queued buffers were left driver-owned, which fires `WARN_ON`
and can leave stale entries on `dmaq->active`.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

Step 1.1: PARSE THE SUBJECT LINE
Record: **[media/em28xx] [requeue] [return queued vb2 buffers when
start_streaming fails]**
Subsystem `media: em28xx`. Action is “requeue” (correctness on failure,
not a feature).

Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none
- **Tested-by:** Hans Verkuil \<hverkuil+cisco@kernel.org\> (author
  tested it)
- **Reviewed-by / Acked-by:** none on the commit
- **Link:** none in the commit; lore found via `b4 dig` (Phase 4)
- **Cc: stable:** none (expected)
- **Signed-off-by:** Hans Verkuil (author); Mauro Carvalho Chehab (media
  maintainer). Ignore any Sasha Levin SOB if present — none on this
  commit.

Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** If `start_streaming` fails, buffers already given to the
  driver via `buf_queue` are not returned to vb2 as
  `VB2_BUF_STATE_QUEUED`.
- **Symptom:** vb2 `WARN_ON` in `vb2_start_streaming()` when
  `owned_by_drv_count != 0`.
- **Version info:** none in the message.
- **Root cause (author):** driver violates the documented
  `start_streaming` contract.

Step 1.4: DETECT HIDDEN BUG FIXES
Record: **Not hidden.** Explicit contract fix. Cover letter (Phase 4)
also states this patch “correctly gives the vb2 buffers back … if
start_streaming fails.”

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/media/usb/em28xx/em28xx-video.c` — **+16 / −2**
- Function: `em28xx_start_analog_streaming()`
- Scope: **single-file surgical error-path fix**

Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- **Before:** `res_get()` failure and `em28xx_init_usb_xfer()` failure
  both `return rc` immediately. Buffers already on `vidq`/`vbiq`
  `active` stay driver-owned.
- **After:** those paths `goto exit`, which under `dev->slock` walks
  `dmaq->active`, `list_del`s each buffer, and calls
  `vb2_buffer_done(..., VB2_BUF_STATE_QUEUED)`. Success still increments
  `streaming_users` and returns 0.
- **Path affected:** STREAMON / qbuf-triggered `start_streaming`
  **error** path only.

Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **[Logic / vb2 contract] + memory-safety follow-on**
- vb2 calls `__enqueue_in_driver()` → `buf_queue` **before**
  `start_streaming` (`videobuf2-core.c`).
- `buffer_queue` / `vbi_buffer_queue` put buffers on `dev->vidq.active`
  / `dev->vbiq.active`.
- On failure the driver must `vb2_buffer_done(..., QUEUED)` (documented
  in `videobuf2-core.h` `@start_streaming`).
- Without that, `vb2_start_streaming()` does
  `WARN_ON(owned_by_drv_count)` and force-reclaims in vb2 **without**
  unlinking the driver’s list, so `dmaq->active` can keep dangling
  `em28xx_buffer` pointers. `get_next_buf()` later takes
  `dma_q->active.next` — **UAF** on a later successful stream.

Step 2.4: ASSESS THE FIX QUALITY
Record:
- **Quality:** Matches `em28xx_stop_streaming()` and the standard V4L2
  pattern. Author is V4L2 maintainer; self-tested.
- **Minimal:** only the failure cleanup.
- **Regression risk:** low (error path, same lock as stop). Minor
  incompleteness: `stop_streaming` also completes `usb_ctl.vid_buf`;
  this path does not. `em28xx_alloc_urbs()` already NULLs those pointers
  before submit, and failed `init_usb_xfer` calls
  `em28xx_uninit_usb_xfer()`. Common failures (`res_get` -EBUSY,
  alloc/submit fail with empty in-flight slot) are covered. Incomplete
  vs. a rare in-flight URB does not make the patch wrong.
- **No API/feature changes.**

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

Step 3.1: BLAME THE CHANGED LINES
Record:
- `em28xx_start_analog_streaming` comes from **d3829fadc461**
  (“\[media\] em28xx: convert to videobuf2”, 2013-01-05), contained in
  **v3.9-rc1**.
- Failure just `return rc` is that old. Bug is long-standing, not
  new-7.3 code.

Step 3.2: FOLLOW THE FIXES: TAG
Record: **No Fixes: tag.** Closest related error-path change:
**cc20e81da6d99** (“fix missing res_free() on init_usb_xfer failure”,
2026-05) added `res_free()` before `return rc`. This commit turns that
`return` into `goto exit`. Complementary, not a substitute.

Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Same series (lifecycle): `288254383674b`, `de626073dfcbb`,
  `7c8bf63b79371`, `c132b07f7e585` — device lifetime/UAF, **not
  required** for this hunk.
- This is **standalone**: only the start_streaming returns change. Cover
  letter lists it as 6/6, but the diff does not use symbols those
  patches add.

Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Hans Verkuil is a V4L2 maintainer (not the em28xx MAINTAINERS
entry; that is Mauro Chehab, who signed this off). Same class of fix
historically: e.g. **80b0963e1698e** “\[media\] pwc: fix WARN_ON”
(QUEUED vs ERROR on start_streaming failure).

Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: **No hard functional dependency.** Applies against the pre-fix
function in this tree’s parent. Older stables without `cc20e81` only
need a trivial context adjust (`return rc` vs `res_free`+`return rc`).
**Standalone.**

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 67f87b104f4ef`: **[PATCHv2 6/6]** https://patch.msgid.link/
  141d43a4860c6007269e9725cc717a556d22d2a4.1781615432.git.hverkuil+cisco
  @kernel.org
- `b4 dig -a`: v1 was a 3-patch lifecycle series (2026-05-19); v2 is
  **[PATCHv2 0/6] media: em28xx: fix lifecycle issues** (2026-06-16).
  Applied version is v2 patch 6.
- Cover letter: last patch returns buffers if start_streaming fails;
  **tested on author’s em28xx device**.
- **No NAK** on patch 6. Sakari Ailus only discussed patch 1
  (`v4l2-async`).
- **No reviewer Cc: stable.** WebFetch to lore returned **403**; thread
  recovered via `b4 dig -m`.

Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc **linux-media**, Hans Verkuil, Mauricio
Faria de Oliveira, Sakari Ailus. Merged by Mauro Chehab. No separate
Reviewed-by on 6/6.

Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Author found it while testing the lifecycle
series. Mechanism is specified in vb2 (WARN_ON comment names this exact
driver bug class).

Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Series 1–5 are separate lifecycle/UAF work. **6/6 is self-
contained** and does not need 1–5 in this tree.

Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No “stable” in the matched mbox. WebSearch did not find a
stable-list thread for this subject (lore HTML 403). **No evidence it
was rejected for stable.**

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: **`em28xx_start_analog_streaming`**. Helpers used: `res_get`,
`res_free`, `em28xx_init_usb_xfer`, `vb2_buffer_done`.

Step 5.2: TRACE CALLERS
Record: Wired as `.start_streaming` in:
- `em28xx_video_qops` (`em28xx-video.c`)
- `em28xx_vbi_qops` (`em28xx-vbi.c`)
Callers are vb2 (`vb2_start_streaming` ← `vb2_core_streamon` /
`vb2_core_qbuf`). **Userspace V4L2 STREAMON/QBUF.**

Step 5.3: TRACE CALLEES
Record: `res_get` can return **-EBUSY**. `em28xx_init_usb_xfer` can fail
on URB alloc, `usb_clear_halt`, or `usb_submit_urb` (and then
`em28xx_uninit_usb_xfer`). Those are realistic (disconnect, ENOMEM, USB
error).

Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace ioctl → vb2 enqueues via `buf_queue` →
`start_streaming` → on failure, buffers must be returned. **Reachable
from userspace** with `CONFIG_VIDEO_EM28XX` / `CONFIG_VIDEO_EM28XX_V4L2`
and a device node.

Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Many drivers return `VB2_BUF_STATE_QUEUED` on start_streaming
failure (uvc, pwc, gspca, hackrf, platform capture drivers). em28xx was
missing that. Historical media commits: pwc, coda, cal, am437x-vpfe.

semcode MCP: **not available** in this session (only `cursor` dynamic
tools). Used grep/read instead.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes.** This checkout is **7.3.0-rc4**. Commit
**67f87b104f4ef** **is an ancestor of HEAD** (in since v7.3-rc1). Parent
of the commit still has the bare `return rc` paths. Driver and
`em28xx_start_analog_streaming` have been here since the vb2 conversion
(**v3.9**). The bug is not “new after this branch.”

Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: For **this** tree the patch is already applied and matches
current `em28xx-video.c`. Against the pre-fix function it is a clean,
18-line change. No conflicting refactor in the start_streaming body
itself.

Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: `cc20e81da6d99` (res_free on USB-init failure) is in this tree.
It does **not** requeue buffers. No other equivalent fix for this
WARN_ON.

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **drivers/media/usb/em28xx** — USB analog/VBI capture (Empia,
Hauppauge, etc.). **IMPORTANT** for users of that hardware,
**PERIPHERAL** vs core mm/net. Not staging.

Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Actively maintained (lifecycle series, device IDs, UAFs in
2026). Mature driver, old bug. MAINTAINERS: Mauro Chehab; linux-media.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific** (`CONFIG_VIDEO_EM28XX` / V4L2). Empia USB
capture sticks and several Hauppauge devices. Not universal, but real
hardware.

Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Trigger: `VIDIOC_STREAMON` (or qbuf that starts streaming) when
  `res_get` fails or USB xfer init fails.
- Commonness: error path, not every boot. USB submit/alloc failure and
  unplug-during-start are realistic.
- Unprivileged: yes if the user can open `/dev/video*` (typical `video`
  group).

Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- Immediate: **WARN_ON** in vb2 (`videobuf2-core.c` around the “driver
  isn’t cleaning up properly after a failed start_streaming()” comment).
  `panic_on_warn` → panic.
- Follow-on: leftover `dmaq->active` entries after vb2 force-reclaim →
  **UAF** in `get_next_buf()` on retry.
- **Severity: HIGH** (WARN_ON + UAF on retry). Not a silent style issue.

Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** high for em28xx users (stops WARN_ON and dangling DMA
  list).
- **Risk:** very low (~16 lines, error path, same locking as stop).
- **Ratio:** favorable.

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

Step 9.1: COMPILE THE EVIDENCE

**FOR:**
- Real vb2 contract violation; documented WARN_ON.
- Dangling `active` list can UAF on the next STREAMON.
- Small, obviously correct, matches driver stop path and many other V4L2
  drivers.
- V4L2 maintainer authored and tested on real em28xx hardware; media
  maintainer merged it.
- Bug in code since ~v3.9; present in this tree’s pre-fix function.
- Standalone; no new API.

**AGAINST:**
- USB capture driver, not core; only hits failed STREAMON.
- No syzbot / external Reported-by.
- Patch 6/6 of a larger series (but this hunk does not depend on 1–5).
- Does not also complete `usb_ctl.vid_buf` (stop_streaming does); common
  fail paths still fixed.

**UNRESOLVED:**
- lore.kernel.org HTTP 403 for WebFetch; thread read via `b4` mbox
  instead.
- No stable@ discussion found.

Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — contract match + Tested-by
   author on hardware.
2. Fixes a real bug that affects users? **PASS** — STREAMON failure on a
   used USB capture driver.
3. Important issue? **PASS** — WARN_ON; UAF on retry. HIGH, not
   cosmetic.
4. Small and contained? **PASS** — 16 insertions / 2 deletions, one
   function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — code is this driver; patch
   already applies here (it is in 7.3-rc1+). No missing prerequisites
   for *this* hunk.

Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **None** (not an ID/quirk/DT/build/docs exception). It is a
normal small bugfix.

Step 9.4: MAKE YOUR DECISION
This tree has the em28xx analog/VBI vb2 path. The fix is a classic,
surgical start_streaming cleanup that prevents WARN_ON and leftover
driver-owned buffers. It meets stable rules for this checkout.

What it solves for users of this tree: failed `VIDIOC_STREAMON` no
longer trips vb2’s `WARN_ON` and no longer leaves capture buffers on
`dmaq->active` for a later UAF.

Risk vs benefit: error-path only, low regression risk, meaningful
correctness fix.

Concerns: none that block a backport here; series membership is
packaging, not a code dependency.

Verification:
- \[Phase 1\] Parsed tags: Tested-by Hans Verkuil; SOB Hans + Mauro; no
  Fixes/Reported-by/Cc stable
- \[Phase 2\] Diff: +16/-2 in `em28xx_start_analog_streaming`; `return
  rc` → `goto exit` + `vb2_buffer_done(QUEUED)`
- \[Phase 2\] Confirmed vb2 contract and WARN_ON in
  `vb2_start_streaming()` (`videobuf2-core.c` ~1769–1815)
- \[Phase 2\] Confirmed `buf_queue` adds to `vidq`/`vbiq` active before
  start_streaming
- \[Phase 2\] Confirmed `get_next_buf()` uses `dma_q->active.next` (UAF
  if list not cleared)
- \[Phase 3\] `git blame`: function from d3829fadc461 (v3.9-rc1)
- \[Phase 3\] `git merge-base --is-ancestor 67f87b104f4ef HEAD` → yes
  (exit 0)
- \[Phase 3\] `git describe HEAD` → v7.3-rc4-27-gf0100363d8c37; `make
  kernelversion` → 7.3.0-rc4
- \[Phase 3\] Related: cc20e81da6d99 only adds res_free; does not
  requeue
- \[Phase 4\] `b4 dig -c 67f87b104f4ef`: PATCHv2 6/6; cover letter
  describes this exact fix; tested on em28xx
- \[Phase 4\] `b4 dig -a`: v1 3-patch → v2 6-patch lifecycle series; 6/6
  standalone
- \[Phase 4\] `b4 dig -w`: linux-media, Sakari Ailus, Mauricio Faria de
  Oliveira
- \[Phase 4\] WebFetch lore/msgid.link: 403; used mbox instead
- \[Phase 5\] Callers: `em28xx_video_qops` and `em28xx_vbi_qops`
  `.start_streaming`
- \[Phase 5\] Failures: `res_get` -EBUSY; `em28xx_init_usb_xfer`
  alloc/halt/submit
- \[Phase 6\] Pre-fix parent still has bare `return rc`; this tree
  includes the fix
- \[Phase 7\] MAINTAINERS: EM28XX VIDEO4LINUX DRIVER, Mauro Chehab
- \[Phase 8\] Failure: WARN_ON + dangling list UAF; severity HIGH
- UNVERIFIED: stable@ mailing list (lore HTTP 403; no hit in matched
  mbox)

The patch is small, correct, and fixes a real WARN_ON/UAF class bug in
code this tree carries.

**YES**

 drivers/media/usb/em28xx/em28xx-video.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index c8514682bccda..e0a69309687b0 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1070,6 +1070,9 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct em28xx *dev = vb2_get_drv_priv(vq);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
+	struct em28xx_dmaqueue *dmaq = vq->type == V4L2_BUF_TYPE_VBI_CAPTURE ?
+		&dev->vbiq : &dev->vidq;
+	unsigned long flags = 0;
 	struct v4l2_frequency f;
 	struct v4l2_fh *owner;
 	int rc = 0;
@@ -1084,7 +1087,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
 	 */
 	rc = res_get(dev, vq->type);
 	if (rc)
-		return rc;
+		goto exit;
 
 	if (v4l2->streaming_users == 0) {
 		/* First active streaming user, so allocate all the URBs */
@@ -1107,7 +1110,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
 					  em28xx_urb_data_copy);
 		if (rc < 0) {
 			res_free(dev, vq->type);
-			return rc;
+			goto exit;
 		}
 
 		/*
@@ -1132,7 +1135,18 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
 	}
 
 	v4l2->streaming_users++;
+	return 0;
 
+exit:
+	spin_lock_irqsave(&dev->slock, flags);
+	while (!list_empty(&dmaq->active)) {
+		struct em28xx_buffer *buf;
+
+		buf = list_entry(dmaq->active.next, struct em28xx_buffer, list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
+	}
+	spin_unlock_irqrestore(&dev->slock, flags);
 	return rc;
 }
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: cec: tegra_cec: don't break off msg on NACK
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: use vb2_video_unregister_device Sasha Levin
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: requeue buffers if start_streaming fails Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: dvb-core: fix feed leak on failed DMX_ADD_PID Sasha Levin
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
  To: patches, stable
  Cc: Hans Verkuil, Mikko Perttunen, Mauro Carvalho Chehab, Sasha Levin,
	hverkuil, mchehab, thierry.reding, jonathanh, linux-tegra,
	linux-media, linux-kernel

From: Hans Verkuil <hverkuil+cisco@kernel.org>

[ Upstream commit be627f257ce283c95fd2988080dc0db3a20d0d2a ]

The Tegra CEC hardware has a bug where, if the first attempt
to transmit a message is NACKed so the transmit is aborted,
then the second attempt can contain corrupt data.

Ensure that the full message is always transmitted to avoid hitting
this bug.

I suspect some internal state is not reset in the case of aborting
a message due to a NACK.

Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This is a hardware-quirk workaround in the Tegra HDMI CEC driver: after
a NACK abort, the next transmit can be corrupt. The local tree is
**v7.3-rc4** (`7.3.0-rc4`). The driver and
`TEGRA_CEC_HWCTRL_TX_NAK_MODE` bit have been here since the original
2017 driver, so the fix belongs in this tree.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

Step 1.1: PARSE THE SUBJECT LINE
Record: [media: cec: tegra_cec] [don't break off] [keep transmitting a
CEC message after NACK so Tegra HW does not corrupt the retry]

Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Hans Verkuil \<hverkuil+cisco@kernel.org\> (author; CEC
  and Tegra CEC maintainer)
- Reviewed-by: Mikko Perttunen \<mperttunen@nvidia.com\> (NVIDIA)
- Signed-off-by: Mauro Carvalho Chehab \<mchehab+huawei@kernel.org\>
  (media maintainer)
- No Fixes:, Reported-by:, Tested-by:, Link:, or Cc: stable (absence
  expected)
- Ignored: any Sasha Levin SOB / Upstream-commit markers (none present
  on the real commit)

Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: Tegra CEC silicon bug. If the first transmit is NACKed and
  aborted, the second attempt can contain corrupt data. Author suspects
  internal HW state is not reset on NACK abort.
- Symptom: corrupt HDMI-CEC frames on retry after NACK (wrong bytes on
  the CEC bus).
- Version info: none in the message. Driver dates to v4.15-rc1.
- Root cause (author): abort-on-NACK leaves HW in a bad state;
  workaround is to always send the full message (`TX_NAK_MODE`).

Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not disguised. Cover letter calls it “a fix” / HW-bug
workaround. Not cleanup.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/media/cec/platform/tegra/tegra_cec.c` (+12 / -1)
- Function: `tegra_cec_adap_enable()`
- Scope: single-file surgical change; one functional OR of an existing
  HW bit plus a comment

Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: enable path wrote `TEGRA_CEC_HW_CONTROL =
  TEGRA_CEC_HWCTRL_TX_RX_MODE` only. Hardware aborted TX on NACK.
- After: same write also sets `TEGRA_CEC_HWCTRL_TX_NAK_MODE` so the full
  frame is sent even if bytes are NACKed.
- Path: adapter enable (normal init), not an error path.
- `tegra_cec_adap_log_addr()` and `tegra_cec_adap_monitor_all_enable()`
  RMW `HW_CONTROL`, so they keep the bit. `tegra_cec_error_recovery()`
  saves/restores `hw_ctrl`, so it keeps the bit too.

Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [Hardware workaround] Default abort-on-NACK leaves Tegra CEC TX
state unrestored; retry can emit corrupt data. Setting `TX_NAK_MODE`
avoids the abort path. IRQ still reports NACK via
`TX_FRAME_OR_BLOCK_NAKD` when `TX_FRAME_TRANSMITTED` fires.

Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: one existing register bit, documented in-tree since
  2017, unused until now.
- Minimal: one OR plus comment.
- Regression risk: low. Bus is occupied a bit longer after NACK (author
  notes this). NVIDIA reviewed. Software still reports
  `CEC_TX_STATUS_NACK`. POLL (the usual NACK) is one byte, so extra bus
  time is negligible.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

Step 3.1: BLAME THE CHANGED LINES
Record: Buggy write is from `9d2d60687c9a` (“media: tegra-cec: add Tegra
HDMI CEC driver”, 2017-07-15, contained in v4.15-rc1).
`TEGRA_CEC_HWCTRL_TX_NAK_MODE` was defined in that same commit (`(1 <<
24)`), later rewritten as `BIT(24)` in `cce8ccca80d838` (2019). Bug has
been in this driver for the entire mainline life of the driver.

Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. N/A. Introduced by original driver, not a later
regression.

Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Same-day series 1/2. 2/2 is `bce7236c16c2c` (“keep track of
number of Rx Low Drives”) — debug counter, not a prerequisite. Later
`a45a81a790b96` is an unrelated `dev_err` cleanup. Standalone.

Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Hans Verkuil is listed in MAINTAINERS for both CEC FRAMEWORK and
ARM/TEGRA HDMI CEC. NVIDIA’s Mikko Perttunen reviewed. High confidence.

Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None. Uses `TEGRA_CEC_HWCTRL_TX_NAK_MODE` already in
`tegra_cec.h` in this tree. Applies standalone.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- Lore: https://patch.msgid.link/7e50d6027e1676650d52905cd20eb212c01cd3e
  5.1783677198.git.hverkuil+cisco@kernel.org
- Cover: `[PATCH 0/2] media: tegra_cec: a fix and an enhancement` — “the
  first works around a HW bug where, if a transmit was NACKed, the
  retransmit would contain corrupt data.”
- Only v1; committed as submitted.
- No NAK, no stable nomination, no reviewer risk flags.
- Included in “[GIT PULL FOR v7.3] media: CEC fixes/improvements”.

Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: To linux-media; Cc Thierry Reding and linux-tegra. Reviewed-by
Mikko Perttunen (NVIDIA). Right maintainers.

Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Author-discovered HW bug, confirmed by
NVIDIA review. No user-count in the thread.

Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: 1/2 of 2. 2/2 is an enhancement (Rx low-drive debugfs), not
required. Do not pull 2/2 as a dependency.

Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No stable-list discussion found for this NACK workaround. linux-
media search for “tegra_cec stable” did not hit this patch.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `tegra_cec_adap_enable()`

Step 5.2: TRACE CALLERS
Record: Wired as `cec_adap_ops.adap_enable`. Called from
`cec_adap_enable()` in `drivers/media/cec/core/cec-adap.c`
(open/configure `/dev/cecX`, logical-address setup, enable/disable).
Userspace-reachable on Tegra HDMI.

Step 5.3: TRACE CALLEES
Record: `cec_write()` → `writel()` of `TEGRA_CEC_HW_CONTROL`. No alloc,
no new locks.

Step 5.4: FOLLOW THE CALL CHAIN
Record: userspace CEC ioctl/open → CEC core `cec_adap_enable()` →
`tegra_cec_adap_enable()`. Transmit path `tegra_cec_adap_transmit()`
fills TX FIFO; NACK is handled in `tegra_cec_irq_handler()`.
Unprivileged users with `/dev/cecX` can trigger TX, including
NACK+retry.

Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: `TX_NAK_MODE` is only used in this driver. No sibling-driver
copy of this workaround.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Tree is v7.3-rc4. File
`drivers/media/cec/platform/tegra/tegra_cec.c` and header bit
`TEGRA_CEC_HWCTRL_TX_NAK_MODE` are present. Pre-fix enable path wrote
only `TX_RX_MODE` (blame to 2017). Bug introduced in v4.15-era driver,
long before this branch.

Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. Context in the candidate is the INT_MASK block
without later `RX_BUS_ERROR_DETECTED` (that line is from 2/2). Against
this tree the hunk is already the intended enable write. No data-
structure or API change.

Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No earlier alternate fix for NACK-abort corruption. This is the
first use of `TX_NAK_MODE` in C code.

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [drivers/media/cec/platform/tegra] [PERIPHERAL / platform
driver, but real Tegra HDMI product path]. CONFIG_CEC_TEGRA, depends on
ARCH_TEGRA.

Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature. Driver since 2017; low churn. This is an old HW bug, not
new-code churn.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

Step 8.1: DETERMINE WHO IS AFFECTED
Record: Tegra HDMI-CEC users (Jetson and other Tegra boards with CEC).
Config- and platform-specific, not universal.

Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Transmit a message that is NACKed, then retry. Common for POLL
during logical-address allocation (1 byte; author says that case is
cheap). Multi-byte NACK+retry is less common but real (absent follower,
follower busy). Userspace with CEC device access can trigger it.

Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: [Corrupt CEC frame on retry] [MEDIUM functionally, HIGH for that
hardware’s CEC reliability]. Not a kernel oops. Puts garbage on the CEC
bus, which can break TV/AVR control after a NACK. That is user-visible
protocol corruption.

Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: high for Tegra CEC — stops corrupt retries on a long-standing
  silicon bug.
- Risk: very low — one register bit, NVIDIA Reviewed-by, CEC maintainer
  authored it.
- Ratio: strongly favors applying the workaround.

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

Step 9.1: COMPILE THE EVIDENCE

FOR:
- Real Tegra CEC hardware bug: NACK abort → corrupt retransmit
- Hardware quirk/workaround (stable exception)
- Tiny: +12/-1, one bit OR
- Bit defined since original 2017 driver; no new API
- Authored by CEC/Tegra-CEC maintainer; Reviewed-by NVIDIA
- Standalone; 2/2 of the series is unrelated debug
- Applies to this tree: driver and define exist
- IRQ path still reports NACK correctly

AGAINST:
- Not a kernel crash, UAF, or security bug
- Tegra-only
- Slightly longer bus occupancy after NACK (documented, accepted)
- No Fixes:/Cc: stable (not a negative here)
- No public multi-user bugzilla/syzbot report

UNRESOLVED:
- lore.kernel.org WebFetch returned 403; thread recovered via `b4 dig
  -m` and gnuweeb/ratatoskr mirrors
- No stable@ discussion found
- HW “internal state not reset” is the author’s suspicion; NVIDIA did
  not contradict it

Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — one documented HW bit; NVIDIA
   Reviewed-by
2. Fixes a real bug that affects users? PASS — corrupt CEC retries after
   NACK
3. Important issue? PASS as hardware workaround / protocol corruption on
   HDMI-CEC, not as a kernel panic
4. Small and contained? PASS — 13-line hunk, one function
5. No new features or APIs? PASS — enables an existing unused control
   bit
6. Can apply to the local tree? PASS — file, function, and
   `TEGRA_CEC_HWCTRL_TX_NAK_MODE` are here

Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Hardware quirk/workaround. Qualifies even without a panic.

Step 9.4: MAKE YOUR DECISION
This is a small, reviewed workaround for a real Tegra CEC silicon bug
that corrupts the next transmit after a NACK abort. The driver and
register bit exist in this v7.3-rc4 tree and have since v4.15. Risk is a
single enable-time bit. That meets stable rules via the hardware-quirk
exception.

What it solves for users of this tree: Tegra HDMI-CEC retries after NACK
can put corrupt bytes on the bus; setting `TX_NAK_MODE` avoids the abort
path that triggers that bug.

Risk vs benefit: one-bit enable flag, NVIDIA-reviewed, vs broken CEC
after NACK. Benefit wins.

===============================================================
Verification:
- [Phase 1] Parsed be627f257ce283c95fd2988080dc0db3a20d0d2a: no
  Fixes/Reported-by/Cc:stable; SOB Hans Verkuil + Mauro; Reviewed-by
  Mikko Perttunen
- [Phase 1] Cover letter (mbox): “works around a HW bug” / corrupt
  retransmit after NACK
- [Phase 2] Diff: `tegra_cec_adap_enable()` OR
  `TEGRA_CEC_HWCTRL_TX_NAK_MODE` into HW_CONTROL (+12/-1)
- [Phase 2] Confirmed RMW of HW_CONTROL in `tegra_cec_adap_log_addr`,
  `tegra_cec_adap_monitor_all_enable`, `tegra_cec_error_recovery`
  preserves the bit
- [Phase 2] IRQ still sets `CEC_TX_STATUS_NACK` on
  `TX_FRAME_TRANSMITTED` + `TX_FRAME_OR_BLOCK_NAKD`
- [Phase 3] git blame parent: HW_CONTROL write from 9d2d60687c9a
  (v4.15-rc1); TX_NAK_MODE in original header
- [Phase 3] git merge-base --is-ancestor 9d2d60687c9a HEAD: yes
- [Phase 3] No Fixes: tag; follow-up bce7236c16c2c is debug-only, not a
  prereq
- [Phase 4] b4 dig -c: https://patch.msgid.link/7e50d6027e1676650d52905c
  d20eb212c01cd3e5.1783677198.git.hverkuil+cisco@kernel.org
- [Phase 4] b4 dig -a: v1 only
- [Phase 4] b4 dig -w: linux-media, linux-tegra, Thierry Reding
- [Phase 4] b4 dig -m: NVIDIA Reviewed-by; no NAK; no Cc:stable in
  thread
- [Phase 4] lore.kernel.org WebFetch: 403; used mbox + gnuweeb/ratatoskr
  instead
- [Phase 5] Callers: cec-adap.c `cec_adap_enable()` → ops->adap_enable;
  userspace `/dev/cecX`
- [Phase 5] grep TX_NAK_MODE: only tegra_cec.c/.h
- [Phase 6] git describe HEAD: v7.3-rc4-27-gf0100363d8c37; make
  kernelversion 7.3.0-rc4
- [Phase 6] Header bit present; enable function present; clean single-
  hunk change
- [Phase 7] MAINTAINERS: Hans Verkuil maintains ARM/TEGRA HDMI CEC and
  CEC FRAMEWORK
- [Phase 8] Failure mode: corrupt CEC retry after NACK, not oops;
  severity MEDIUM/HIGH for that hardware
- UNVERIFIED: no TRM quote confirming “internal state not reset”; author
  suspicion only, not used as the sole reason

**YES**

 drivers/media/cec/platform/tegra/tegra_cec.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/media/cec/platform/tegra/tegra_cec.c b/drivers/media/cec/platform/tegra/tegra_cec.c
index fe66336e734f8..f8ffaeb78118d 100644
--- a/drivers/media/cec/platform/tegra/tegra_cec.c
+++ b/drivers/media/cec/platform/tegra/tegra_cec.c
@@ -243,7 +243,18 @@ static int tegra_cec_adap_enable(struct cec_adapter *adap, bool enable)
 		  TEGRA_CEC_INT_MASK_RX_REGISTER_FULL |
 		  TEGRA_CEC_INT_MASK_RX_START_BIT_DETECTED);
 
-	cec_write(cec, TEGRA_CEC_HW_CONTROL, TEGRA_CEC_HWCTRL_TX_RX_MODE);
+	/*
+	 * TX_NAK_MODE ensures that the whole message is transmitted even
+	 * if each byte is NACKed. Without this flag the retransmit of the
+	 * messages after a NACK can be corrupt. This is a bug in the hardware.
+	 *
+	 * While less efficient, in practice you rarely transmit messages
+	 * that can be NACKed, with the exception of POLL messages which
+	 * are just one byte anyway.
+	 */
+	cec_write(cec, TEGRA_CEC_HW_CONTROL,
+		  TEGRA_CEC_HWCTRL_TX_RX_MODE |
+		  TEGRA_CEC_HWCTRL_TX_NAK_MODE);
 	return 0;
 }
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: dvb-core: fix feed leak on failed DMX_ADD_PID
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (2 preceding siblings ...)
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: cec: tegra_cec: don't break off msg on NACK Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: go7007: s2250: propagate control I/O failures Sasha Levin
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
  To: patches, stable
  Cc: Rituparna Warwatkar, syzbot+e9a1f5e196de6663631b,
	Mauro Carvalho Chehab, Sasha Levin, mchehab, linux-media,
	linux-kernel

From: Rituparna Warwatkar <rwarwatkar@gmail.com>

[ Upstream commit 9fa26c971ca310dd10a3bc0014f2fc7ea7167bba ]

dvb_dmxdev_add_pid() allocates a new dmxdev_feed, links it into
filter->feed.ts and, when the filter is already running, immediately
starts the feed.

If starting the feed fails, the newly allocated feed remains on the
list. Subsequent restart and rollback paths may then operate on this
stale entry, leaving feed resources allocated and causing leaks in
drivers that allocate resources from ->start_feed() and release them
from ->stop_feed().

Remove the feed from the list and free it when
dvb_dmxdev_start_feed() fails.

Reported-by: syzbot+e9a1f5e196de6663631b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e9a1f5e196de6663631b
Signed-off-by: Rituparna Warwatkar <rwarwatkar@gmail.com>
Link: https://patch.msgid.link/20260714141059.63582-1-rwarwatkar@gmail.com
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Message-ID: <20260714141059.63582-1-rwarwatkar@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local checkout is mainline **7.3.0-rc4**. The change is a small,
syzbot-confirmed feed leak in `dvb_dmxdev_add_pid()`, present since
2009, and it belongs in this tree.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

**Step 1.1: PARSE THE SUBJECT LINE**

Record: **[media/dvb-core] [fix] feed leak on failed DMX_ADD_PID**

- Subsystem: `media: dvb-core:`
- Action verb: **fix** (explicit bug fix)
- Claimed intent: stop leaking a `dmxdev_feed` when `DMX_ADD_PID` fails
  to start a already-running filter

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**

Record:
- **Reported-by:** syzbot+e9a1f5e196de6663631b@syzkaller.appspotmail.com
  (fuzzer-found, reproducible)
- **Closes:**
  https://syzkaller.appspot.com/bug?extid=e9a1f5e196de6663631b
- **Signed-off-by:** Rituparna Warwatkar (author)
- **Link:**
  https://patch.msgid.link/20260714141059.63582-1-rwarwatkar@gmail.com
- **Signed-off-by:** Mauro Carvalho Chehab (media maintainer, committer)
- **Message-ID:** `<20260714141059.63582-1-rwarwatkar@gmail.com>`
- **No Fixes:** tag (expected for this review pipeline)
- **No Cc: stable** (expected)
- **No Reviewed-by / Tested-by / Acked-by**
- Sasha Levin SOB: not present on this commit (ignored per instructions
  anyway)

Notable pattern: syzbot report + media maintainer SOB.

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**

Record:
- **Bug:** `dvb_dmxdev_add_pid()` allocates a `dmxdev_feed`, links it
  onto `filter->feed.ts`, then (if the filter is already
  `DMXDEV_STATE_GO`) calls `dvb_dmxdev_start_feed()`. On start failure
  the object stays on the list.
- **Symptom:** leaked feed objects and leaked driver resources allocated
  in `->start_feed()` and meant to be released in `->stop_feed()`.
- **Failure mode:** resource leak; subsequent restart/rollback walks the
  stale list entry.
- **Version info:** none in the message. History shows the pattern dates
  to 2009.
- **Root cause (author):** missing `list_del` + `kfree` on the
  `dvb_dmxdev_start_feed()` error path.

**Step 1.4: DETECT HIDDEN BUG FIXES**

Record: **Not disguised.** This is an explicit error-path leak fix
(syzbot memory leak). Not a cleanup/refactor.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

**Step 2.1: INVENTORY THE CHANGES**

Record:
- **File:** `drivers/media/dvb-core/dmxdev.c` (+9 / −2; net +7)
- **Function:** `dvb_dmxdev_add_pid()` only
- **Scope:** single-file surgical error-path fix

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**

Record:
- **Before:** if `filter->state >= DMXDEV_STATE_GO`, return
  `dvb_dmxdev_start_feed(...)` directly. On failure the feed is already
  on `filter->feed.ts` and is never unlinked or freed.
- **After:** capture the return value; on `ret < 0`,
  `list_del(&feed->next)`, `kfree(feed)`, then return the error. Success
  path still returns 0.
- **Path affected:** error path of `DMX_ADD_PID` while a PES filter is
  already running. Normal success path unchanged.

**Step 2.3: IDENTIFY THE BUG MECHANISM**

Record:
- **Category:** error-path resource leak, with a follow-on NULL deref /
  UAF on close/stop
- **Mechanism:** `list_add()` happens before start. `list_add()` inserts
  at the **head**. `dvb_dmxdev_start_feed()` sets `feed->ts = NULL` then
  may fail in `allocate_ts_feed()` (ts stays NULL) or fail after
  `release_ts_feed()` (ts dangling). `dvb_dmxdev_feed_stop()` /
  `dvb_dmxdev_filter_stop()` then walk the list and call
  `feed->ts->stop_filtering(feed->ts)` without a NULL check. Close
  (`dvb_dmxdev_filter_free`) always calls those stop/reset paths.
  Because the stale feed is at the head, stop hits it first and never
  stops the original live feed — matching the syzbot vidtv `start_feed`
  leak (mux/PSI objects never destroyed). `dvb_dmxdev_remove_pid()` also
  skips entries with `feed->ts == NULL`, so userspace cannot recover via
  `DMX_REMOVE_PID`.
- **Fix:** unlink and free the new feed if start fails, restoring the
  list to the pre-ioctl state.

**Step 2.4: ASSESS THE FIX QUALITY**

Record:
- **Quality:** obviously correct. Mirrors the existing success-cleanup
  in `dvb_dmxdev_remove_pid()` (`list_del` + `kfree`).
  `dvb_dmxdev_start_feed()` already releases a partially allocated TS
  feed on its own error paths, so this does not double-free driver TS
  feeds.
- **Minimal:** only the failure branch.
- **Regression risk:** very low. Does not change locking, APIs, or
  success behavior. A remaining unrelated weakness is that
  `dvb_dmxdev_start_feed()` does not NULL `feed->ts` after
  `release_ts_feed()` on set/start_filtering failure; this patch kfree’s
  the wrapper so that dangling pointer is discarded.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

**Step 3.1: BLAME THE CHANGED LINES**

Record:
- Buggy allocate/list_add/start pattern introduced in
  **`1cb662a3144992`** (“V4L/DVB (12275): Add two new ioctls:
  DMX_ADD_PID and DMX_REMOVE_PID”), Andreas Oberritter, 2009-07-14.
- Contained in **v2.6.32-rc1**. Present in this tree and in every
  current LTS.
- Allocation line later became `kzalloc_obj` (`bf4afc53b77ae`, 2026);
  this patch does not depend on that.

**Step 3.2: FOLLOW THE FIXES: TAG**

Record: **No Fixes: tag.** Not applicable. The introducing commit is
identified via blame as `1cb662a3144992`, and `git merge-base --is-
ancestor` is not needed for that SHA as a Fixes target; the buggy
function is in this checkout.

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**

Record:
- Recent `dmxdev.c` commits are unrelated (ringbuffer reopen,
  kzalloc_obj conversion, vb2, mmap, UAF-on-release, etc.).
- No later follow-up on this function: `git log 9fa26c971ca31..HEAD --
  drivers/media/dvb-core/dmxdev.c` is empty.
- **Standalone**, not patch X/Y.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**

Record: Rituparna Warwatkar has this single commit under
`drivers/media/` in this tree. Not a subsystem maintainer. **Mauro
Carvalho Chehab** (media maintainer) committed it, which is the relevant
trust signal.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**

Record: **None.** Uses existing `list_del` / `kfree` /
`dvb_dmxdev_start_feed()`. Applies on top of the 2009 function. The
current `kzalloc_obj` line is **not** part of the hunk.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**

Record:
- `b4 dig -c 9fa26c971ca31` →
  https://patch.msgid.link/20260714141059.63582-1-rwarwatkar@gmail.com
- `b4 dig -a`: **v1 only**, single patch, not a series
- `b4 dig -m`: thread is **only the original submission**; no public
  replies, NAKs, or reviewer-added `Cc: stable`
- lore.kernel.org WebFetch returned **403**; discussion recovered from
  the mbox instead
- Applied as submitted by Mauro on 2026-07-27

**Step 4.2: CHECK WHO REVIEWED THE PATCH**

Record (`b4 dig -w`): To Mauro Carvalho Chehab; Cc linux-media, linux-
kernel, syzbot. No extra reviewers. Maintainer applied it (SOB as
committer).

**Step 4.3: SEARCH FOR THE BUG REPORT**

Record (syzkaller, fetched successfully):
- Title: **memory leak in vidtv_psi_registration_desc_init**
- Status: upstream reported, **C repro**
- Labels: **prio:high**
- Fix commit listed: `9fa26c971ca3`
- Syzbot AI: DenialOfService exploitable, **Unprivileged: yes**
- Duplicate: “memory leak in vidtv_psi_sdt_service_init”
- Two crashes (2026-07-10, 2026-07-21) with C/syz reproducers
- Stack: `vidtv_start_feed` → `dmx_ts_feed_start_filtering` →
  `dvb_dmxdev_start_feed` → `dvb_dmxdev_filter_start` →
  `dvb_demux_do_ioctl` (ioctl path)
- Patch testing on upstream: **OK** (author + another tester)

The leak objects are vidtv PSI/mux allocations from `->start_feed()`.
That matches “drivers that allocate from start_feed and release from
stop_feed” once stop never runs because the stale list head is hit
first.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**

Record: standalone v1. Duplicate syzbot bug closed as dup. No sibling
patches required.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**

Record: lore.kernel.org/stable WebFetch returned **403**. **UNVERIFIED**
whether stable@ discussed this. Absence of Cc: stable on the commit is
expected and not used against the patch.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**

Record: `dvb_dmxdev_add_pid()` modified. Closely involved (not changed):
`dvb_dmxdev_start_feed()`, `dvb_dmxdev_feed_stop()`,
`dvb_dmxdev_filter_stop()`, `dvb_dmxdev_filter_start()`,
`dvb_dmxdev_filter_free()`, `dvb_dmxdev_remove_pid()`.

**Step 5.2: TRACE CALLERS**

Record:
- `dvb_dmxdev_pes_filter_set()` → `dvb_dmxdev_add_pid()` for the initial
  PID. At that point state is `SET` not `GO`, so the start-on-GO branch
  (the bug) is **not** taken there.
- `dvb_demux_do_ioctl()` `DMX_ADD_PID` → `dvb_dmxdev_add_pid()`. This
  **is** the GO-state path after `DMX_START` / immediate start.
- Context: userspace ioctl on `/dev/dvb/adapterX/demuxY`, under
  `dmxdevfilter->mutex`.

**Step 5.3: TRACE CALLEES**

Record: `kzalloc_obj` / historically `kzalloc`, `list_add`,
`dvb_dmxdev_start_feed()` → `allocate_ts_feed` / `tsfeed->set` /
`tsfeed->start_filtering` → driver `start_feed` (e.g. `vidtv_start_feed`
increments `nfeeds` and may call `vidtv_start_streaming`).

**Step 5.4: FOLLOW THE CALL CHAIN**

Record:
`ioctl(DMX_SET_PES_FILTER)` → start filter (`DMXDEV_STATE_GO`, driver
`start_feed`) → `ioctl(DMX_ADD_PID)` → fail `dvb_dmxdev_start_feed` →
stale list entry → `close` / `filter_stop` walks list.

**Userspace reachable: yes.** Syzbot C repro confirms it.

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**

Record: `dvb_dmxdev_filter_start()` already rolls back with
`dvb_dmxdev_filter_stop()` if a later PID’s `start_feed` fails.
`add_pid` was the missing counterpart. `remove_pid` already does
`list_del`+`kfree`. No other copy of this exact bug in dvb-core.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**

Record:
- `git describe HEAD` → **v7.3-rc4-27-gf0100363d8c37**
- `make kernelversion` → **7.3.0-rc4** (mainline, not an LTS branch
  name)
- File and function exist at `drivers/media/dvb-core/dmxdev.c`
- Pre-fix body confirmed via `git show 9fa26c971ca31^:...`
- Bug introduced **v2.6.32-rc1** (`1cb662a3144992`); not a post-branch
  issue for this tree
- `git merge-base --is-ancestor 9fa26c971ca31 HEAD` → yes (the fix is
  already on this mainline checkout). That is **not** used as circular
  “already selected for stable” reasoning; it only confirms the code
  belongs here.

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**

Record: **Clean apply.** Surrounding function has been stable since 2009
aside from the allocator rename, which this hunk does not touch. No
conflicting later edits to this function.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**

Record: this *is* the fix. No alternate older fix for the same error
path.

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**

Record: **media / DVB core demux (`drivers/media/dvb-core/`)**.
Criticality: **IMPORTANT** (shared by all DVB adapters; not mm/net core,
not staging). UAPI ioctl `DMX_ADD_PID` in
`include/uapi/linux/dvb/dmx.h`.

**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**

Record: dvb-core is mature; this function is ~17 years old. Occasional
security/leak/UAF fixes. Not a newly added subsystem.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

**Step 8.1: DETERMINE WHO IS AFFECTED**

Record: **driver/config-specific** — users of DVB demux (`CONFIG` via
media/DVB stack), including the in-tree vidtv test adapter used by
syzbot. Any hardware driver that allocates in `start_feed` and frees in
`stop_feed` can leak the same way.

**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**

Record:
- Trigger: `DMX_ADD_PID` while a PES TSDEMUX_TAP filter is running, and
  `dvb_dmxdev_start_feed()` fails (allocation busy, invalid frontend,
  driver `-ENOMEM`, etc.).
- How common: error path, but syzbot produced a **C repro**.
- Unprivileged: syzbot assessment says yes (device node permissions
  permitting).

**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**

Record:
- Primary report: **memory leak** of driver streaming/PSI objects (and
  the `dmxdev_feed` itself)
- On close/stop: **NULL deref or UAF** walking `feed->ts` on the stale
  head entry; live feed never stopped
- Repeatable from ioctl → DoS via leak or oops
- Severity: **HIGH** (syzbot prio:high; leak + crash on teardown)

**Step 8.4: CALCULATE RISK-BENEFIT RATIO**

Record:
- **Benefit: high** — stops a userspace-triggerable leak/crash in DVB
  core, syzbot-confirmed, long-present bug
- **Risk: very low** — ~7 lines, error path only, maintainer-applied,
  syzbot patch test OK
- **Ratio: strongly favorable**

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

**Step 9.1: COMPILE THE EVIDENCE**

**FOR backporting:**
- Real, reproducible leak (syzbot C repro, prio:high)
- Userspace ioctl trigger; unprivileged DoS per syzbot
- Also creates a stale list head that `feed_stop`/`filter_stop`
  dereference (NULL/UAF) so the original feed is never stopped
- Bug in code from **2009** (v2.6.32); present in this tree
- 7-line, obviously correct error-path cleanup
- No new APIs/features; standalone; no prerequisites
- Media maintainer committed it; syzbot patch tests passed

**AGAINST:**
- No public review comments (v1 applied as-is)
- No Fixes/Cc: stable tags (expected here, not a negative)
- DVB is not a universal core path (still a shared subsystem, not
  staging)

**UNRESOLVED:**
- lore.kernel.org and stable@ WebFetch 403; thread recovered via `b4 dig
  -m` (no replies)
- Whether stable@ already discussed it: unverified, not used in the
  decision

**Step 9.2: APPLY THE STABLE RULES CHECKLIST**

1. Obviously correct and tested? **PASS** — local code matches the
   described leak; syzbot C repro + patch test OK; maintainer SOB
2. Fixes a real bug that affects users? **PASS** — kmemleak + ioctl
   repro
3. Important issue? **PASS** — HIGH: resource leak and teardown NULL
   deref/UAF, not a style cleanup
4. Small and contained? **PASS** — one function, +9/−2
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — same function, no missing
   helpers

**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**

Record: not a device-ID/quirk/DT/build/docs exception. It is a normal
important bugfix.

**Step 9.4: MAKE YOUR DECISION**

This is a small, correct error-path leak fix in DVB core, reachable from
`DMX_ADD_PID`, present in this tree since the ioctl was added, and
confirmed by syzbot. It meets stable rules for this checkout.

**What the commit solves for users of this tree:** a failed
`DMX_ADD_PID` on a running filter left a `dmxdev_feed` on
`filter->feed.ts`. Later stop/close walked that stale head entry,
skipped `->stop_feed()` for the live feed, and leaked driver allocations
(vidtv PSI/mux in the repro) and could NULL-deref `feed->ts`.

**Risk vs benefit:** benefit is a real leak/crash fix; risk is a few
lines on an ioctl error path.

**Concerns:** none for apply/prereqs on this tree. lore HTTP 403 did not
block verification because `b4 dig` saved the thread.

Verification:
- [Phase 1] Parsed tags: Reported-by syzbot, Closes syzkaller URL, Link
  msgid, SOB author + Mauro Chehab; no Fixes/Cc:stable
- [Phase 2] Diff: `dvb_dmxdev_add_pid()` only; on
  `dvb_dmxdev_start_feed()` failure, `list_del` + `kfree`
- [Phase 2] Confirmed `list_add` inserts at head;
  `dvb_dmxdev_feed_stop()` does `feed->ts->stop_filtering` without NULL
  check; `remove_pid` skips `ts == NULL`
- [Phase 3] git blame: buggy pattern from `1cb662a3144992` (2009-07-14),
  contained in v2.6.32-rc1
- [Phase 3] No Fixes tag; no follow-ups on `dmxdev.c` after this commit;
  standalone
- [Phase 3] Author has one media commit; maintainer Mauro committed it
- [Phase 4] `b4 dig -c 9fa26c971ca31`:
  https://patch.msgid.link/20260714141059.63582-1-rwarwatkar@gmail.com
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: To Mauro, Cc linux-media/lkml/syzbot
- [Phase 4] `b4 dig -m`: submission only, no replies/NAKs
- [Phase 4] WebFetch syzbot: prio:high, C repro, DoS unprivileged, fix
  SHA 9fa26c971ca3, patch test OK
- [Phase 4] lore.kernel.org and lore.kernel.org/stable WebFetch: 403 —
  UNVERIFIED via HTTP; mbox used instead
- [Phase 5] Callers: `DMX_ADD_PID` ioctl and `pes_filter_set` (GO-state
  path is the ioctl)
- [Phase 5] vidtv `start_feed`/`stop_feed` nfeeds + mux alloc/free
  confirms leak if stop skipped
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37;
  kernelversion 7.3.0-rc4
- [Phase 6] Pre-fix function verified with `git show
  9fa26c971ca31^:drivers/media/dvb-core/dmxdev.c`
- [Phase 6] `git merge-base --is-ancestor 9fa26c971ca31 HEAD`: yes
- [Phase 8] Failure mode: leak + teardown NULL deref/UAF, severity HIGH
- UNVERIFIED: stable@ mailing-list discussion (HTTP 403); not used for
  the verdict

**YES**

 drivers/media/dvb-core/dmxdev.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index ab34be22cd1aa..f6fb54ad05e7a 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -871,6 +871,7 @@ static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev,
 			      struct dmxdev_filter *filter, u16 pid)
 {
 	struct dmxdev_feed *feed;
+	int ret;
 
 	if ((filter->type != DMXDEV_TYPE_PES) ||
 	    (filter->state < DMXDEV_STATE_SET))
@@ -888,8 +889,14 @@ static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev,
 	feed->pid = pid;
 	list_add(&feed->next, &filter->feed.ts);
 
-	if (filter->state >= DMXDEV_STATE_GO)
-		return dvb_dmxdev_start_feed(dmxdev, filter, feed);
+	if (filter->state >= DMXDEV_STATE_GO) {
+		ret = dvb_dmxdev_start_feed(dmxdev, filter, feed);
+		if (ret < 0) {
+			list_del(&feed->next);
+			kfree(feed);
+			return ret;
+		}
+	}
 
 	return 0;
 }
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: go7007: s2250: propagate control I/O failures
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (3 preceding siblings ...)
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: dvb-core: fix feed leak on failed DMX_ADD_PID Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: ivtv: stop VBI start-code scan before short tail Sasha Levin
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
  To: patches, stable
  Cc: Yousef Alhouseen, Hans Verkuil, Sasha Levin, hverkuil, mchehab,
	linux-media, linux-kernel

From: Yousef Alhouseen <alhouseenyousef@gmail.com>

[ Upstream commit 59dc14a6cb5ff1ae5ce2f6ebf51fe0139e1c0623 ]

The brightness and contrast paths use oldvalue after read_reg_fp()
without checking whether the read succeeded.  A failed read leaves
oldvalue uninitialized and can write arbitrary reserved register bits.

Return read and write errors from every control path so failed hardware
access cannot be reported as a successful control update.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is mainline **7.3.0-rc4**. The Sensoray 2250 control path
is present here, and the change is a small, real error-path fix: a
failed `read_reg_fp()` left `oldvalue` uninitialized and could program
reserved VPX322 bits while still reporting success to V4L2.

## Phase 1: Commit message forensics

**Step 1.1: Subject line**
Record: **[media/go7007/s2250] [propagate] Return control I/O errors so
brightness/contrast do not use an uninitialized register image**

**Step 1.2: Tags**
Record:
- **Signed-off-by:** Yousef Alhouseen (author)
- **Signed-off-by:** Hans Verkuil (media/GO7007 maintainer; applied the
  patch)
- **No** Fixes, Reported-by, Tested-by, Reviewed-by, Acked-by, Link, or
  Cc: stable (absence of Fixes/Cc stable is expected for this review)
- Not a syzbot report; not a kernel test robot report

**Step 1.3: Body**
Record:
- **Bug:** brightness/contrast call `read_reg_fp()` then use `oldvalue`
  without checking the read.
- **Symptom:** a failed read leaves `oldvalue` uninitialized; the
  following write can poke **arbitrary reserved register bits**. Failed
  I/O is still reported as a successful control update.
- **Version info:** none in the message. Commit `59dc14a6cb5ff` was
  applied 2026-07-27 and is an ancestor of `v7.3-rc1` (this checkout is
  `v7.3-rc4-27-gf0100363d8c37`). It is **not** an ancestor of `v7.2`.
- **Root cause (author):** missing error checks on FP register
  read/write in `s2250_s_ctrl()`.

**Step 1.4: Hidden bug fix?**
Record: **Yes, and it is not hidden.** The subject uses “propagate”
rather than “fix”, but the body is an uninitialized-use / false-success
bug. Saturation/hue changes are the same class: swallow write errors and
return 0.

## Phase 2: Diff analysis

**Step 2.1: Inventory**
Record:
- **File:** `drivers/media/usb/go7007/s2250-board.c` — **+33 / −21** (54
  lines with context; under the 100-line stable cap)
- **Function:** `s2250_s_ctrl()` only
- **Scope:** single-file surgical fix

**Step 2.2: Code flow**
Record (before → after), all in `s2250_s_ctrl()`:

- **Brightness / contrast:** `read_reg_fp()` / `write_reg_fp()` results
  ignored; always `break` then `return 0` → each call’s return is
  checked; first failure is returned; last write’s status is returned.
- **Saturation / hue:** write ignored, `return 0` → `return
  write_reg_fp(...)`.
- **Normal path:** unchanged when I/O succeeds (still RMW reserved bits,
  then write `0x140`).
- **Error path:** now fails the V4L2 set instead of committing a fake
  success.

**Step 2.3: Bug mechanism**
Record: **Uninitialized data + ignored I/O errors (logic/correctness).**

Verified in this tree: `read_reg_fp()` writes `*val` only after a
successful USB vendor request:

```249:286:drivers/media/usb/go7007/s2250-board.c
static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
{
        // ...
        if (go == NULL)
                return -ENODEV;
        if (go->status == STATUS_SHUTDOWN)
                return -EBUSY;
        // kzalloc / mutex_lock_interruptible / usb_control_msg failures
        // all return without *val = ...
        *val = (buf[0] << 8) | buf[1];
        kfree(buf);
        return 0;
}
```

`write_reg_fp()` likewise returns 0 or a negative errno, never a
positive byte count, so `if (ret)` is equivalent to `if (ret < 0)`.

On a failed read, `oldvalue` is stack garbage. The write is `ctrl->val |
(oldvalue & ~0xff)` (brightness) or `... & ~0x3f` (contrast), so
reserved bits come from that garbage.

**Step 2.4: Fix quality**
Record: **Obviously correct and minimal.** No API/data-structure change.
Regression risk is low: VIDIOC_S_CTRL that used to return 0 on hardware
failure now returns the errno. That is the intended V4L2 behavior
(`try_or_set_cluster()` only copies new values after `s_ctrl` succeeds).
Partial updates if a later write fails were already possible; the patch
does not add locking or new control IDs.

## Phase 3: Git history

**Step 3.1: Blame**
Record:
- Unchecked `read_reg_fp()` + `oldvalue` RMW: **05d76f2da1e5cc**
  (“s2250: subdev conversion”, 2009; contained in **v2.6.33-rc1**)
- Driver itself: **b11869dbb6cc4** (v2.6.29-rc1 era staging)
- Control-framework conversion: **d3b2ccd9e307ea** (2013) kept the same
  ignore-errors pattern
- Bug is old, not recent churn

**Step 3.2: Fixes: tag**
Record: **None.** No Fixes SHA to follow. The buggy pattern is the 2009
subdev conversion, not a recent regression.

**Step 3.3: File history**
Record: Recent `s2250-board.c` work is i2c probe conversions and a probe
leak fix, not a series this patch depends on. **Standalone.** Same-day
sibling by the same author: `41f82777e5477` (“avoid undefined shifts in
MPEG-4 headers”) — different file (`go7007-driver` MPEG path), not a
prerequisite.

**Step 3.4: Author**
Record: Yousef Alhouseen is not the subsystem maintainer. Two
media/go7007 correctness patches on 2026-06-30; Hans Verkuil applied
both. Maintainer SOB is a positive quality signal.

**Step 3.5: Dependencies**
Record: **None.** Uses existing `read_reg_fp()` / `write_reg_fp()` and
`s2250_s_ctrl()`. **Applies standalone.**

## Phase 4: Mailing list / external

**Step 4.1:**
Record:
- **b4 dig -c 59dc14a6cb5ff** → https://patch.msgid.link/20260630105015.
  53932-1-alhouseenyousef@gmail.com
- **b4 dig -a:** **v1 only** (committed diff matches v1)
- **b4 dig -m:** thread is the patch mail only — **no replies, no NAK,
  no Cc: stable**
- lore.kernel.org HTTP fetches returned **403**; discussion content was
  recovered via `b4`

**Step 4.2:**
Record: **b4 dig -w** recipients: Hans Verkuil, Mauro Chehab, linux-
media, linux-kernel. Appropriate lists/maintainers. Hans’s SOB on the
git commit is the review signal.

**Step 4.3:**
Record: **No bugzilla/syzbot/user report.** Finding is from code
inspection.

**Step 4.4:**
Record: Standalone v1 patch, not part of a numbered series. Sibling
MPEG-4 shift patch is independent.

**Step 4.5:**
Record: **UNVERIFIED** whether linux-stable ever discussed this
(lore.kernel.org 403; no local hit on this file’s history besides the
mainline commit).

## Phase 5: Semantic / call graph

**Step 5.1:**
Record: Modified function: **`s2250_s_ctrl`**. Helpers used:
`read_reg_fp`, `write_reg_fp`.

**Step 5.2: Callers**
Record: Wired as `s2250_ctrl_ops.s_ctrl`. Invoked from:
- `try_or_set_cluster()` → `call_op(master, s_ctrl)` (`v4l2-ctrls-
  core.c`)
- `__v4l2_ctrl_handler_setup()` during control setup
- Userspace: `v4l2_s_ctrl()` / `VIDIOC_S_CTRL` / `VIDIOC_S_EXT_CTRLS`

**Step 5.3: Callees**
Record: USB vendor requests via `go7007_usb_vendor_request()` →
`usb_control_msg()`. Also `mutex_lock_interruptible()` (can return
**-EINTR**).

**Step 5.4: Reachability**
Record: **Yes, from userspace** if `CONFIG_VIDEO_GO7007_USB_S2250_BOARD`
is enabled and a Sensoray 2250/2251 is present. Realistic failure that
still continues into the write: **EINTR on the read’s mutex**, then a
successful write mutex — two separate `mutex_lock_interruptible()`
calls. ENOMEM on the read’s `kzalloc` with a later successful write
alloc is also possible. `STATUS_SHUTDOWN`/`go == NULL` fail both read
and write before hardware access, so those paths do not program garbage.

**Step 5.5: Similar patterns**
Record: `s2250_s_std`, `s2250_set_fmt`, and `s2250_s_video_routing`
still ignore `write_reg_fp()` results. This patch does not claim to fix
those; they have no uninitialized `oldvalue`. Not a series dependency.

semcode MCP: **not available**; used `git grep` / file reads.

## Phase 6: This checkout

**Step 6.1:**
Record:
- Tree: **`v7.3-rc4-27-gf0100363d8c37`**, `make kernelversion` =
  **7.3.0-rc4**
- File and `s2250_s_ctrl()` **exist**
- Buggy ignore-error RMW existed in this lineage from 2009 until
  **59dc14a6cb5ff** (merged for **v7.3-rc1**)
- Current `HEAD` source already contains the fixed function (commit is
  an ancestor of `HEAD` and of `v7.3-rc4`)
- Bug was **not** introduced after this tree; it is old. This 7.3
  snapshot already includes the fix as a mainline merge, not as a stable
  cherry-pick.

**Step 6.2:**
Record: **Clean apply** to this file’s `s2250_s_ctrl()` shape (same
switch, same register macros). No conflicting refactor in this tree.

**Step 6.3:**
Record: No alternate fix for this `oldvalue` bug. Only this commit
changes those checks.

## Phase 7: Subsystem context

**Step 7.1:**
Record: **media / USB V4L2 driver** (`drivers/media/usb/go7007/`).
**PERIPHERAL** — Sensoray 2250/2251 only
(`CONFIG_VIDEO_GO7007_USB_S2250_BOARD`). Maintainer: Hans Verkuil,
linux-media.

**Step 7.2:**
Record: File is mature/low-churn (last functional s2250 work before this
was older i2c/probe fixes). Not a newly added subsystem.

## Phase 8: Impact and risk

**Step 8.1:**
Record: **Driver-specific / config-specific**
(`VIDEO_GO7007_USB_S2250_BOARD`). Not universal. Small user population
(legacy USB MPEG capture box).

**Step 8.2:**
Record:
- Trigger: `VIDIOC_S_CTRL` for brightness/contrast (and sat/hue for the
  false-success half)
- Common on a working device: **no** (happy path already initialized
  `oldvalue`)
- Realistic error: **signal interrupting the read lock**, USB control-
  msg failure, or alloc failure
- Unprivileged user with the video node can issue the ioctl

**Step 8.3:**
Record:
- **Failure mode:** uninitialized stack bits written into VPX322
  reserved fields; V4L2 still treats the set as success and publishes
  the new control value
- **Not** an oops, deadlock, filesystem corruption, or a demonstrated
  CVE
- **Severity: MEDIUM** (hardware misprogramming + lying to userspace).
  On shutdown-only failures, writes also fail first, so those are lower
  impact.

**Step 8.4:**
Record:
- **Benefit:** medium-low globally, high for the few users of this board
  if a control set races with EINTR/USB error
- **Risk:** **very low** (33 lines, error returns only, maintainer-
  applied)
- **Ratio:** favorable for a tiny correctness fix; the weak point is
  “important issue” given niche hardware and no reports

## Phase 9: Synthesis

**Step 9.1: Evidence**

**For backporting**
- Verified uninitialized `oldvalue` when `read_reg_fp()` fails
- Verified reserved-bit RMW from that garbage
- Verified V4L2 commits the new value if `s_ctrl` returns 0
- Realistic EINTR window (separate interruptible locks)
- Small, obviously correct, maintainer SOB
- No new API; under 100 lines
- Driver and function exist in this tree

**Against**
- Niche, aging Sensoray 2250/2251 hardware
- No user/syzbot/KMSAN report
- Not a crash, hang, or user-data corruption
- Looks like a static-analysis sweep (two go7007 patches the same day)
- Sibling functions still ignore I/O errors
- Official rule text wants a bug that “bothers people” or an “oh, that’s
  not good” issue — this is the latter, not a production fire

**Unresolved**
- Could not read lore.kernel.org in the browser (403); no on-list review
  beyond Hans applying v1
- Did not compile to confirm `-Wmaybe-uninitialized`
- No evidence of prior stable-list discussion

**Step 9.2: Stable rules checklist** (this tree)
1. Obviously correct and tested? **PASS** — mechanical error returns;
   applied by Hans Verkuil. No extra Tested-by.
2. Real bug that affects users? **PASS** — uninit RMW and false ioctl
   success on a reachable control path.
3. Important (crash/security/corruption/deadlock)? **PASS** (weak) —
   hardware register corruption and incorrect V4L2 success fall under
   “oh, that’s not good”, not oops/hang. Not a theoretical race without
   a trigger.
4. Small and contained? **PASS** — one function, +33/−21.
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — same `s2250_s_ctrl()`; this
   7.3-rc4 checkout already contains the commit as of v7.3-rc1.

**Step 9.3: Exception category**
Record: **None** (not a device ID, quirk, DT, build, or docs fix).

**Step 9.4: Decision**
This tree’s go7007/s2250 code is the long-standing buggy RMW path. The
patch is a small, maintainer-applied fix for uninitialized reserved-bit
writes and false `VIDIOC_S_CTRL` success. That is a real, user-visible
device-control bug with very low regression risk. It is not a core-
kernel crisis, but it is in-scope for stable as an “oh, that’s not good”
driver correctness fix, and the code it needs is present here.

### What the commit solves for this tree
`s2250_s_ctrl()` used to ignore FP register I/O errors. On
brightness/contrast, a failed read left `oldvalue` uninitialized and the
next write could set reserved VPX322 bits while V4L2 still stored the
new control. After the fix, those errors propagate so userspace is not
told the hardware update succeeded.

### Risk vs benefit
Benefit is limited to Sensoray 2250/2251 users, but the downside of
taking the patch is negligible. Returning errno instead of 0 on failed
I/O is the correct userspace contract.

---

Verification:
- [Phase 1] Parsed commit `59dc14a6cb5ff`; tags are author + Hans
  Verkuil SOB only
- [Phase 1] Confirmed no syzbot/Fixes/Link/Reported-by
- [Phase 2] Diff is only `s2250_s_ctrl()` in `s2250-board.c` (+33/−21)
- [Phase 2] Read `read_reg_fp()`/`write_reg_fp()`: `*val` set only on
  success; writes return 0 or negative
- [Phase 3] `git blame` on pre-patch function: ignore-errors RMW from
  `05d76f2da1e5cc` (v2.6.33-rc1)
- [Phase 3] No Fixes tag; sibling `41f82777e5477` is a different go7007
  issue, not a dep
- [Phase 3] `git merge-base --is-ancestor 59dc14a6cb5ff v7.2` → not in
  7.2; ancestor of `v7.3-rc1` and of HEAD
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1, Hans+media list, no thread
  replies, no stable nomination
- [Phase 4] WebFetch/curl to lore.kernel.org → 403; UNVERIFIED public
  review beyond the mbox
- [Phase 5] `s2250_ctrl_ops.s_ctrl` → `try_or_set_cluster()` /
  `v4l2_s_ctrl()`; userspace `VIDIOC_S_CTRL`
- [Phase 5] Confirmed `try_or_set_cluster()` does not publish new values
  if `s_ctrl` returns nonzero
- [Phase 6] `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
  kernelversion` = 7.3.0-rc4
- [Phase 6] Current file already has the error checks; driver Kconfig
  `VIDEO_GO7007_USB_S2250_BOARD` exists
- [Phase 7] MAINTAINERS: GO7007 MPEG CODEC, Hans Verkuil
- [Phase 8] Failure mode: reserved-bit programming + false success;
  severity MEDIUM; EINTR path verified in `read_reg_fp`/`write_reg_fp`
- [Phase 9] Official `stable-kernel-rules.rst` read: ≤100 lines, real
  bug, “oh that’s not good”, no new API
- UNVERIFIED: compiler warning reproduction; stable mailing-list history

**YES**

 drivers/media/usb/go7007/s2250-board.c | 54 ++++++++++++++++----------
 1 file changed, 33 insertions(+), 21 deletions(-)

diff --git a/drivers/media/usb/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c
index a155b987282f8..e536964c14e6a 100644
--- a/drivers/media/usb/go7007/s2250-board.c
+++ b/drivers/media/usb/go7007/s2250-board.c
@@ -365,36 +365,48 @@ static int s2250_s_ctrl(struct v4l2_ctrl *ctrl)
 	struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl);
 	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
 	u16 oldvalue;
+	int ret;
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
-			     ctrl->val | (oldvalue & ~0xff));
-		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
-			     ctrl->val | (oldvalue & ~0xff));
-		write_reg_fp(client, 0x140, 0x60);
-		break;
+		ret = read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
+		if (ret)
+			return ret;
+		ret = write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
+				   ctrl->val | (oldvalue & ~0xff));
+		if (ret)
+			return ret;
+		ret = read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
+		if (ret)
+			return ret;
+		ret = write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
+				   ctrl->val | (oldvalue & ~0xff));
+		if (ret)
+			return ret;
+		return write_reg_fp(client, 0x140, 0x60);
 	case V4L2_CID_CONTRAST:
-		read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_CONTRAST0,
-			     ctrl->val | (oldvalue & ~0x3f));
-		read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
-		write_reg_fp(client, VPX322_ADDR_CONTRAST1,
-			     ctrl->val | (oldvalue & ~0x3f));
-		write_reg_fp(client, 0x140, 0x60);
-		break;
+		ret = read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
+		if (ret)
+			return ret;
+		ret = write_reg_fp(client, VPX322_ADDR_CONTRAST0,
+				   ctrl->val | (oldvalue & ~0x3f));
+		if (ret)
+			return ret;
+		ret = read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
+		if (ret)
+			return ret;
+		ret = write_reg_fp(client, VPX322_ADDR_CONTRAST1,
+				   ctrl->val | (oldvalue & ~0x3f));
+		if (ret)
+			return ret;
+		return write_reg_fp(client, 0x140, 0x60);
 	case V4L2_CID_SATURATION:
-		write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
-		break;
+		return write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
 	case V4L2_CID_HUE:
-		write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
-		break;
+		return write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
 	default:
 		return -EINVAL;
 	}
-	return 0;
 }
 
 static int s2250_set_fmt(struct v4l2_subdev *sd,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: ivtv: stop VBI start-code scan before short tail
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (4 preceding siblings ...)
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: go7007: s2250: propagate control I/O failures Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: go7007: avoid undefined shifts in MPEG-4 headers Sasha Levin
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Hans Verkuil, Sasha Levin, awalls, mchehab,
	linux-media, linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit f373cf17fb8e7a530bc6e1e36fc41cb5dab2cdaa ]

compress_sliced_buf() scans one byte at a time while testing a four-byte
VBI start code.  The final iterations can read beyond the remaining
buffer tail.

Stop the scan once fewer than four bytes remain.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit message forensics

**Step 1.1: Subject line**
Record: **[media/ivtv] [stop] stop VBI start-code scan before a short
tail so a 4-byte SAV check cannot read past the buffer**

**Step 1.2: Tags**
Record:
- `Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>` (author)
- `Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (media/V4L
  maintainer; applied the patch)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
  by:`, `Link:`, or `Cc: stable`
- Absence of `Fixes:` / `Cc: stable` is expected for this review and is
  not a negative signal

**Step 1.3: Body**
Record:
- **Bug:** `compress_sliced_buf()` walks one byte at a time while
  testing a four-byte VBI start code (SAV: `0xff 0x00 0x00 sav`).
- **Symptom/failure mode:** last loop iterations read past the remaining
  buffer tail (out-of-bounds read of up to 3 bytes).
- **Version info:** none in the message.
- **Root cause:** loop bound is `i < size` while the body reads
  `buf[0]`..`buf[3]`.

**Step 1.4: Hidden bug fix?**
Record: **Not hidden.** This is an explicit bounds fix, not
cleanup/refactoring.

---

## Phase 2: Diff analysis

**Step 2.1: Inventory**
Record:
- File: `drivers/media/pci/ivtv/ivtv-vbi.c` — **1 insertion, 1
  deletion**
- Function: `compress_sliced_buf()`
- Scope: **single-file surgical one-liner**

**Step 2.2: Code flow**
Record:
- **Before:** `for (i = 0; i < size; i++, buf++)` then `buf[0]==0xff &&
  !buf[1] && !buf[2] && buf[3]==sav`
  - When `i == size-1`, `buf[1]`, `buf[2]`, `buf[3]` are 1–3 bytes past
    the declared `size`.
  - When `size` is 1, 2, or 3, the first iteration already overreads.
- **After:** `for (i = 0; i + 3 < size; i++, buf++)` — stop once fewer
  than 4 bytes remain.
- Path: **normal VBI parse path** (finding the first SAV), not an error-
  only path.

Verified pre-image:

```334:336:drivers/media/pci/ivtv/ivtv-vbi.c
                if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] ==
sav)
                        break;
```

(with the new `i + 3 < size` bound on the `for` line immediately above)

**Step 2.3: Bug mechanism**
Record: **Memory safety / out-of-bounds read.** The four-byte SAV test
used a one-byte walk with an inclusive `size` bound. The remaining `size
-= i` / `size < line_size` logic still bails out on a short tail, so
this is an **overread**, not a later overflow write.

**Step 2.4: Fix quality**
Record:
- **Obviously correct:** the predicate now matches the 4-byte access.
  Same pattern as the sibling `cx18` fix (`bf533acaaa7de`).
- **Minimal:** one loop condition, no API/data-structure change.
- **Regression risk: very low.** If `size < 4`, the loop does not run,
  `i` stays 0, then `size < line_size` (51/272/284) returns as before. A
  4-byte SAV at the last valid position is still seen (`i + 3 < size`
  allows `i == size-4`).

---

## Phase 3: Git history

**Step 3.1: Blame**
Record: The scan loop (including `buf[3]`) was introduced in
**`1a0adaf37c30e`** — *V4L/DVB (5345): ivtv driver for Conexant
cx23416/cx23415 MPEG encoder/decoder* (Hans Verkuil, **2007-04-27**).
The bug is as old as the driver.

**Step 3.2: Fixes: tag**
Record: **No Fixes: tag.** The introducing commit is the original ivtv
merge (`1a0adaf37c30e`), present in this tree (`git merge-base --is-
ancestor` exit 0).

**Step 3.3: File history**
Record: Recent commits on this file are email-address churn, an
uninitialized `vbi.type` fix (`31218df77e7f1`), SPDX, and this bounds
fix. **No prerequisite refactor.** Standalone; not `patch X/Y`.

**Step 3.4: Author**
Record: Pengpeng Hou’s only ivtv commit is this one. Same
day/author/message as **`bf533acaaa7de`** (`media: cx18: stop VBI start-
code scan before short tail`). Hans Verkuil applied both; he is the
long-time V4L maintainer and original ivtv author. That is a strong
quality signal.

**Step 3.5: Dependencies**
Record: **None.** The loop, `sav` argument, and `buf[3]` access already
exist. The cx18 sibling is independent (different driver). **Applies
standalone.**

---

## Phase 4: Mailing list / external

**Step 4.1: Original discussion**
Record:
- `b4 dig -c f373cf17fb8e7` →
  https://patch.msgid.link/2026063008027101.2-ccfa108-0015-media-ivtv-
  stop-VBI-start-c-pengpeng@iscas.ac.cn
- `b4 dig -a`: **v1 only** (2026-06-30), no later revisions.
- Saved mbox: **patch only, no replies.** No NAK, no reviewer
  commentary, no in-thread `Cc: stable`.
- lore.kernel.org HTML fetch returned **403** (Anubis bot-wall). Thread
  content was recovered via `b4 dig -m`.

**Step 4.2: Recipients (`b4 dig -w`)**
Record: To/Cc included **Andy Walls** (IVTV maintainer in MAINTAINERS),
**Mauro Carvalho Chehab**, `linux-media@vger.kernel.org`, `linux-
kernel@vger.kernel.org`. Applied by **Hans Verkuil**.

**Step 4.3: Bug report**
Record: **No user/syzbot/bugzilla report.** Looks like a static-
analysis/audit fix (author has many similar bounds patches). The
mechanism is still a real OOB read, verified from the code.

**Step 4.4: Related series**
Record: Paired with **cx18** commit `bf533acaaa7de` (same wording, same
day). Each is self-contained. This ivtv commit does not need the cx18
change.

**Step 4.5: Stable list**
Record: **UNVERIFIED** — lore.kernel.org/stable returned 403. No
evidence in-tree of a prior rejection.

---

## Phase 5: Semantic / call-chain

**Step 5.1: Functions**
Record: `compress_sliced_buf()` only.

**Step 5.2: Callers**
Record: Only `ivtv_process_vbi_data()` in the same file, twice:

```398:404:drivers/media/pci/ivtv/ivtv-vbi.c
                lines = compress_sliced_buf(itv, 0, p, size / 2,
                        itv->vbi.sliced_decoder_sav_odd_field);
                /* second field */
                /* experimentation shows that the second half does not
always begin
                   at the exact address. So start a bit earlier (hence
32). */
                lines = compress_sliced_buf(itv, lines, p + size / 2 -
32, size / 2 + 32,
                        itv->vbi.sliced_decoder_sav_even_field);
```

`ivtv_process_vbi_data()` callers:
- `ivtv_get_buffer()` in `ivtv-fileops.c` (userspace read of MPEG/VBI
  streams)
- `dma_post()` in `ivtv-irq.c` (decoder VBI DMA completion)

**Step 5.3: Callees**
Record: After the scan, `v4l2_subdev_call(..., decode_vbi_line, ...)`.
The OOB is in the scan itself, before that call.

**Step 5.4: Reachability**
Record: Reachable when sliced VBI capture/processing runs on **Hauppauge
PVR-150/250/350/500** (and other cx23415/cx23416 cards),
`CONFIG_VIDEO_IVTV`. Needs the hardware; not a generic syscall fuzz
path. Real for those devices.

**Step 5.5: Similar patterns**
Record: `cx18` had the identical bug and the same one-line fix.
`compress_raw_buf()` indexes `p[0..3]` at `buf + i * line_size` with `i
< lines`, a different bound; not the same bug.

---

## Phase 6: This tree

**Step 6.1: Local tree and buggy code**
Record:
- `git describe HEAD` → **`v7.3-rc4-27-gf0100363d8c37`** (`VERSION=7`,
  `PATCHLEVEL=3`, `SUBLEVEL=0`, `EXTRAVERSION=-rc4`)
- Candidate **`f373cf17fb8e7` is already an ancestor of HEAD**
- Buggy loop existed here from **2007** until that commit; pre-image
  confirmed via `git show f373cf17fb8e7^:drivers/media/pci/ivtv/ivtv-
  vbi.c`

This checkout is **7.3-rc4 mainline**, not an older -stable branch. The
bug class and the surrounding code are the same ones every current LTS
still carries.

**Step 6.2: Backport difficulty**
Record: **Clean apply.** The `for (i = 0; i < size; i++, buf++)` line
has been unchanged since 2007.

**Step 6.3: Related fixes already here**
Record: Only this commit and the cx18 sibling. No alternate ivtv fix for
the same scan.

---

## Phase 7: Subsystem context

**Step 7.1**
Record: **media/pci/ivtv** — Hauppauge PVR / Conexant cx2341x MPEG
encoder. **PERIPHERAL** (specific old PCI capture cards), but a
supported in-tree driver, not staging.

**Step 7.2**
Record: The file is **mature/quiet**. The driver has been stable for
years; this is a long-standing latent bounds bug, not fallout from a new
feature.

---

## Phase 8: Impact and risk

**Step 8.1: Who is affected**
Record: **Driver-specific / config-specific** (`CONFIG_VIDEO_IVTV`),
users capturing **sliced VBI** on those cards.

**Step 8.2: Trigger**
Record: Hardware DMA fills an ivtv buffer; `ivtv_process_vbi_data()`
scans for SAV. Fires whenever the start code is missing or near the tail
(including a full walk with no match). Unprivileged users can hit it if
they can open the V4L VBI/MPEG node. Not a remote network path.

Buffers are `kmalloc(s->buf_size + 256)` and DMA last-SG size is also
`+= 256` (`ivtv-queue.c`, `ivtv-irq.c`). `dma_post()` may do
`buf->bytesused += s->dma_last_offset` (cookie search up to 252 bytes).
A 3-byte overread of the **logical** `size` often still sits inside that
256-byte DMA window, so a crash is not guaranteed; it is still an out-
of-bounds access relative to the length the scan is given, and
`bytesused` can sit close to the allocation.

**Step 8.3: Failure mode**
Record: **Out-of-bounds read (up to 3 bytes).** Severity **MEDIUM–HIGH**
as memory safety; practical oops risk **MEDIUM** (small overread, extra
DMA padding). Remaining length after a false SAV in the tail is `< 4`,
so `size < line_size` returns without treating the overread as payload.
**Not data corruption of the VBI output**, but a real buffer-tail
overread.

**Step 8.4: Risk–benefit**
Record:
- **Benefit:** stops a real OOB read on a path that runs during VBI
  capture; same class as other stable OOB one-liners; bug present on
  every LTS.
- **Risk:** one loop bound, no locking/API change — **very low**.
- **Ratio:** strongly favors taking the fix.

---

## Phase 9: Synthesis

**Step 9.1: Evidence**

For:
- Real 4-byte load on a 1-byte scan; last iterations read past `size`
- One-line, obviously correct, no new API
- Bug in tree since 2007 (`1a0adaf37c30e`); clean apply
- Applied by Hans Verkuil; To: Andy Walls (ivtv maintainer)
- Sibling cx18 fix of the same bug
- Standalone; no series dependency

Against:
- No crash/syzbot/`Reported-by`
- Niche, aging PCI hardware
- +256 DMA/kmalloc padding makes a guaranteed heap oops less likely
- No mailing-list review comments (v1 applied as-is)

Unresolved:
- Stable-list discussion (lore 403)
- Exact KASAN behavior vs. the +256 allocation (not reproduced here)

**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — bound matches the 4-byte
   access; maintainer applied it; v1 needed no respin.
2. Real bug affecting users? **PASS** — OOB read on sliced-VBI
   processing for ivtv hardware.
3. Important (crash/security/corruption/deadlock)? **PASS** — memory-
   safety OOB read; practical crash is not certain, but this is the
   standard small OOB class, not a style tweak.
4. Small and contained? **PASS** — 1 line, one function.
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — already in 7.3-rc4; pre-fix line
   is the original 2007 loop, so older stables should take it cleanly.

**Step 9.3: Exception category**
Record: Not a device-ID/quirk/DT/build/doc exception. It is a **small
memory-safety fix**.

**Step 9.4: Decision**
The commit is a one-line, obviously correct stop of a four-byte SAV scan
that walked off the declared VBI buffer. That bug has been in ivtv since
2007, needs no prerequisites, and is the same fix already used on cx18.
It belongs in stable.

---

## Verification

- **[Phase 1]** Parsed tags: only author + Hans Verkuil SOBs; no
  Fixes/Reported-by/Cc: stable
- **[Phase 2]** Diff: 1 line in `compress_sliced_buf()`; `i < size` → `i
  + 3 < size`
- **[Phase 2]** Confirmed `buf[0]..buf[3]` SAV test in current file at
  lines 333–335
- **[Phase 3]** `git blame`: loop from `1a0adaf37c30e` (2007-04-27);
  bound line is this commit
- **[Phase 3]** `git merge-base --is-ancestor 1a0adaf37c30e HEAD` → yes
- **[Phase 3]** `git show f373cf17fb8e7^:...ivtv-vbi.c` → old `i < size`
  loop present
- **[Phase 3]** File log: no prerequisite refactor; sibling
  `bf533acaaa7de` is cx18-only
- **[Phase 4]** `b4 dig -c f373cf17fb8e7`: lore/msgid link above; `b4
  dig -a`: v1 only
- **[Phase 4]** `b4 dig -w`: Andy Walls, Mauro Chehab, linux-media,
  linux-kernel
- **[Phase 4]** `b4 dig -m`: 81-line mbox, patch only, no replies
- **[Phase 4]** WebFetch/curl to lore: 403 — stable-list search
  UNVERIFIED
- **[Phase 5]** Callers: `ivtv_process_vbi_data` ← `ivtv-fileops.c`,
  `ivtv-irq.c`
- **[Phase 5]** cx18 `compress_sliced_buf` uses the same `i + 3 < size`
  bound after `bf533acaaa7de`
- **[Phase 6]** `git describe HEAD` = v7.3-rc4-27-g…; `make
  kernelversion` = 7.3.0-rc4
- **[Phase 6]** `git merge-base --is-ancestor f373cf17fb8e7 HEAD` →
  already in this tree
- **[Phase 7]** MAINTAINERS: IVTV → Andy Walls, linux-media
- **[Phase 8]** kmalloc `buf_size+256` and DMA `size += 256` /
  `bytesused += dma_last_offset` verified in `ivtv-queue.c` and `ivtv-
  irq.c`
- **UNVERIFIED:** whether this overread was ever KASAN-reported; whether
  stable@ discussed it

The fix is small, surgical, and meets the stable criteria for an out-of-
bounds read.

**YES**

 drivers/media/pci/ivtv/ivtv-vbi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c
index ae7a00f462574..af086c4cbe1a7 100644
--- a/drivers/media/pci/ivtv/ivtv-vbi.c
+++ b/drivers/media/pci/ivtv/ivtv-vbi.c
@@ -330,7 +330,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8
 	unsigned lines = 0;
 
 	/* find the first valid line */
-	for (i = 0; i < size; i++, buf++) {
+	for (i = 0; i + 3 < size; i++, buf++) {
 		if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
 			break;
 	}
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: go7007: avoid undefined shifts in MPEG-4 headers
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (5 preceding siblings ...)
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: ivtv: stop VBI start-code scan before short tail Sasha Levin
@ 2026-10-19 13:49 ` Sasha Levin
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: cx88: fix memory leak in cx8802_register_driver() error path Sasha Levin
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:49 UTC (permalink / raw)
  To: patches, stable
  Cc: Yousef Alhouseen, Hans Verkuil, Sasha Levin, hverkuil, mchehab,
	linux-media, linux-kernel

From: Yousef Alhouseen <alhouseenyousef@gmail.com>

[ Upstream commit 41f82777e547732460290ceb28fcc7c1b95ef192 ]

The byte-alignment paths can call CODE_ADD() with a zero bit
length.  The macro then shifts an int by name.b, which can be 32
after the preceding bit was flushed.

vti_bitlen() can likewise shift a signed int into its sign bit while
searching for the bit length, and the package mask construction can
shift by the full type width.

Make zero-length additions a no-op, derive the bit length with fls(),
and build the mask with GENMASK().

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit message forensics

**Step 1.1 — Subject line**
Record: `[media/go7007] [avoid] undefined shifts in MPEG-4 header bit-
packing`. Subsystem is the WIS GO7007 USB MPEG encoder. “Avoid” is a
bug-fix verb: the patch stops C undefined behavior, not adding a
feature.

**Step 1.2 — Tags**
Record:
- `Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>` (author)
- `Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (media
  maintainer; applied)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
  by:`, `Link:`, or `Cc: stable` (absence of Fixes/Cc-stable is expected
  for this review)

**Step 1.3 — Body**
Record:
- Bug: `CODE_ADD()` can be called with bit length 0; after a flush
  `name.b` can be 32, so `(val) << name.b` is a 32-bit shift of a 32-bit
  int (C UB).
- `vti_bitlen()` uses `(1 << i)` with signed `1` and `i` starting at 31
  (shift into the sign bit).
- Package mask `(1 << vop_time_increment_bitlength) - 1` can shift by
  the full type width.
- Symptoms: UBSAN shift diagnostics; wrong bitstream on arches that mask
  the shift count; possible hang in `vti_bitlen()` when `max_time_incr
  == 0`.
- No version range or crash log in the message.
- Root cause as stated: unguarded shift counts in the MPEG header
  bitpacker.

**Step 1.4 — Hidden bug fix?**
Record: Not disguised. It is an explicit UB/correctness fix. The `fls()`
rewrite is equivalent for every nonzero value and also stops an unsigned
wrap / infinite loop when `max_time_incr == 0`.

---

## Phase 2: Diff analysis

**Step 2.1 — Inventory**
Record:
- File: `drivers/media/usb/go7007/go7007-fw.c` (+15 / −13)
- Functions/macros: `CODE_ADD`, `vti_bitlen()`, `seqhead_to_package()`;
  plus `#include <linux/bitops.h>`
- Scope: single-file surgical fix

**Step 2.2 — Flow change**
Record:
1. `CODE_ADD`: previously always did `name.b -= length; name.a |= (val)
   << name.b`. After: `if (length)` wraps the body, so length-0 is a no-
   op.
2. `vti_bitlen`: previously a countdown from 31 with `(1 << i) - 1`
   masks. After: `fls(max_time_incr)` with `bitlen ?: 1`.
3. `seqhead_to_package`: `(1 << vop_time_increment_bitlength) - 1` →
   `GENMASK(vop_time_increment_bitlength - 1, 0)`.

Affected path is firmware-image construction at MPEG-4 stream start
(`go7007_start_encoder()`), not a generic hot path.

**Step 2.3 — Bug mechanism**
Record: **Type / undefined-shift (UBSAN class)**, with a logic/hang side
effect.

Verified zero-length `CODE_ADD` in `mpeg4_frame_header()` /
`mpeg4_sequence_header()`:

```758:761:drivers/media/usb/go7007/go7007-fw.c
        /* Byte-align with a zero followed by ones */
        i = 8 - (CODE_LENGTH(c) % 8);
        CODE_ADD(c, 0, 1);
        CODE_ADD(c, (1 << (i - 1)) - 1, i - 1);
```

When `CODE_LENGTH % 8 == 7`, `i == 1`, so the second call is
`CODE_ADD(..., 0, 0)`. After the 1-bit add, `name.b` can be 32, then
`(val) << 32` is UB.

Pre-fix `vti_bitlen`:

```c
for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i)
    ;
return i + 1;
```

`1 << 31` is a signed shift into the sign bit (UB) on every call. If
`max_time_incr == 0`, the condition is always true, `i` is `unsigned
int`, `--i` wraps, and the loop does not terminate.

**Step 2.4 — Fix quality**
Record: Obviously correct and minimal.
- `fls(x)` matches the old loop for all `x > 0` (spot-checked 1, 2,
  30000, 0x80000000).
- `fls(0) ?: 1` returns 1 instead of hanging.
- `GENMASK(n-1, 0)` is the defined way to build an n-bit mask;
  `vti_bitlen()` never returns 0 after the `?: 1` guard, so `GENMASK(-1,
  0)` cannot happen.
- Regression risk is low: no locking, no API, no data-structure change.
  Residual UB not in this patch: `(1 << (i - 1))` in the same padding
  path is safe because `i` is in 1..8.

---

## Phase 3: Git history

**Step 3.1 — Blame**
Record: Buggy `CODE_ADD` / `vti_bitlen` / mask come from
`866b8695d67e83` (“Staging: add the go7007 video driver”, 2008-10-10).
Driver left staging in `7955f03d18d14`. The bug is ~18 years old, not
recent churn.

**Step 3.2 — Fixes: tag**
Record: No `Fixes:` tag. Introducer is the 2008 staging add above. `git
merge-base --is-ancestor 41f82777e5477 HEAD` is true: this snapshot
already contains the fix.

**Step 3.3 — File history**
Record: Recent `go7007-fw.c` commits are unrelated (min/max macros,
SPDX, KASAN frame warning, sparse). Standalone, not `N/M`.

**Step 3.4 — Author**
Record: Yousef Alhouseen is not the media maintainer; nearby work is a
series of small correctness patches. Weight comes from Hans Verkuil’s
SOB (applied to media tree).

**Step 3.5 — Dependencies**
Record: Needs `fls()` and `GENMASK()`, both long-standing
(`<linux/bitops.h>` / `<linux/bits.h>`). No prerequisite series. Can
apply standalone to any tree that still has this file.

---

## Phase 4: Mailing list / external

**Step 4.1 — Original discussion**
Record: `b4 dig -c 41f82777e5477` → https://patch.msgid.link/20260630105
257.54757-1-alhouseenyousef@gmail.com
`b4 dig -a`: **v1 only**, one revision.
Saved mbox: single message, no replies. Hans applied it without public
review comments. No NAK, no reviewer `Cc: stable`.

**Step 4.2 — Recipients (`b4 dig -w`)**
Record: Hans Verkuil, Mauro Chehab, linux-media, linux-kernel. Right
maintainers were on the To/Cc list.

**Step 4.3 — Bug report**
Record: No syzbot/bugzilla/Reported-by. Inspection/UBSAN-style fix, not
a user crash report.

**Step 4.4 — Series**
Record: Standalone v1. Same-day sibling `media: go7007: s2250: propagate
control I/O failures` is a different bug.

**Step 4.5 — Stable list**
Record: lore.kernel.org/stable fetch returned 403. Web search for this
subject on stable found **no** discussion. UNVERIFIED beyond that
search.

---

## Phase 5: Semantic / call graph

**Step 5.1 — Functions**
Record: `CODE_ADD` (macro), `vti_bitlen()`, `seqhead_to_package()`. No
semcode MCP in this environment; used grep.

**Step 5.2 — Callers**
Record:
- `vti_bitlen()` ← `mpeg4_frame_header()`, `mpeg4_sequence_header()`,
  `seqhead_to_package()`
- those ← `gen_mpeg4hdr_to_package()` / `do_special(SPECIAL_SEQHEAD)`
  when `go->format == V4L2_PIX_FMT_MPEG4`
- `go7007_construct_fw_image()` ← `go7007_start_encoder()` ←
  `go7007_start_streaming()` (vb2 `start_streaming`)

**Step 5.3 — Callees**
Record: After the patch, `fls()` and `GENMASK()` only. No alloc/lock in
the changed lines.

**Step 5.4 — Reachability**
Record: Yes, from userspace: open the V4L2 node, `VIDIOC_S_FMT` MPEG-4,
`VIDIOC_STREAMON`. Firmware construction runs with `hw_lock` held.

`VIDIOC_S_PARM` can make `fps_scale` huge:

```485:491:drivers/media/usb/go7007/go7007-v4l2.c
        n = go->sensor_framerate *
                parm->parm.capture.timeperframe.numerator;
        d = 1001 * parm->parm.capture.timeperframe.denominator;
        if (n != 0 && d != 0 && n > d)
                go->fps_scale = (n + d/2) / d;
        else
                go->fps_scale = 1;
```

If `fps_scale > sensor_framerate` (~25025–30030), `max_time_incr == 0`
and the old loop hangs while holding `hw_lock`. Needs device node access
(typically `video` group), not a random unprivileged syscall on machines
without the hardware.

**Step 5.5 — Similar patterns**
Record: MPEG-1 byte-align already skips `CODE_ADD` when `j == 8`. MPEG-4
padding is the length-0 case. No sibling drivers share this macro.

---

## Phase 6: This checkout

**Step 6.1 — Does the buggy code exist here?**
Record: Local tree is **v7.3-rc4** (`7.3.0-rc4`, `f0100363d8c37`). The
driver is present. Current `go7007-fw.c` already has the fix (`#include
<linux/bitops.h>`, `if (length)`, `fls()`, `GENMASK()`). Pre-fix code
lived in this file from 2008 until `41f82777e5477` (2026-07-15). Any
stable kernel that still has unfixed `go7007-fw.c` has the bug.

**Step 6.2 — Backport difficulty**
Record: Clean apply. The bitpacker has been stable since 2008; the hunks
match the historical file. Only extra include is `<linux/bitops.h>`.

**Step 6.3 — Related fixes already here**
Record: This *is* the fix. No earlier alternate fix in the file history.

---

## Phase 7: Subsystem context

**Step 7.1**
Record: `drivers/media/usb/go7007` — USB V4L2 MPEG encoder (WIS GO7007 /
Sensoray 2250, Plextor, etc.). Criticality: **PERIPHERAL** (specific old
capture dongles), but not staging.

**Step 7.2**
Record: Low churn. Recent commits are small leak/error-path fixes.
Mature, rarely touched encoder header generator.

---

## Phase 8: Impact and risk

**Step 8.1 — Who is affected**
Record: Users of `CONFIG_VIDEO_GO7007` with MPEG-4 encode. Hardware IDs
include Sensoray 2250/2251 (`0x1943:0xa250`) and several WIS/Plextor USB
IDs. Not universal.

**Step 8.2 — Trigger**
Record:
- Common: every MPEG-4 `STREAMON` can hit length-0 `CODE_ADD` depending
  on header bit length (UBSAN / UB). Typical `val` is 0, so x86 often
  still produces a no-op.
- Uncommon but real: `VIDIOC_S_PARM` with a large time-per-frame →
  `max_time_incr == 0` → old `vti_bitlen` infinite loop under `hw_lock`.
- Typical `sensor_framerate` is 25025/30000/30030, so `(1 << vti_bitlen)
  - 1` is a ~15-bit shift and not the 32-bit case; the GENMASK change is
  defensive for that site.

**Step 8.3 — Failure mode**
Record:
- Length-0 shift: UBSAN / undefined; functional impact usually none
  because `val == 0`. Severity **MEDIUM** (UBSAN), not a proven oops.
- `vti_bitlen` hang: driver stuck with `hw_lock` held → STREAMON never
  finishes. Severity **HIGH** for that device, not a machine-wide panic.
- Overall: **MEDIUM–HIGH**, not core-kernel CRITICAL.

**Step 8.4 — Risk vs benefit**
Record: Benefit medium for go7007 users (defined behavior, no hang).
Risk **very low** (~15 lines, equivalent `fls()`, maintainer-applied).
Ratio favors backport.

---

## Phase 9: Synthesis

**Step 9.1 — Evidence**

For:
- Real C undefined shifts in reachable MPEG-4 header generation
- Old `vti_bitlen()` can livelock when `fps_scale` is large
- 15/13 lines, one file, obviously correct
- `fls()` is equivalent for all nonzero inputs
- Hans Verkuil signed off
- Bug present since 2008; applies cleanly
- No new API/feature

Against:
- Niche USB encoder, few systems
- No user/syzbot report
- Common-path length-0 add is `val==0`, often a practical no-op
- GENMASK site is not a 32-bit shift with real framerates
- No public review beyond maintainer apply

Unresolved:
- Could not read lore.kernel.org/stable (403)
- No sanitizer log attached to the commit (whether UBSAN actually fired
  is unverified)

**Step 9.2 — Stable rules**
1. Obviously correct and tested? **PASS** — equivalent rewrite;
   maintainer applied v1.
2. Real bug that affects users? **PASS** — UB on MPEG-4 start; hang if
   `max_time_incr==0`.
3. Important (crash/security/corruption/deadlock)? **PASS** — hang under
   `hw_lock` plus UBSAN-class UB. Not a core panic, but a real driver
   DoS/UB, not style cleanup.
4. Small and contained? **PASS** — one file, ~28 lines.
5. No new features/APIs? **PASS**.
6. Applies to this tree’s go7007 code? **PASS** — same file/macros;
   include is standard.

**Step 9.3 — Exception category**
Record: None (not a device ID/quirk/DT/build/docs). It is a normal small
correctness fix.

**Step 9.4 — Decision**
This checkout is mainline 7.3-rc4, which already contains the commit;
the question is whether the fix has stable technical merit for trees
that still have the 2008 bitpacker. It does: small, correct, no
dependencies, fixes defined-behavior bugs and a reachable livelock in
`go7007_start_encoder()`. Risk of regression is negligible.

### What the commit solves for stable users
On MPEG-4 stream start the GO7007 firmware generator packes headers with
`CODE_ADD()`. Padding can request a 0-bit add after a flush (`name.b ==
32`), which is an illegal shift. `vti_bitlen()` always does `1 << 31`
and, if userspace sets a very large frame interval, can spin forever
with `hw_lock` held so `VIDIOC_STREAMON` never returns. The patch skips
zero-length adds, uses `fls()`, and builds the mask with `GENMASK()`.

### Risk vs benefit
Benefit is defined behavior and no encoder-start hang for remaining
GO7007/Sensoray users. Risk is a few lines in a dormant driver with no
API change.

### Concerns
Obscure hardware and no field report. That lowers urgency, not
correctness. No backport rework needed.

---

Verification:
- [Phase 1] Parsed subject/body/tags: only author + Hans Verkuil SOBs;
  no Fixes/Reported-by/Link/Cc-stable
- [Phase 2] `git show --numstat 41f82777e5477`: 15/13, one file; read
  current and `41f82777e5477^` `CODE_ADD` / `vti_bitlen` / mask
- [Phase 2] Confirmed length-0 path: `i = 8 - (CODE_LENGTH % 8)` then
  `CODE_ADD(..., i-1)` when `i==1`
- [Phase 2] Confirmed `fls` equivalence for 1, 2, 30000, 0x80000000;
  `fls(0)?:1` vs old wrap
- [Phase 3] `git blame` / `git log -1 866b8695d67e83`: introduced 2008
  with staging driver
- [Phase 3] `git merge-base --is-ancestor 41f82777e5477 HEAD` → yes
  (already in this 7.3-rc4 snapshot)
- [Phase 3] `git log --oneline --author="Yousef Alhouseen"`: standalone
  vs nearby s2250 patch
- [Phase 4] `b4 dig -c/-a/-w/-m`: v1 only; To Hans/Mauro/linux-media;
  mbox has no replies
- [Phase 4] lore.kernel.org 403; lkml.iu.edu shows the same v1 patch
  text
- [Phase 4] WebSearch stable archive: no hit for this subject
- [Phase 5] grep callers: `vti_bitlen` → MPEG-4 headers → `do_special` →
  `go7007_construct_fw_image` → `go7007_start_encoder` →
  `go7007_start_streaming`
- [Phase 5] Read `vidioc_s_parm`: `fps_scale` unbounded when `n > d`
- [Phase 6] `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
  kernelversion` = 7.3.0-rc4
- [Phase 6] Current file already has the fix; parent file has the old
  loop/mask
- [Phase 7] Kconfig `VIDEO_GO7007`; USB IDs include Sensoray 2250
- [Phase 8] Failure: UB on padding; hang if `max_time_incr==0` under
  `hw_lock`
- UNVERIFIED: whether UBSAN actually reported this in a boot/log;
  stable-list archives beyond web search (403)

**YES**

 drivers/media/usb/go7007/go7007-fw.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c
index 86ce593e0c546..8cf959c20e30c 100644
--- a/drivers/media/usb/go7007/go7007-fw.c
+++ b/drivers/media/usb/go7007/go7007-fw.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/bitops.h>
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/device.h>
@@ -58,14 +59,16 @@ struct code_gen {
 #define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 }
 
 #define CODE_ADD(name, val, length) do { \
-	name.b -= (length); \
-	name.a |= (val) << name.b; \
-	while (name.b <= 24) { \
-		*name.p = name.a >> 24; \
-		++name.p; \
-		name.a <<= 8; \
-		name.b += 8; \
-		name.len += 8; \
+	if (length) { \
+		name.b -= (length); \
+		name.a |= (val) << name.b; \
+		while (name.b <= 24) { \
+			*name.p = name.a >> 24; \
+			++name.p; \
+			name.a <<= 8; \
+			name.b += 8; \
+			name.len += 8; \
+		} \
 	} \
 } while (0)
 
@@ -707,11 +710,10 @@ static int gen_mpeg1hdr_to_package(struct go7007 *go,
 
 static int vti_bitlen(struct go7007 *go)
 {
-	unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale;
+	unsigned int max_time_incr = go->sensor_framerate / go->fps_scale;
+	int bitlen = fls(max_time_incr);
 
-	for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i)
-		;
-	return i + 1;
+	return bitlen ?: 1;
 }
 
 static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf,
@@ -1209,7 +1211,7 @@ static int seqhead_to_package(struct go7007 *go, __le16 *code, int space,
 		0xbf08,		fps,
 		0xbf09,		0,
 		0xbff2,		vop_time_increment_bitlength,
-		0xbff3,		(1 << vop_time_increment_bitlength) - 1,
+		0xbff3,		GENMASK(vop_time_increment_bitlength - 1, 0),
 		0xbfe6,		0,
 		0xbfe7,		(fps / 1000) << 8,
 		0,		0,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: cx88: fix memory leak in cx8802_register_driver() error path
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (6 preceding siblings ...)
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: go7007: avoid undefined shifts in MPEG-4 headers Sasha Levin
@ 2026-10-19 13:49 ` Sasha Levin
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: cec: tegra: add missing MODULE_DEVICE_TABLE() Sasha Levin
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:49 UTC (permalink / raw)
  To: patches, stable
  Cc: Chen Changcheng, Hans Verkuil, Sasha Levin, mchehab, linux-media,
	linux-kernel

From: Chen Changcheng <chenchangcheng@kylinos.cn>

[ Upstream commit e228b8b1a5b47a72b265671dc6d864c0da5528d0 ]

In cx8802_register_driver(), when drv->probe(driver) fails (non-zero),
the allocated cx8802_driver struct is freed neither in the else branch
nor later in cx8802_unregister_driver() (which only frees entries that
were added to dev->drvlist on success). Each failed probe leaks the
driver struct.

Add kfree(driver) in the else branch to fix the leak.

Signed-off-by: Chen Changcheng <chenchangcheng@kylinos.cn>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This is a one-line leak fix in a long-standing cx88 error path. Local
tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The buggy code has
been in this lineage since 2006, and the patch is self-contained.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

Step 1.1: PARSE THE SUBJECT LINE
Record: **[media/cx88] [fix] [free leaked `cx8802_driver` when
`drv->probe()` fails in `cx8802_register_driver()`]**

Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Signed-off-by:** Chen Changcheng `<chenchangcheng@kylinos.cn>`
  (author)
- **Signed-off-by:** Hans Verkuil `<hverkuil+cisco@kernel.org>` (media
  maintainer; applied the patch)
- **No Fixes:** tag (expected for this review pipeline)
- **No Cc: stable@vger.kernel.org** (expected; not a negative signal)
- **No Reported-by / Tested-by / Reviewed-by / Acked-by / Link**
- Ignore any pipeline “Upstream commit” / Sasha Levin SOB (none on this
  commit object itself)

Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** In `cx8802_register_driver()`, `kzalloc`/`kzalloc_obj` of a
  `cx8802_driver` is not freed when `drv->probe(driver)` returns non-
  zero. `cx8802_unregister_driver()` only `kfree`s entries that were
  `list_add_tail`’d onto `dev->drvlist` after a successful probe.
- **Symptom:** Each failed probe leaks one `cx8802_driver` object until
  reboot (or forever across module reload).
- **Version info:** none in the message. History shows the
  allocation+else-without-free pattern dates to 2006.
- **Root cause (author):** failed probes never join `drvlist`, so
  unregister cannot reclaim them; the else branch must `kfree(driver)`.

Step 1.4: DETECT HIDDEN BUG FIXES
Record: **Not hidden.** Subject and body say “fix memory leak”. The diff
is exactly that: add `kfree(driver)` on the probe-failure path.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

Step 2.1: INVENTORY THE CHANGES
Record:
- **File:** `drivers/media/pci/cx88/cx88-mpeg.c` — **+1 / -0**
- **Function:** `cx8802_register_driver()`
- **Scope:** single-file, single-line, surgical error-path fix

Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record: Before (verified at `e228b8b1a5b47^`):

```
err = drv->probe(driver);
if (err == 0) {
    i++;
    list_add_tail(&driver->drvlist, &dev->drvlist);
} else {
    pr_err("cx8802 probe failed, err = %d\n", err);
}
```

After: same, plus `kfree(driver)` in the else branch. Only the **probe-
failure path** changes. Success path, ENOMEM `goto out`, and unregister
of successful entries are unchanged.

Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **[Error path / resource leak]** Mechanism: per-device snapshot
of `struct cx8802_driver` is allocated, probe fails, pointer is dropped.
Unregister walks `dev->drvlist` only, so the object is unreachable. Fix:
free it immediately on failure. This is **adding a put/free (leak
fix)**, not removing one.

Step 2.4: ASSESS THE FIX QUALITY
Record:
- **Obviously correct:** allocation is `kzalloc_obj(*drv)` (historically
  `kzalloc(sizeof(*drv), GFP_KERNEL)`); matching `kfree(driver)` on the
  only path that neither lists it nor returns it.
- **Minimal:** one statement; no unrelated edits.
- **Regression risk: very low.** Probe callbacks (`cx8802_dvb_probe`,
  `cx8802_blackbird_probe`) return errors without stashing `drv` on a
  list. `kfree` under `core->lock` is safe. No API/locking/refcount
  changes.
- **No red flags.**

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

Step 3.1: BLAME THE CHANGED LINES
Record:
- Loop, alloc, memcpy, probe, else-`pr_err` introduced by
  **`6c5be74c86f102`** (“V4L/DVB (4676): Dynamic cx88 mpeg port
  management…”, Steven Toth, **2006-12-10**).
- `pr_err` conversion: `65bc2fe86e6670` (2016).
- Alloc API later became `kzalloc_obj` via **`69050f8d6d075`** (Kees
  Cook, 2026) then **`bf4afc53b77ae`**.
- The **missing free is original**, not a recent regression. Present
  since ~v2.6.20-era, so it exists in every current stable series.

Step 3.2: FOLLOW THE FIXES: TAG
Record: **No Fixes: tag.** Introducer is `6c5be74c86f102`, confirmed by
blame of the alloc/`probe`/else block. `git merge-base --is-ancestor
e228b8b1a5b47 HEAD` → **IS_ANCESTOR** (commit is in this checkout). No
intermediate “same leak” fixes on this file besides this one.

Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Recent `cx88-mpeg.c` commits are PCI_DEVICE macros, kmalloc_obj
conversion, IRQ status clear, dma_ API switch — not prerequisites of
this `kfree`. Older related leak: **`96df988bb9359`** “[media] cx88: Fix
possible leak in `cx8802_probe()`” (different function: PCI probe of the
mpeg manager, not this subdriver register path). **Standalone; not part
of a series.**

Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Chen Changcheng has **only this commit** under
`drivers/media/pci/cx88/`. Applied by **Hans Verkuil**, linux-media
maintainer. Subsystem listed as **“Odd fixes”** in MAINTAINERS (`CX88
VIDEO4LINUX DRIVER`, Mauro Chehab).

Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: **None.** The hunk only needs the existing `else {
pr_err("cx8802 probe failed..."); }` block. Allocation style (`kzalloc`
vs `kzalloc_obj`) is **outside** the hunk, so the one-line add applies
on older trees. **Can apply standalone.**

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- **`b4 dig -c e228b8b1a5b47…`:** https://patch.msgid.link/2026072402521
  8.32318-1-chenchangcheng@kylinos.cn
- **`b4 dig -a`:** **v1 only** (2026-07-24). Applied 2026-07-28. No
  v2/v3.
- **`b4 dig -m`:** thread is **the patch itself only** — no replies,
  NAKs, or reviewer `Cc: stable` in the saved mbox.
- Lore HTML via WebFetch: **403 Forbidden** (could not read the web UI).
  Content recovered from the mbox; it matches the committed message and
  diff.

Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To **mchehab@kernel.org**, **kees@kernel.org**; Cc
**linux-media**, **linux-kernel**. Appropriate lists. No on-list
Reviewed-by; **Hans Verkuil committed it** (implicit maintainer
acceptance). Kees was CC’d (likely due to recent allocator work); no
recorded reply.

Step 4.3: SEARCH FOR THE BUG REPORT
Record: **No Reported-by / Link / syzbot / bugzilla.** Bug is from
**code inspection**, not a user crash report. Still a real leak (see
Phase 5/8).

Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone `[PATCH]`, not `n/m`. No sibling cx88 leak patches in
file history besides the old `cx8802_probe()` leak.

Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: WebFetch of
`https://lore.kernel.org/stable/?q=cx8802_register_driver` returned
**403**. **UNVERIFIED** whether stable@ already discussed this. Not used
to drive the verdict.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: **`cx8802_register_driver()`** only. (semcode MCP not available;
used hunk headers + grep.)

Step 5.2: TRACE CALLERS
Record:
- `cx88-dvb.c` `dvb_init()` →
  `cx8802_register_driver(&cx8802_dvb_driver)` (`module_init`)
- `cx88-blackbird.c` `blackbird_init()` →
  `cx8802_register_driver(&cx8802_blackbird_driver)` (`module_init`)
- Autoload from PCI probe: `cx8802_probe()` → `request_modules()` →
  `request_module("cx88-dvb")` / `"cx88-blackbird"` when `board.mpeg`
  has the corresponding bit.

Context: **module init / device probe**, not IRQ/hot path.

Step 5.3: TRACE CALLEES
Record: `cx8802_check_driver()`, `kzalloc_obj`, `memcpy`,
`mutex_lock(&drv->core->lock)`, **`drv->probe(driver)`**,
`list_add_tail` on success, `pr_err` + (now) `kfree` on failure.

Probe implementations:
- `cx8802_dvb_probe`: **returns `-ENODEV` immediately** if
  `!(core->board.mpeg & CX88_MPEG_DVB)`; also fails on
  `vp3054_i2c_probe`, `cx8802_alloc_frontends`, `vb2_queue_init`,
  `dvb_register`.
- `cx8802_blackbird_probe`: same **`-ENODEV` if not BLACKBIRD**; also
  `cx2341x_handler_init` / `vb2_queue_init`.

Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace/module load of `cx88-dvb` or `cx88-blackbird` (or udev
via `cx8802_probe`) → register walks **`cx8802_devlist` (every MPEG
function-2 device)** → alloc + probe. **Reachable from normal driver
load, not an obscure config.** Type-mismatch `-ENODEV` is a **designed,
common** failure: register does not filter by `type_id` first.

Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Unregister already `kfree(d)` after successful `remove`. Success
path is balanced; **only the failure path was missing the free.** No
duplicate of this bug in sibling functions beyond the historical
`cx8802_probe()` leak that was already fixed.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes, in this lineage.** Pre-fix source at `e228b8b1a5b47^`
still has the else branch **without** `kfree`. HEAD already contains the
fix (`e228b8b1a5b47` is an ancestor). Bug introduced **2006**
(`6c5be74c86f102`), long before 7.3. The `pr_err` else block and leak
exist on all current LTS kernels.

Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **Clean apply / trivial.** Context line `pr_err("cx8802 probe
failed, err = %d\n", err);` has been stable since 2016. Adjacent
`kzalloc_obj` vs older `kzalloc(sizeof(*drv), GFP_KERNEL)` is **not in
this hunk**.

Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: This exact `kfree` **is** already in HEAD. That is the candidate
commit, not a different prior fix. No competing rewrite of the error
path. (`96df988bb9359` is a different leak.)

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **`drivers/media/pci/cx88`** — Conexant CX2388x analog/DVB TV
capture. **PERIPHERAL** (specific PCI TV cards). Maintainer status:
**Odd fixes**. Still in-tree and used on remaining hardware.

Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Low churn; mostly treewide/API conversions plus occasional
bugfixes. **Mature.** A 20-year leak in a quiet driver is still a leak
for those cards.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific / config-specific:** `CONFIG_VIDEO_CX88` plus
`VIDEO_CX88_DVB` and/or `VIDEO_CX88_BLACKBIRD`. Not universal. Distros
that ship these modules (common in desktop kernels) can hit it on CX88
MPEG hardware.

Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- **Primary realistic trigger:** subdriver init probes **every**
  `cx8802_dev`. A DVB-only card + `cx88-blackbird` load (or mixed cards
  in one machine) takes the `-ENODEV` path **every boot / every module
  load**.
- **Also:** genuine probe errors (`vb2_queue_init`, frontend alloc,
  etc.).
- **Module reload** leaks again (unregister never sees the object).
- Unprivileged users cannot typically trigger it unless they can load
  modules; **not a UAF/security primitive**, a leak.

Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: **Memory leak of one `struct cx8802_driver` (~pointers + enums,
small) per failed probe.** Not a panic/UAF. **Severity: MEDIUM**
(init/error path, small object, can repeat on reload / multi-device
mismatch). Still a real, permanent leak of kernel memory for affected
users.

Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** stops a real leak on a path that is not purely
  theoretical (type-mismatch `-ENODEV` is intentional). Helps CX88 users
  and anyone who reloads these modules.
- **Risk:** **very low** (1 line, `kfree` of an unlisted object,
  maintainer-applied).
- **Ratio:** strongly favors backport.

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

Step 9.1: COMPILE THE EVIDENCE

**FOR backporting:**
- Real leak: alloc without free when probe fails; unregister cannot
  recover it (verified in both functions).
- Failure path includes **common `-ENODEV` type mismatch**, not only
  rare ENOMEM.
- One-line, obviously correct `kfree`; maintainer (Hans Verkuil) applied
  it.
- Bug present since 2006 — all stable trees that have cx88 have the bug.
- Applies cleanly; no new API, no locking change, no series dependency.
- Matches the stable “error-path leak / missing kfree” pattern.

**AGAINST:**
- Peripheral old TV capture driver; small object; not a
  crash/security/data-corruption bug.
- No user/syzbot report; no Fixes/Cc: stable (expected here).
- Not a hot-path unbounded leak unless modules are reloaded or many
  devices mismatch.

**UNRESOLVED:**
- Lore web UI and stable@ search returned HTTP 403; on-list review
  comments beyond the patch email could not be read (mbox had no
  replies).

Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — code inspection; applied by
   media maintainer (no extra Tested-by).
2. Fixes a real bug that affects users? **PASS** — leaked `kzalloc` on
   failed/mismatched probe.
3. Important issue? **PASS** (medium: resource leak on driver load; not
   panic-level, but a genuine leak stable regularly takes).
4. Small and contained? **PASS** — +1 line, one function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — same else-branch context; no
   missing helpers.

Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **Not an exception category** (not a device
ID/quirk/DT/build/doc). It is a normal **error-path leak fix**.

Step 9.4: MAKE YOUR DECISION
The leak is real, old, and fixed with a single obviously-correct
`kfree`. Risk is negligible. It belongs in this tree’s stable backports:
CX88 still probes every MPEG device, and failed probes (including
designed `-ENODEV`) drop the allocation on the floor.

**What it solves for stable users:** loading `cx88-dvb`/`cx88-blackbird`
(or mixed CX88 cards) no longer leaks a `cx8802_driver` per failed
probe, including across module reload.

**Risk vs benefit:** one-line free on an object that is not on any list
— benefit clearly wins.

**Concerns:** none for apply/prereqs. Severity is “leak” not “oops”;
still within stable practice for missing `kfree` on error paths.

Verification:
- [Phase 1] Subject/tags: leak fix; SOBs Chen Changcheng + Hans Verkuil;
  no Fixes/Reported-by/Cc:stable
- [Phase 1] Body matches the mechanism verified in source
- [Phase 2] `git show e228b8b1a5b47`: +1 line `kfree(driver)` in else of
  `cx8802_register_driver()`
- [Phase 2] `git show e228b8b1a5b47^`: else branch logs error and does
  not free
- [Phase 2] `cx8802_unregister_driver()` only `kfree`s `dev->drvlist`
  entries after successful `remove`
- [Phase 3] `git describe HEAD` / `make kernelversion`:
  v7.3-rc4-27-gf0100363d8c37, 7.3.0-rc4
- [Phase 3] `git merge-base --is-ancestor e228b8b1a5b47 HEAD`:
  IS_ANCESTOR
- [Phase 3] `git blame`: leaky alloc/probe/else from `6c5be74c86f102`
  (2006-12-10)
- [Phase 3] Author log: only this cx88 commit; file not a series
- [Phase 4] `b4 dig -c/-a/-w/-m`: lore msgid 20260724025218.32318-1; v1
  only; To mchehab+kees; mbox has no replies
- [Phase 4] WebFetch lore.kernel.org: 403 — UNVERIFIED web
  thread/stable@ discussion
- [Phase 5] grep callers: only `cx88-dvb.c` and `cx88-blackbird.c`
  module_init
- [Phase 5] Read `cx8802_dvb_probe` / `cx8802_blackbird_probe`:
  `-ENODEV` if MPEG type bit unset
- [Phase 5] `cx8802_probe` → `request_modules()` autoloads matching
  subdrivers
- [Phase 6] Pre-fix function present; hunk independent of `kzalloc_obj`
  (`69050f8d6d075`)
- [Phase 7] MAINTAINERS: CX88 VIDEO4LINUX DRIVER, Odd fixes, Mauro
  Chehab
- [Phase 8] Failure mode: kernel memory leak, MEDIUM, driver-specific
- UNVERIFIED: on-list reviewer comments (mbox empty of replies; lore
  HTTP 403)
- UNVERIFIED: whether stable@ already queued this elsewhere (not used
  for the verdict)

**YES**

 drivers/media/pci/cx88/cx88-mpeg.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 2c1d5137ac470..bc08b35e247e0 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -640,6 +640,7 @@ int cx8802_register_driver(struct cx8802_driver *drv)
 			list_add_tail(&driver->drvlist, &dev->drvlist);
 		} else {
 			pr_err("cx8802 probe failed, err = %d\n", err);
+			kfree(driver);
 		}
 		mutex_unlock(&drv->core->lock);
 	}
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: cec: tegra: add missing MODULE_DEVICE_TABLE()
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (7 preceding siblings ...)
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: cx88: fix memory leak in cx8802_register_driver() error path Sasha Levin
@ 2026-10-19 13:49 ` Sasha Levin
  2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] media: cec: stm32: return an error when log-address wait times out Sasha Levin
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:49 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Hans Verkuil, Sasha Levin, hverkuil, mchehab,
	thierry.reding, jonathanh, linux-tegra, linux-media, linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit 8dcf23edaf4bdf22259f6a47cfddc8bb1467425c ]

The driver has an OF match table wired to .of_match_table, but does
not export the table with MODULE_DEVICE_TABLE().

Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias
information is generated for OF based module autoloading.

This is a source-level fix.  It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the platform driver, and the missing module alias publication.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This is a one-line OF module-alias fix on a driver that has been in the
tree since v4.15. Local checkout is **v7.3-rc4** (`7.3.0-rc4`,
`f0100363d8c37`), not a numbered stable branch. The candidate is
`8dcf23edaf4bd`.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

Step 1.1: PARSE THE SUBJECT LINE
Record: `[media/cec/tegra] [add] missing MODULE_DEVICE_TABLE() so OF
module aliases are generated`

Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn> (author)
- Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org> (CEC/Tegra CEC
  maintainer; applied the patch)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
  or Cc: stable
- Absence of Fixes:/Cc: stable is expected for this review pipeline and
  is not a negative signal

Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: OF match table is wired to `.of_match_table` but not exported via
  `MODULE_DEVICE_TABLE(of, ...)`.
- Symptom: when `CONFIG_CEC_TEGRA=m`, depmod/modinfo get no `of:`
  aliases, so udev will not autoload `tegra_cec.ko` for
  `nvidia,tegra114-cec` / `tegra124-cec` / `tegra210-cec`.
- Version info: none in the message. Git shows the match table dates to
  the original driver (v4.15-rc1).
- Root cause: missing module-alias publication, not a probe/runtime
  logic error.
- Author states this is a source-level finding, not a live hardware
  repro.

Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit autoload/hardware-
enablement fix. The “source-level” wording is candor, not a claim that
nothing is wrong.

===============================================================
PHASE 2: DIFF ANALYSIS
===============================================================

Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/media/cec/platform/tegra/tegra_cec.c` (+1 / -0)
- Functions: none. Adds `MODULE_DEVICE_TABLE(of, tegra_cec_of_match)`
  after the existing `tegra_cec_of_match[]` table.
- Scope: single-file, one-line surgical change.

Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: table exists and is assigned to
  `platform_driver.driver.of_match_table`, so a **already loaded** or
  **built-in** driver still matches DT nodes.
- After: `scripts/mod/file2alias.c` also emits `of:` modaliases into the
  `.ko`, so userspace can autoload the module from sysfs modalias.
- Path affected: module build / autoload, not probe/remove/IRQ/CEC
  transfer.

Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: hardware enablement / missing device-table export (same
  family as adding IDs).
- Mechanism: `MODULE_DEVICE_TABLE()` creates the
  `__mod_device_table__kmod_*` alias that `file2alias.c` consumes.
  Without it, the kernel can bind the driver once loaded, but the module
  will not be loaded automatically.

Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: sibling CEC platform drivers (`stm32-cec`,
  `meson/ao-cec`, `s5p_cec`, `stih-cec`, `cec-gpio`) already use the
  same pattern.
- Minimal: one line, no API/struct/locking change.
- Regression risk: very low. Builtin builds are unaffected at runtime;
  modular builds only gain aliases.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

Step 3.1: BLAME THE CHANGED LINES
Record:
- Match table introduced in `9d2d60687c9a06` ("media: tegra-cec: add
  Tegra HDMI CEC driver", Hans Verkuil, 2017-07-15; first contained in
  **v4.15-rc1**).
- Original file had the OF table and `.of_match_table =
  of_match_ptr(...)` and **no** `MODULE_DEVICE_TABLE`.
- Bug has been present for the entire life of the driver.

Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Not applicable. Introduction commit is
`9d2d60687c9a06`, present in this tree (`git merge-base --is-ancestor`
of the candidate vs HEAD succeeds).

Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record (recent on this file):
- `7bc1f3c8bd673` (2023): drop `of_match_ptr` so the table is always
  used (build fix for !OF).
- `8dcf23edaf4bd` (this commit)
- Later functional CEC fixes (`be627f257ce28`, `bce7236c16c2c`) do not
  depend on this line.
- Standalone; not patch X/Y.

Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record:
- Pengpeng Hou submitted a large set of “add missing
  MODULE_DEVICE_TABLE()” patches (rtc, vdpa, watchdog, fbdev, soc, can,
  clk, power, this CEC driver). Same recipe, LLM-style commit text.
- Hans Verkuil is listed maintainer of `ARM/TEGRA HDMI CEC` and applied
  this patch. That is a strong quality signal for the **change**, even
  if the author is doing a sweep.

Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None. The macro has existed for decades
(`include/linux/module.h`). The table and `.of_match_table` assignment
are original. Applies standalone.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 8dcf23edaf4bd` →
  https://patch.msgid.link/20260704122631.99057-1-pengpeng@iscas.ac.cn
- Single revision (v1 only). `b4 dig -a` also matched an unrelated 2024
  Liao Chen v4l2-subdev series by patch-id search noise; this commit is
  a standalone v1.
- Direct lore HTTP fetch returned 403; full thread was saved via `b4 dig
  -m` to `/tmp/tegra_cec_moddev.mbox`.
- NVIDIA Tegra developer Mikko Perttunen replied 2026-07-15: objected to
  the “source-level fix / no dynamic hardware reproduction” paragraph as
  AI boilerplate, and said **“Otherwise looks fine to me.”** No NAK. No
  request for v2. Hans applied v1 as-is (that paragraph remained).
- No reviewer asked for Cc: stable.

Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc included Hans Verkuil, Mauro Chehab, Thierry
Reding, Jonathan Hunter, linux-tegra, linux-media, linux-kernel. Right
lists and maintainers. Informal ack from Mikko Perttunen (NVIDIA);
applied by Hans Verkuil.

Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by, bugzilla, or syzbot. Evidence is the missing
export next to a live OF table. No user report of failed autoload was
found.

Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Same-day author sweep of missing `MODULE_DEVICE_TABLE` across
subsystems. Not a dependent series; each driver patch is self-contained.
Sibling CEC OF drivers already had the macro.

Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No lore.kernel.org/stable thread for this exact Tegra CEC patch
(search did not return a relevant hit). Same-class patches **have** gone
into stable before, including:
- `PCI: tegra: Add missing MODULE_DEVICE_TABLE` on 4.19-stable
- `can: ctucanfd: add missing MODULE_DEVICE_TABLE()` from the same
  author, committed to linux-stable by Greg Kroah-Hartman
  (`d937bdb244a75` upstream)

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: No functions modified. Macro addition adjacent to
`tegra_cec_of_match[]`. Related structures: `tegra_cec_driver`
(`module_platform_driver`).

Step 5.2: TRACE CALLERS
Record: `tegra_cec_probe` is the platform probe (DT device
instantiation). `MODULE_DEVICE_TABLE` is not called at runtime;
`scripts/mod/file2alias.c` `do_table()` consumes the alias at module
build. Impact surface is autoload of `tegra_cec.ko` only.

Step 5.3: TRACE CALLEES
Record: N/A for the added line. The driver already includes
`<linux/module.h>` and `<linux/of.h>`.

Step 5.4: FOLLOW THE CALL CHAIN
Record: Reachable for users with `CONFIG_CEC_TEGRA=m` on Tegra
114/124/210 HDMI CEC DT nodes (e.g. Jetson TK1 / older Tegra boards).
Unprivileged userspace cannot trigger a crash; the user-visible failure
is “CEC adapter never appears until `modprobe tegra_cec`”. Builtin
(`=y`) is already fine.

Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Other CEC platform drivers already export OF tables. This file
was the outlier. Same missing-macro pattern exists across many drivers
and is treated as a real autoload bug.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. File `drivers/media/cec/platform/tegra/tegra_cec.c` exists.
Pre-commit parent still has the OF table and `.of_match_table` without
the macro. Candidate **is already an ancestor of HEAD** (`git merge-base
--is-ancestor 8dcf23edaf4bd HEAD`). Bug introduced v4.15-rc1; present in
every long-lived stable series that has this driver.

Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Expected apply: **clean**. Context around the table (compatibles
tegra114/124/210) is original. Later commits only add the macro and then
unrelated CEC protocol fixes. Line numbers differ slightly on current
HEAD because of later edits, but the hunk is trivial.

Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: This is the fix; it is already in this 7.3-rc4 tree. No earlier
substitute autoload fix on this file. `7bc1f3c8bd673` only dropped
`of_match_ptr`; it did not add aliases.

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: `drivers/media/cec/platform/tegra/` — HDMI CEC on NVIDIA Tegra.
Criticality: **PERIPHERAL** (SoC-specific media driver), but real
product hardware (Jetson TK1 and Tegra X1 designs were the original test
targets).

Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Low churn. Driver added 2017; occasional correctness fixes.
Mature. The missing macro is long-standing, not a regression from recent
refactoring.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific / config-specific: `CONFIG_CEC_TEGRA=m` on DT
platforms with `nvidia,tegra114-cec`, `nvidia,tegra124-cec`, or
`nvidia,tegra210-cec`. Not universal.

Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Every boot/hotplug of that DT node when the driver is a module
and nothing else loads it. Common on distros that package CEC as a
module; irrelevant if the vendor kernel builds it in. Not a race. Not
triggerable as a crash by unprivileged users.

Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: HDMI CEC device never binds until manual `modprobe`. No oops,
leak, or corruption. Severity: **MEDIUM** for those boards
(feature/hardware dead), **LOW** globally. This is the same user-visible
class as “device ID missing so the module never loads.”

Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: restores intended autoload for modular Tegra CEC; matches
  every other CEC OF driver.
- Risk: one compile-time alias line; no runtime path change.
- Ratio: high benefit for affected users, negligible risk.

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

Step 9.1: COMPILE THE EVIDENCE

FOR backporting:
- Real bug: OF match table used by the platform driver is not published
  to module aliases.
- `CEC_TEGRA` is **tristate**; modular builds are first-class.
- One line, obviously correct, no new API.
- Same pattern as the documented **device-ID / hardware enablement**
  exception.
- Maintainer-applied (Hans Verkuil); NVIDIA engineer said the change
  looks fine.
- Sibling CEC drivers already have `MODULE_DEVICE_TABLE(of, ...)`.
- Bug present since v4.15; no prerequisites.
- Same class of patches has historically been accepted into stable
  (including this author’s `can: ctucanfd` MODULE_DEVICE_TABLE fix).

AGAINST:
- Not a crash, UAF, deadlock, or security hole.
- No end-user report; author did not claim hardware reproduction.
- Peripheral SoC driver; small user population.
- Author is doing a mass static-analysis sweep; commit text was called
  out as AI boilerplate.
- Builtin kernels are unaffected.

UNRESOLVED:
- Could not HTTP-fetch lore (403); discussion recovered from `b4 dig -m`
  instead.
- Could not find a stable-list thread for **this** SHA.

Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — one well-known macro;
   applied by the subsystem maintainer; NVIDIA developer agreed. Build-
   tested at least (author/reviewer).
2. Fixes a real bug that affects users? **PASS** — modular autoload for
   real Tegra CEC DT compatibles.
3. Important issue? **PASS** under the hardware-enablement exception
   (device does not come up). Not CRITICAL crash/corruption.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS** — publishes an existing table.
6. Can apply to the local tree? **PASS** — file and table exist; hunk is
   trivial. (This 7.3-rc4 tree already contains the commit.)

Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **Device ID / module alias publication for an existing driver.**
Closest listed exception is new device IDs; this is the matching half
(exporting the IDs the driver already matches). Also analogous to
quirks/DT enablement: it makes already-supported hardware actually
attach when built as a module.

Step 9.4: MAKE YOUR DECISION
The local tree is mainline **7.3.0-rc4**. The driver and buggy omission
exist here and in any stable series that still has `tegra_cec`. The
patch is a one-line, maintainer-acked autoload fix with no runtime risk.
That is stable material.

What problem it solves for stable users: with `CONFIG_CEC_TEGRA=m`, udev
never loads the module from the DT compatible, so HDMI CEC stays dead
until a manual modprobe. Distros that ship this as a module on
Jetson/Tegra boards hit that.

Risk vs benefit: benefit is hardware actually probing; risk is
essentially zero.

Verification:
- [Phase 1] Parsed tags: author + Hans Verkuil SOB only; no
  Fixes/Reported-by/Cc: stable
- [Phase 1] Body describes missing OF alias publication, not a crash
- [Phase 2] Diff: +1 line `MODULE_DEVICE_TABLE(of, tegra_cec_of_match)`
  in `tegra_cec.c`
- [Phase 2] Confirmed `.of_match_table = tegra_cec_of_match` already
  present
- [Phase 3] `git blame`: table from `9d2d60687c9a06` (v4.15-rc1); macro
  from `8dcf23edaf4bd`
- [Phase 3] Original driver dump: no MODULE_DEVICE_TABLE
- [Phase 3] Author sweep of similar one-liners; Hans is MAINTAINERS
  owner of ARM/TEGRA HDMI CEC
- [Phase 4] `b4 dig -c 8dcf23edaf4bd`:
  https://patch.msgid.link/20260704122631.99057-1-pengpeng@iscas.ac.cn
- [Phase 4] `b4 dig -a`: single v1; no later revision
- [Phase 4] `b4 dig -w`: linux-media, linux-tegra, Hans, Mauro, Thierry
  Reding, Jonathan Hunter
- [Phase 4] mbox: Mikko Perttunen “Otherwise looks fine to me”;
  complaint was about AI commit-message padding only
- [Phase 4] lore WebFetch 403; content taken from mbox
- [Phase 4] No stable@ thread for this SHA; same-class
  MODULE_DEVICE_TABLE patches have landed in stable
- [Phase 5] Kconfig `CEC_TEGRA` is tristate; Makefile
  `obj-$(CONFIG_CEC_TEGRA) += tegra_cec.o`
- [Phase 5] `MODULE_DEVICE_TABLE` in `include/linux/module.h` creates
  file2alias symbol; `scripts/mod/file2alias.c` `do_table()` consumes it
- [Phase 5] Other CEC OF drivers already have the macro
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; `make
  kernelversion`: 7.3.0-rc4
- [Phase 6] `git merge-base --is-ancestor 8dcf23edaf4bd HEAD`: yes
  (already in this tree)
- [Phase 6] Backport difficulty: clean one-liner
- [Phase 7] Peripheral media driver, maintainer-applied
- [Phase 8] Failure mode: module not autoloaded → CEC unused; severity
  MEDIUM for Tegra modular users, not a panic
- UNVERIFIED: live udev autoload on real Tegra hardware (author did not
  claim it)

**YES**

 drivers/media/cec/platform/tegra/tegra_cec.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/cec/platform/tegra/tegra_cec.c b/drivers/media/cec/platform/tegra/tegra_cec.c
index 3ed50097262f6..fe66336e734f8 100644
--- a/drivers/media/cec/platform/tegra/tegra_cec.c
+++ b/drivers/media/cec/platform/tegra/tegra_cec.c
@@ -458,6 +458,7 @@ static const struct of_device_id tegra_cec_of_match[] = {
 	{ .compatible = "nvidia,tegra210-cec", },
 	{},
 };
+MODULE_DEVICE_TABLE(of, tegra_cec_of_match);
 
 static struct platform_driver tegra_cec_driver = {
 	.driver = {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: cec: stm32: return an error when log-address wait times out
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (8 preceding siblings ...)
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: cec: tegra: add missing MODULE_DEVICE_TABLE() Sasha Levin
@ 2026-10-19 13:50 ` Sasha Levin
  2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] media: v4l2-tpg: reduce stack usage for kasan builds Sasha Levin
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:50 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Hans Verkuil, Sasha Levin, hverkuil, mchehab,
	mcoquelin.stm32, alexandre.torgue, linux-media, linux-stm32,
	linux-arm-kernel, linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit 3bc2e4a26465386332ee1a40219d8dafba335b0b ]

stm32_cec_adap_log_addr() waits for TXSOM to clear before disabling CEC
and updating the logical address registers. The wait result is ignored,
so a timeout can still be reported as a successful logical address
update.

Return the polling error before touching the address registers. Compute
the address mask only for valid logical addresses so the invalid-address
path does not evaluate a shift based on CEC_LOG_ADDR_INVALID.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This tree is **6.18.53** (`v6.18.53-5049-g0f0bdc2b0dffb`, branch
`autosel`). The verdict is only for this checkout: the STM32 CEC
timeout/shift bugs are present at `v6.18.53`, and the patch applies
cleanly.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: PARSE THE SUBJECT LINE**

Record: `[media/cec/stm32] [return] return an error when log-address
wait times out`

Subsystem prefix `media: cec: stm32`. Verb `return` is error-propagation
language (equivalent to “handle/fix”). Intent: stop treating a timed-out
TXSOM wait as a successful logical-address update.

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**

Record:
- `Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>` (author)
- `Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (CEC
  framework maintainer; also the committer of upstream `3bc2e4a26465`)
- Ignored pipeline tags: `[Upstream commit
  3bc2e4a26465386332ee1a40219d8dafba335b0b]`, `Signed-off-by: Sasha
  Levin`
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
  by:`, `Link:`, or `Cc: stable` (absence expected for this review)

Notable: maintainer SOB, no syzbot/user report.

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**

Record:
- **Bug:** `stm32_cec_adap_log_addr()` polls for TXSOM to clear, then
  ignores the poll result and still disables CEC, writes OAR, re-enables
  CEC, and returns 0.
- **Symptom:** userspace/CEC core can be told a logical address was
  programmed when the wait timed out and the registers may not have been
  updated safely.
- **Second issue:** address mask `(1 << logical_addr) << 16` is computed
  before the `CEC_LOG_ADDR_INVALID` check, so the invalid-address path
  still evaluates a shift of `0xff`.
- **Root cause:** missing return-value check; mask computed too early.
- **Version info:** none in the message. Poll wait was added in 2019
  (`1a726df6078c2f`, v5.2-rc1).

**Step 1.4: DETECT HIDDEN BUG FIXES**

Record: Not disguised. It is an explicit error-path and UB fix (“return
the polling error”, “does not evaluate a shift”).

---

## PHASE 2: DIFF ANALYSIS

**Step 2.1: INVENTORY THE CHANGES**

Record:
- File: `drivers/media/cec/platform/stm32/stm32-cec.c` — **+11 / −5**
  (16 lines in one function)
- Function: `stm32_cec_adap_log_addr()` only
- Scope: single-file surgical fix

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**

Record (verified against `v6.18.53` and the candidate diff):

**Before** (at `v6.18.53`):
```c
u32 oar = (1 << logical_addr) << 16;
regmap_read_poll_timeout(...);  /* return value discarded */
regmap_update_bits(..., CECEN, 0);
if (logical_addr == CEC_LOG_ADDR_INVALID)
    clear OAR;
else
    set oar bits;
re-enable CECEN;
return 0;
```

**After:**
- Capture poll result; if nonzero, return it immediately (no CFGR
  write).
- Compute `BIT(logical_addr) << 16` only in the valid-address branch.

Affected path: CEC logical-address claim and unconfigure
(`adap_log_addr`), not probe/IRQ hot path.

**Step 2.3: IDENTIFY THE BUG MECHANISM**

Record:
- **(a) Error path:** ignored `regmap_read_poll_timeout()` result.
  Typical returns: `-ETIMEDOUT` or `-EFAULT`.
- **(g) Logic/correctness:** false success (`return 0`) after a failed
  wait.
- **(f/UBSAN):** `(1 << logical_addr)` with `logical_addr ==
  CEC_LOG_ADDR_INVALID` (`0xff` in `include/uapi/linux/cec.h`) is an
  oversized shift (UB). Result is unused on that branch, but the
  expression is always evaluated first.

Hardware context (from `1a726df6078c2f`): CFGR/OAR must be written only
with CECEN=0, after TXSOM clears. On timeout the old code still toggled
CECEN and wrote CFGR.

**Step 2.4: ASSESS THE FIX QUALITY**

Record:
- Obviously correct: check the value the wait already returned; don’t
  shift `0xff`.
- Minimal; `1 <<` → `BIT()` is local to the valid-LA branch (`BIT` comes
  from `linux/kernel.h` → `bitops.h` → `vdso/bits.h`, already included).
- Regression risk: low. On timeout, `cec_config_log_addr()` already does
  `if (err) return err`. On unconfigure, `cec_adap_unconfigure()` does
  `WARN_ON(call_op(..., CEC_LOG_ADDR_INVALID))`, so a stuck TXSOM can
  now warn instead of silently returning 0. That is the existing core
  contract for a failed clear, not a new API. Timeout budget is
  `CEC_XFER_TIMEOUT_MS` = 2100 ms, so this is a stuck-TX path, not a
  normal claim.

---

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: BLAME THE CHANGED LINES**

Record:
- Function and `return 0` / CECEN/OAR writes: `d69ae57453c80a` (“[media]
  cec: add STM32 cec driver”, 2017) — first in **v4.13-rc1**.
- Poll without checking the result: `1a726df6078c2f` (“media: platform:
  stm32: wait end of transmission”, 2019) — first in **v5.2-rc1**.
- Buggy pattern has been in this line of kernels for years, including
  6.18.y.

**Step 3.2: FOLLOW THE FIXES: TAG**

Record: No `Fixes:` tag. Buggy poll commit `1a726df6078c2f` **is** an
ancestor of HEAD and of `v6.18.53`. Intermediate related work on this
file: `0c260d3f97e52` (RX overflow OOB) is a separate bug, not a
prerequisite.

**Step 3.3: CHECK FILE HISTORY**

Record: Recent file commits are cleanup/moves plus the RX OOB fix. This
is standalone, not “patch X/Y”. No later follow-up on this function
after the candidate.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**

Record: Pengpeng Hou is not the CEC maintainer. In this tree, the other
hit under `drivers/media/cec/` is unrelated (`tegra`
MODULE_DEVICE_TABLE). Weight comes from **Hans Verkuil** (CEC FRAMEWORK
maintainer in `MAINTAINERS`) signing off and committing upstream.

**Step 3.5: DEPENDENT/PREREQUISITE COMMITS**

Record: None. Uses existing `regmap_read_poll_timeout`, `BIT()`,
`CEC_LOG_ADDR_INVALID`. Can apply standalone. Confirmed `1a726df6078c2f`
and `d69ae57453c80a` are in `v6.18.53`.

---

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**

Record:
- `b4 dig -c 3bc2e4a26465` →
  https://patch.msgid.link/20260624144015.63929-1-pengpeng@iscas.ac.cn
- `b4 dig -a`: **v1 only**, 2026-06-24, no later revisions
- lore.kernel.org fetches returned 403; discussion recovered from
  LKML/Openwall/Patchew mirrors. Patch body matches the commit. No
  replies on those archives.
- No reviewer NAK found. Hans Verkuil applied it (CommitDate Mon Jun 29
  2026).

**Step 4.2: CHECK WHO REVIEWED THE PATCH**

Record (`b4 dig -w`): To/Cc included Hans Verkuil, Mauro Chehab, Maxime
Coquelin, Alexandre Torgue, `linux-media`, `linux-stm32`, `linux-arm-
kernel`, `lkml`. Right maintainers were on the submission. No extra
Reviewed-by in the committed message.

**Step 4.3: SEARCH FOR THE BUG REPORT**

Record: No `Reported-by` / bugzilla / syzbot. Static/code-correctness
fix, not a user crash report.

**Step 4.4: RELATED PATCHES AND SERIES**

Record: Standalone `[PATCH]`, not a series. Sibling STM32 change
`0c260d3f97e52` is a different RX OOB bug and already has `Cc: stable`.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**

Record: No usable stable-list hit for this subject (lore/stable blocked
by anti-bot). UNVERIFIED that nobody previously rejected it for stable.
No evidence of a known NAK.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: KEY FUNCTIONS**

Record: `stm32_cec_adap_log_addr` only. Registered as `.adap_log_addr`
in `stm32_cec_adap_ops`.

**Step 5.2: TRACE CALLERS**

Record (`call_op` in `drivers/media/cec/core/cec-priv.h`):
- `cec_config_log_addr()` in `cec-adap.c` — claim path; error is
  returned to the config thread.
- `cec_adap_unconfigure()` — `WARN_ON(call_op(...,
  CEC_LOG_ADDR_INVALID))`; then core still marks the adapter
  unconfigured.

Called with `adap->lock` held from the CEC kthread / ioctl configuration
path, not IRQ context.

**Step 5.3: TRACE CALLEES**

Record: `regmap_read_poll_timeout`, `regmap_update_bits`. Sleeps up to
~2.1 s. No alloc/new locks.

**Step 5.4: FOLLOW THE CALL CHAIN**

Record: Userspace CEC ioctls (`CEC_ADAP_S_LOG_ADDRS` / adapter enable-
disable) → CEC core → `adap_log_addr`. Reachable on STM32 HDMI CEC
(`CONFIG_CEC_STM32`, `st,stm32-cec`) without extra privilege beyond
access to the CEC device node. Not a generic syscall bug on x86.

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**

Record: Other platform CEC drivers (tegra, meson) check
`CEC_LOG_ADDR_INVALID` before building a shift mask. Tegra still uses `1
<< logical_addr` only in the else branch. This STM32 driver was the one
evaluating the shift first.

---

## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**

Record: **Yes**, at `v6.18.53` in `stm32_cec_adap_log_addr()`.
Introduced 2017 (shift) / 2019 (ignored poll). Upstream fix
`3bc2e4a26465` is **not** an ancestor of HEAD (expected: it is a later
mainline commit being evaluated). The autosel cherry-pick
`a1157fd7d1e0f` is already on this branch; that is ignored as selection
evidence.

**Step 6.2: BACKPORT COMPLICATIONS**

Record: **Clean apply.** Surrounding function at `v6.18.53` matches the
pre-image exactly. No refactor of this callback on 6.18.y.

**Step 6.3: RELATED FIXES ALREADY HERE**

Record: No earlier timeout-return or shift-guard on this function. RX
OOB fix is independent.

---

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

**Step 7.1: SUBSYSTEM AND CRITICALITY**

Record: `drivers/media/cec/platform/stm32/` — STM32 HDMI CEC.
**PERIPHERAL** (SoC HDMI-CEC), but a supported in-tree driver (`CEC
FRAMEWORK` is Supported; Kconfig `CEC_STM32` depends on `ARCH_STM32 ||
COMPILE_TEST`).

**Step 7.2: SUBSYSTEM ACTIVITY**

Record: File is mature (2017), low churn aside from tree-wide media
cleanups and the recent RX OOB fix. This is an old bug, not a regression
in brand-new code.

---

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: WHO IS AFFECTED**

Record: Driver-specific / config-specific: STM32 boards with HDMI CEC
(`st,stm32-cec`). Not universal.

**Step 8.2: TRIGGER CONDITIONS**

Record:
- **Timeout bug:** TXSOM stuck for >2.1 s while claiming or clearing a
  LA. Uncommon, but that is exactly the failure the 2019 wait was meant
  to cover. Unprivileged users with CEC device access can hit the claim
  path.
- **Shift UB:** every unconfigure (`CEC_LOG_ADDR_INVALID` = 0xff), a
  normal path when disabling/reconfiguring CEC.

**Step 8.3: FAILURE MODE SEVERITY**

Record:
- False-success LA update + CFGR write while TXSOM still set: CEC
  misconfiguration / possible controller or bus glitch. **MEDIUM**
  (functional/hardware-constraint), not a kernel oops.
- Shift UB on unconfigure: UBSAN-class undefined behavior; result unused
  on that branch, so not a typical oops. **MEDIUM**.

Not panic/UAF/corruption in the usual sense. Still a real correctness
bug on a user-reachable path.

**Step 8.4: RISK-BENEFIT RATIO**

Record:
- **Benefit:** medium for STM32 CEC users — honest errors, no forbidden
  CFGR write after timeout, no `1 << 0xff`.
- **Risk:** very low — ~16 lines, one function, no API/locking/data-
  structure change.
- Ratio: favorable. The new `WARN_ON` on unconfigure-timeout is the main
  behavioral change and only fires if the wait already failed.

---

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: EVIDENCE**

**FOR:**
- Real bugs: ignored poll error → false success and a CFGR write the
  driver itself documented as illegal during TX; UB shift of `0xff` on
  unconfigure.
- Small, obviously correct, maintainer-acked (Hans Verkuil).
- Buggy code exists in this 6.18.y tree; applies cleanly; no
  prerequisites.
- Matches stable error-handling / UBSAN-shift patterns.

**AGAINST:**
- Peripheral STM32 HDMI CEC, not a core path.
- No user/syzbot report; timeout is rare.
- Failure is not a documented oops/CVE/deadlock.
- Unconfigure timeout can now `WARN_ON` (honest, but user-visible in
  dmesg).

**UNRESOLVED:**
- Full lore thread (403); no public review comments beyond maintainer
  application.
- Stable-list history not searchable here.

**Step 9.2: STABLE RULES CHECKLIST**

1. Obviously correct and tested? **PASS** — check existing return;
   maintainer merged it.
2. Fixes a real bug that affects users? **PASS** — false success and
   hardware-forbidden write; UB on unconfigure.
3. Important issue? **PASS** (medium) — not a panic, but incomplete
   timeout handling plus UBSAN-class shift on a normal unconfigure path.
   Driver fixes of this size are in-scope.
4. Small and contained? **PASS** — one function, +11/−5.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — pre-image matches `v6.18.53`.

**Step 9.3: EXCEPTION CATEGORIES**

Record: None (not a device ID, quirk, DT, build, or docs-only change).
Qualifies as a normal small bugfix.

**Step 9.4: DECISION**

Backport. The bugs exist in this 6.18 tree, the patch is surgical, and
the risk is far smaller than leaving a wait whose result is discarded
and a `1 << 0xff` on every unconfigure.

---

### What the commit solves for this tree

On 6.18.53, `stm32_cec_adap_log_addr()` waits for TXSOM then always
programs OAR and returns success. After a 2.1 s timeout that still
writes CFGR, which the 2019 change said must not happen during transmit,
and reports a successful LA update. Separately, unconfigure always
evaluates `(1 << 0xff) << 16` before the invalid-address check. The
patch returns the poll error first and only builds the mask for valid
LAs.

### Risk vs benefit

Benefit is correct CEC address programming and avoidance of a hardware-
illegal register update and a shift UB. Risk is a few lines in one STM32
CEC callback; the only extra symptom is `WARN_ON` if unconfigure hits a
stuck TXSOM.

---

### Verification

- **[Phase 1]** Parsed subject/tags from `git log -1` / `git show` of
  `a1157fd7d1e0f` and upstream `3bc2e4a26465`. No Fixes/Reported-by.
  Hans Verkuil SOB + committer.
- **[Phase 2]** Diff: +11/−5 in `stm32_cec_adap_log_addr`. Pre-image
  confirmed via `git show
  v6.18.53:drivers/media/cec/platform/stm32/stm32-cec.c`.
  `CEC_LOG_ADDR_INVALID` is `0xff`.
- **[Phase 3]** `git blame` on the function: `d69ae57453c80a` (v4.13),
  poll `1a726df6078c2f` (v5.2). `git merge-base --is-ancestor` of both
  vs `v6.18.53` and HEAD: present. No `Fixes:` tag. No follow-ups after
  the candidate on this file.
- **[Phase 3]** `git merge-base --is-ancestor 3bc2e4a26465 HEAD` → not
  in this branch (mainline-only). Local cherry-pick is on autosel;
  ignored as selection evidence.
- **[Phase 4]** `b4 dig -c/-a/-w`: v1-only, msgid
  `20260624144015.63929-1-pengpeng@iscas.ac.cn`, correct maintainers
  CCed. lore.kernel.org 403; LKML/Openwall/Patchew matched the committed
  diff; no NAK found.
- **[Phase 4]** Stable-list search unusable (anti-bot). UNVERIFIED:
  prior stable discussion.
- **[Phase 5]** Callers: `cec_config_log_addr`, `cec_adap_unconfigure`
  in `cec-adap.c`. `call_op` in `cec-priv.h`. Kconfig `CEC_STM32`.
- **[Phase 6]** `git describe HEAD` → `v6.18.53-5049-g0f0bdc2b0dffb`;
  `make kernelversion` → 6.18.53. Buggy code at v6.18.53. Clean pre-
  image.
- **[Phase 7]** Peripheral STM32 CEC; maintainer Hans Verkuil.
- **[Phase 8]** Failure: false success + illegal CFGR write (MEDIUM);
  shift UB on unconfigure (MEDIUM). Risk very low.
- **UNVERIFIED:** live review comments on lore (403); whether UBSAN has
  actually fired on this shift in the field.

**YES**

 drivers/media/cec/platform/stm32/stm32-cec.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/media/cec/platform/stm32/stm32-cec.c b/drivers/media/cec/platform/stm32/stm32-cec.c
index 8c2fc232202de..29418966a98ef 100644
--- a/drivers/media/cec/platform/stm32/stm32-cec.c
+++ b/drivers/media/cec/platform/stm32/stm32-cec.c
@@ -194,18 +194,24 @@ static int stm32_cec_adap_enable(struct cec_adapter *adap, bool enable)
 static int stm32_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
 {
 	struct stm32_cec *cec = adap->priv;
-	u32 oar = (1 << logical_addr) << 16;
 	u32 val;
+	int ret;
 
 	/* Poll every 100µs the register CEC_CR to wait end of transmission */
-	regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM),
-				 100, CEC_XFER_TIMEOUT_MS * 1000);
+	ret = regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM),
+				       100, CEC_XFER_TIMEOUT_MS * 1000);
+	if (ret)
+		return ret;
+
 	regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0);
 
-	if (logical_addr == CEC_LOG_ADDR_INVALID)
+	if (logical_addr == CEC_LOG_ADDR_INVALID) {
 		regmap_update_bits(cec->regmap, CEC_CFGR, OAR, 0);
-	else
+	} else {
+		u32 oar = BIT(logical_addr) << 16;
+
 		regmap_update_bits(cec->regmap, CEC_CFGR, oar, oar);
+	}
 
 	regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN);
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: v4l2-tpg: reduce stack usage for kasan builds
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (9 preceding siblings ...)
  2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] media: cec: stm32: return an error when log-address wait times out Sasha Levin
@ 2026-10-19 13:50 ` Sasha Levin
  2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] media: cx18: stop VBI start-code scan before short tail Sasha Levin
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:50 UTC (permalink / raw)
  To: patches, stable
  Cc: Arnd Bergmann, Hans Verkuil, Sasha Levin, mchehab, linux-media,
	linux-kernel

From: Arnd Bergmann <arnd@arndb.de>

[ Upstream commit c49cdaafa443ccf861a72d3191121294742c28c7 ]

tpg_fill_plane_buffer() is a rather complex function. While there is
nothing wrong with it per se, I have run into corner cases with clang-22
on s390 using KASAN that makes it run out of registers and blow the
stack warning limit from excessive spills:

drivers/media/common/v4l2-tpg/v4l2-tpg-core.c:2629:6: error: stack frame size (1560) exceeds limit (1536)
      in 'tpg_fill_plane_buffer' [-Werror,-Wframe-larger-than]
 2629 | void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,

Forcing the two largest callees out of line completely avoids the problem
and prevents all the register spills, with the stack usage for each function
going down to a few bytes for the local variables.

Arguably this is a problem caused by clang rather than the code, but
a noinline_for_stack annotation is an easy workaround.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

I have enough history, diff, and mailing-list evidence to walk through
all nine phases and decide for this 7.3-rc4 tree.

## Phase 1: Commit message forensics

**Step 1.1: Subject line**
- Record: `[media/v4l2-tpg] [reduce] Reduce stack usage of
  tpg_fill_plane_buffer() for clang+KASAN builds so -Wframe-larger-than
  does not fail the build.`

**Step 1.2: Tags**
- Record:
  - `Signed-off-by: Arnd Bergmann <arnd@arndb.de>` (author)
  - `Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (media
    maintainer)
  - No `Fixes:`
  - No `Reported-by:` / `Tested-by:` / `Reviewed-by:` / `Acked-by:` /
    `Link:` / `Cc: stable`
  - Absence of `Fixes:` / `Cc: stable` is expected for this pipeline and
    is not a negative signal
  - Notable: author is Arnd Bergmann (kbuild/clang/stack-usage); applied
    by Hans Verkuil (V4L2 maintainer). No syzbot, no user crash reports.

**Step 1.3: Body**
- Record:
  - **Bug:** `tpg_fill_plane_buffer()` is large; clang-22 on s390 with
    KASAN spills so many temporaries that the compile-time stack-frame
    warning fires as an error.
  - **Symptom:** `error: stack frame size (1560) exceeds limit (1536) in
    'tpg_fill_plane_buffer' [-Werror,-Wframe-larger-than]`
  - **Root cause:** clang register allocator + KASAN instrumentation,
    not incorrect C logic. Author: “nothing wrong with it per se” / “a
    problem caused by clang rather than the code”.
  - **Fix:** `noinline_for_stack` on the two largest callees so they are
    not inlined into the parent; per-function stack then drops to a few
    bytes.
  - **Version info:** clang-22, s390, KASAN. No kernel-version range
    given.

**Step 1.4: Hidden bug fix?**
- Record: Not a disguised UAF/leak/race. It is a **build-failure
  workaround**. Cover letter in the mbox also offers an LLVM bug if
  reviewers want one. Not a hidden runtime fix.

## Phase 2: Diff analysis

**Step 2.1: Inventory**
- Record:
  - File: `drivers/media/common/v4l2-tpg/v4l2-tpg-core.c` — 8
    insertions, 6 deletions (net +2)
  - Functions: `tpg_fill_plane_extras()`, `tpg_fill_plane_pattern()` —
    declaration only
  - Scope: single-file surgical annotation change; no logic, locking, or
    API change

**Step 2.2: Code flow**
- Record:
  - **Before:** both helpers are `static void`, so the compiler may
    inline them into `tpg_fill_plane_buffer()`.
  - **After:** both are `static noinline_for_stack void`; they remain
    callable from the same loop in `tpg_fill_plane_buffer()` (lines
    2707–2710) but cannot be inlined.
  - Path affected: compile-time inlining of the per-line fill helpers.
    Runtime control flow is unchanged.

**Step 2.3: Bug mechanism**
- Record: **Build / compiler-workaround (hardware-workaround
  analogue).** Not UAF, leak, race, NULL deref, or overflow.
  `noinline_for_stack` is `noinline` in `include/linux/compiler_types.h`
  “to prevent stack consumption”.

**Step 2.4: Fix quality**
- Record: Obviously correct and minimal. Regression risk is very low:
  extra calls in a test-pattern generator, not a production hot path.
  Arnd reports stack usage of each function drops. No public API /
  struct / locking change.

## Phase 3: Git history

**Step 3.1: Blame**
- Record: The two functions date to Hans Verkuil’s vivid TPG (2015),
  exported as `drivers/media/common/v4l2-tpg/v4l2-tpg-core.c` in
  `e07d46e7e0da8` (2016). The `noinline_for_stack` lines are this commit
  (`c49cdaafa443c`, 2026-06-18 / applied 2026-07-10). Long-lived code;
  the warning is from clang-22+KASAN inlining, not a new logic bug.

**Step 3.2: Fixes: tag**
- Record: None. Not applicable.

**Step 3.3: File history**
- Record: Recent TPG work is formats/patterns (`5a3757801e58a`,
  `5a531791edb24`), a div-by-zero fix, memleak fix. No prerequisite
  refactor. Standalone, not `N/M`.

**Step 3.4: Author**
- Record: Arnd Bergmann; many similar media stack-usage fixes
  (`c03b7dec3c4dd` rkvdec, `1a03f91c2c241` vivid clang stack,
  `ad4729225d93f` mxl5005s, etc.). This is the established
  `noinline_for_stack` pattern. Hans Verkuil applied it.

**Step 3.5: Dependencies**
- Record: Only `noinline_for_stack`, present in this tree as `#define
  noinline_for_stack noinline`. Applies standalone.

## Phase 4: Mailing list / external

**Step 4.1: Original discussion**
- Record:
  - `b4 dig -c c49cdaafa443c` →
    https://patch.msgid.link/20260618143252.1885475-1-arnd@kernel.org
  - `b4 dig -a`: **v1 only**, 2026-06-18. No later revision.
  - mbox is the patch plus: “If anyone thinks we should track this as an
    llvm bug, I can help come up with a reproducer”. **No replies, no
    NAK, no Cc: stable suggestion.**
  - lore.kernel.org WebFetch returned 403; thread recovered via `b4 dig
    -m`.

**Step 4.2: Recipients (`b4 dig -w`)**
- Record: Mauro Chehab, Nathan Chancellor, Nick Desaulniers, Bill
  Wendling, Justin Stitt, linux-media, LKML, llvm@lists.linux.dev. Right
  maintainers and LLVM list. No review tags in-tree beyond Hans’s SOB on
  apply.

**Step 4.3: Bug report**
- Record: No syzbot/bugzilla. The “report” is Arnd’s own clang-22 s390
  KASAN build. Severity: compile error under `-Werror`, not a runtime
  crash.

**Step 4.4: Series**
- Record: Standalone v1. Not part of a multi-patch series.

**Step 4.5: Stable list**
- Record: lore.kernel.org/stable WebFetch 403. **UNVERIFIED:** whether
  this was discussed on stable@. Nothing in the mbox nominates it.

## Phase 5: Semantic / call graph

**Step 5.1: Functions**
- Record: `tpg_fill_plane_extras`, `tpg_fill_plane_pattern`
  (annotations). Indirectly `tpg_fill_plane_buffer` (the function named
  in the warning).

**Step 5.2: Callers**
- Record: Both helpers are static and only called from
  `tpg_fill_plane_buffer()`. That function is `EXPORT_SYMBOL_GPL` and
  called from:
  - `tpg_fillbuffer()` (same file)
  - `drivers/media/test-drivers/vivid/vivid-kthread-cap.c`
  - `drivers/media/test-drivers/vimc/vimc-sensor.c`
  - `drivers/media/test-drivers/visl/visl-dec.c`
- Userspace-reachable only if a **virtual V4L2 test driver**
  (vivid/vimc/visl) is loaded. Not IRQ/core.

**Step 5.3: Callees**
- Record: memcpy of pattern lines, rectangle/pillar drawing, pixel-
  format switches. No locks, no alloc in the changed signatures.

**Step 5.4: Reachability**
- Record: Yes from userspace via vivid/vimc/visl, but those Kconfigs say
  “When in doubt, say N.” The failure being fixed is **compile-time**,
  so it hits anyone who *builds* `VIDEO_V4L2_TPG` (selected by those
  drivers; allmodconfig will build it).

**Step 5.5: Similar patterns**
- Record: Same `noinline_for_stack` workaround exists elsewhere in media
  (vivid 2019, rkvdec 2026). This instance is the TPG core helper, not a
  duplicate of those.

## Phase 6: This checkout

**Step 6.1: Local tree and buggy code**
- Record:
  - `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`
  - `make kernelversion` → `7.3.0-rc4`
  - Makefile: VERSION=7 PATCHLEVEL=3 SUBLEVEL=0 EXTRAVERSION=-rc4
  - File and functions exist. Pre-patch form was `static void
    tpg_fill_plane_*`. TPG present since 2016 (`e07d46e7e0da8` is an
    ancestor).
  - `git merge-base --is-ancestor c49cdaafa443c HEAD` is true (commit is
    in this development tree). That is **not** treated as “already
    selected for stable”.

**Step 6.2: Backport difficulty**
- Record: Clean apply on this tree. Only the two `static void`
  prototypes change. `noinline_for_stack` exists.

**Step 6.3: Related fixes already here**
- Record: No earlier equivalent TPG stack workaround. `1a03f91c2c241` is
  a similar vivid kthread workaround from 2019, different file/function.

## Phase 7: Subsystem context

**Step 7.1**
- Record: Subsystem `drivers/media/common/v4l2-tpg` (V4L2 test pattern
  generator). **PERIPHERAL** — only vivid/vimc/visl test drivers. Not
  mm/fs/net core.

**Step 7.2**
- Record: Mature (2015–2016), occasional format additions. Not a high-
  churn core path.

## Phase 8: Impact and risk

**Step 8.1: Who is affected**
- Record: Config-specific: `CONFIG_VIDEO_V4L2_TPG` via vivid/vimc/visl,
  plus clang-22, KASAN, `-Werror`, and `CONFIG_FRAME_WARN=1536` (error
  text). Default 64-bit `FRAME_WARN` is **2048** (`lib/Kconfig.debug`);
  1560 < 2048, so **default s390 64-bit allmodconfig would not fail**.
  1536 is the 32-bit Xtensa default, or a non-default int in
  randconfig/custom CI.

**Step 8.2: Trigger**
- Record: Building that file with that toolchain/config. Not a runtime
  trigger. Unprivileged users cannot “hit” it except as a failed kernel
  build.

**Step 8.3: Failure mode**
- Record: Compile error under `-Werror` (WERROR defaults to
  COMPILE_TEST). Runtime stack on s390 is 16KiB, 64KiB with KASAN
  (`arch/s390/Makefile`); 1560 bytes is not a runtime overflow.
  Severity: **MEDIUM for CI/debug builds with a lowered FRAME_WARN; LOW
  for production stable users.**

**Step 8.4: Risk-benefit**
- Record:
  - Benefit: unblocks clang+KASAN+Werror builds of TPG/vivid; tiny
    annotation.
  - Risk: very low (2 annotations, no behavior change).
  - Ratio: favorable **if** treated as a build fix; modest user benefit
    because the default 64-bit limit is 2048.

## Phase 9: Synthesis

**Step 9.1: Evidence**

FOR:
- Official `stable-kernel-rules.rst` lists **build error** (not
  CONFIG_BROKEN).
- Build-fix exception in the evaluation rubric.
- 8/6-line, obviously correct `noinline_for_stack` — the kernel’s
  standard answer to clang+KASAN frame-size errors.
- Author Arnd Bergmann; applied by Hans Verkuil; LLVM Linux people on
  Cc.
- Helpers and macro exist in this 7.3-rc4 tree; applies cleanly; no
  series deps.
- Similar media workarounds have been used for years.

AGAINST:
- Not a crash, UAF, deadlock, corruption, or security bug.
- Author: clang problem, not a logic bug.
- Only vivid/vimc/visl (test drivers, “When in doubt, say N”).
- Reproduced with FRAME_WARN **1536**; 64-bit default is **2048**, so
  typical s390 KASAN allmodconfig may not fail.
- clang-22 + s390 + KASAN is a narrow toolchain.
- No stable nomination, no user reports, v1 with no review discussion.

UNRESOLVED:
- Whether default `FRAME_WARN=2048` allmodconfig on this tree fails with
  clang-22+KASAN (reported size 1560 suggests no).
- Whether 32-bit clang+KASAN exceeds the 1280 default (not claimed;
  unverified).
- Whether stable@ ever discussed this (lore 403).

**Step 9.2: Stable rules checklist**
1. Obviously correct and tested? **PASS** — two `noinline_for_stack`
   marks; Arnd built it; maintainer applied v1.
2. Real bug that affects users? **PASS** as a **build error** for the
   configs that hit it; **weak** for production runtime users.
3. Important (crash/security/corruption/deadlock)? **PASS only via the
   documented build-error clause**, not via runtime severity. Frame 1560
   vs 1536 is a warning-as-error, not an oops.
4. Small and contained? **PASS** — one file, ~14-line diff, well under
   100 lines.
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — file, functions, and
   `noinline_for_stack` are all here.

**Step 9.3: Exception category**
- Record: **Build fix** (compilation error/warning under `-Werror`). Not
  a device-ID, quirk, DT, or docs exception.

**Step 9.4: Decision**

This tree is **Linux 7.3-rc4** (mainline). The TPG helpers are present;
the patch is self-contained and matches the code here.

It is not a runtime stability fix. It is the documented class of **build
error** that stable rules allow: clang-22 + KASAN inlines two large
`static` helpers into `tpg_fill_plane_buffer()` until `-Wframe-larger-
than` fails with `-Werror`. The change is two `noinline_for_stack`
annotations, no semantic change, negligible regression risk.

That is enough for this tree: the affected code exists, the workaround
is the usual one, and blocking KASAN/clang builds of `VIDEO_V4L2_TPG` is
a real compile failure even though vivid is a test driver.

## What the commit solves for this tree

`tpg_fill_plane_buffer()` grows a 1560-byte frame when clang-22+KASAN
inlines `tpg_fill_plane_extras()` and `tpg_fill_plane_pattern()`. With
`CONFIG_FRAME_WARN=1536` and `CONFIG_WERROR`, the build dies. Forcing
those callees out of line removes the spill storm. Stable users who
build this kernel with clang+KASAN+Werror (CI, debug kernels) need that
to compile; production runtime behavior is unchanged.

## Risk vs benefit

Benefit is restoring those builds; risk is two extra calls in a test-
pattern path. The FRAME_WARN=1536 vs default 2048 gap means default
64-bit configs may already pass, but the official build-error rule still
covers the failure Arnd hit, and the patch is too small to justify
withholding it.

## Verification
- [Phase 1] Parsed message/tags: Arnd + Hans SOB only; no
  Fixes/Reported-by/Link/Cc:stable
- [Phase 2] `git show c49cdaafa443c --stat`: 1 file, +8/-6; only two
  function signatures
- [Phase 2] Read `v4l2-tpg-core.c` ~2350–2712: loop still calls both
  helpers; no logic change
- [Phase 2] `noinline_for_stack` is `#define noinline` in
  `include/linux/compiler_types.h:264`
- [Phase 3] `git blame` on the annotations: `c49cdaafa443c`; older
  `static void` from 2015 vivid TPG
- [Phase 3] Origin `e07d46e7e0da8` (2016) is an ancestor of HEAD
- [Phase 3] No Fixes: tag to follow
- [Phase 3] `git log --oneline -20 --
  drivers/media/common/v4l2-tpg/v4l2-tpg-core.c`: no prerequisite series
- [Phase 4] `b4 dig -c c49cdaafa443c`: lore msgid
  `20260618143252.1885475-1-arnd@kernel.org`
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: media + LLVM maintainers Cc’d
- [Phase 4] `b4 dig -m /tmp/tpg-thread.mbox`: patch + LLVM-bug offer; no
  replies
- [Phase 4] WebFetch lore/stable: 403 — UNVERIFIED stable-list history
- [Phase 5] `git grep tpg_fill_plane_buffer`: vivid, vimc, visl only
- [Phase 5] No semcode MCP; used grep/read
- [Phase 6] `git describe HEAD` / `make kernelversion`: v7.3-rc4 /
  7.3.0-rc4
- [Phase 6] `git merge-base --is-ancestor c49cdaafa443c HEAD`: yes
  (original commit in this tree; not used as circular “already
  selected”)
- [Phase 6] Parent blobs still have `static void
  tpg_fill_plane_extras/pattern`
- [Phase 7] Kconfig: `VIDEO_V4L2_TPG` tristate selected by
  vivid/vimc/visl test drivers
- [Phase 8] `lib/Kconfig.debug`: FRAME_WARN default 2048 if 64BIT, 1536
  only if !64BIT && XTENSA; s390 `STACK_SIZE` 16K/64K with KASAN
- [Phase 8] `init/Kconfig`: WERROR default COMPILE_TEST
- UNVERIFIED: allmodconfig with default FRAME_WARN=2048 on clang-22 s390
  KASAN (1560 suggests it would pass)
- UNVERIFIED: 32-bit clang KASAN frame size vs 1280 default

**YES**

 drivers/media/common/v4l2-tpg/v4l2-tpg-core.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
index 931e5dc453b90..e1d5c220f7381 100644
--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
@@ -2346,9 +2346,11 @@ static void tpg_fill_params_extras(const struct tpg_data *tpg,
 			(params->is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
 }
 
-static void tpg_fill_plane_extras(const struct tpg_data *tpg,
-				  const struct tpg_draw_params *params,
-				  unsigned p, unsigned h, u8 *vbuf)
+/* noinline to work around clang KASAN issues */
+static noinline_for_stack void
+tpg_fill_plane_extras(const struct tpg_data *tpg,
+		      const struct tpg_draw_params *params,
+		      unsigned p, unsigned h, u8 *vbuf)
 {
 	unsigned twopixsize = params->twopixsize;
 	unsigned img_width = params->img_width;
@@ -2483,9 +2485,9 @@ static void tpg_fill_plane_extras(const struct tpg_data *tpg,
 	}
 }
 
-static void tpg_fill_plane_pattern(const struct tpg_data *tpg,
-				   const struct tpg_draw_params *params,
-				   unsigned p, unsigned h, u8 *vbuf)
+static noinline_for_stack void
+tpg_fill_plane_pattern(const struct tpg_data *tpg, const struct tpg_draw_params *params,
+		       unsigned p, unsigned h, u8 *vbuf)
 {
 	unsigned twopixsize = params->twopixsize;
 	unsigned img_width = params->img_width;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: cx18: stop VBI start-code scan before short tail
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (10 preceding siblings ...)
  2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] media: v4l2-tpg: reduce stack usage for kasan builds Sasha Levin
@ 2026-10-19 13:51 ` Sasha Levin
  2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Program the sensor on stream start Sasha Levin
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:51 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Hans Verkuil, Sasha Levin, awalls, mchehab,
	linux-media, linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit bf533acaaa7dee21d49bcaabf8e813ea36bddcd8 ]

compress_sliced_buf() scans one byte at a time while testing a four-byte
VBI start code.  The final iterations can read beyond the remaining
buffer tail.

Stop the scan once fewer than four bytes remain.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is **v7.3-rc4** (mainline `7.3.0-rc4`). The candidate is
`bf533acaaa7de` (“media: cx18: stop VBI start-code scan before short
tail”). It is a one-line bounds fix for a four-byte VBI start-code scan
that can read past `bytesused`.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

Step 1.1: PARSE THE SUBJECT LINE
Record: **[media/cx18] [stop] [stop VBI start-code scan before a short
4-byte tail]**
- Subsystem: `media: cx18`
- Verb: **stop** (prevent incorrect continuation) — a bug-fix verb even
  without “fix”
- Intent: do not scan a 4-byte EAV/start code when fewer than 4 bytes
  remain

Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Signed-off-by:** Pengpeng Hou &lt;pengpeng@iscas.ac.cn&gt; (author)
- **Signed-off-by:** Hans Verkuil &lt;hverkuil+cisco@kernel.org&gt;
  (media maintainer; applied the patch)
- **No Fixes:**
- **No Reported-by / Tested-by / Reviewed-by / Acked-by / Link / Cc:
  stable**
- Absence of Fixes/Cc:stable is expected for this pipeline and is not a
  negative signal
- Ignored: any Sasha Levin SOB / “[Upstream commit …]” (none in the real
  commit)

Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** `compress_sliced_buf()` walks one byte at a time and tests
  `buf[0]..buf[3]`. The last iterations can read past the remaining
  tail.
- **Symptom:** out-of-bounds **read** of 1–3 bytes past `size` (the
  caller’s `buf->bytesused`).
- **Failure mode:** memory-safety defect (possible slab/page over-read
  if `bytesused` equals the allocation; otherwise a logical over-read of
  DMA payload).
- **Version info:** none in the message. History shows the loop since
  2008/2009.
- **Root cause (author):** loop condition `i < size` does not leave four
  readable bytes.

Step 1.4: DETECT HIDDEN BUG FIXES
Record: **Not disguised.** It is an explicit bounds fix. Not
cleanup/refactor.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

Step 2.1: INVENTORY THE CHANGES
Record:
- **File:** `drivers/media/pci/cx18/cx18-vbi.c` — **1 insertion, 1
  deletion** (`2 +-`)
- **Function:** `compress_sliced_buf()`
- **Scope:** single-file, single-line surgical fix

Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- **Before:** `for (i = hdr_size, buf += hdr_size; i < size; i++,
  buf++)` then `buf[0]..buf[3]`. When `i` is `size-3`, `size-2`, or
  `size-1`, `buf[3]` is at `size`, `size+1`, or `size+2` — past the
  valid tail.
- **After:** `i + 3 < size` so the last readable index is `i+3 <=
  size-1`.
- **Path:** sliced-VBI start-code search (not probe init). Only the “no
  start code until EOF” path actually hits the tail; a successful match
  `break`s earlier.

Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- **Category:** **(d) memory safety** — buffer over-read / out-of-bounds
- **Mechanism:** 4-byte peek with a 1-byte stride and an exclusive
  `size` bound.
- **Fix:** require four remaining bytes (`i + 3 < size`), the same
  pattern as the sibling ivtv change.

If no start code is found:
- Old: `i == size`, then `size -= (i - hdr_size)` → remaining `hdr_size`
  (12)
- New: `i == size - 3` (when `size` is large enough), remaining
  `hdr_size + 3` (15)
Both are still `< line_size` (272/284), so the function still returns 0.
A 4-byte code cannot sit in the last 3 bytes, so no false negative.

Step 2.4: ASSESS THE FIX QUALITY
Record:
- **Obviously correct.** Classic `need N bytes remaining` bound.
- **Minimal.** One condition, no API/locking/structure change.
- **Regression risk: very low.** False match in the old over-read tail
  still left remaining size ≪ `line_size`. `i` starts at `hdr_size` (12)
  and only increments; `i + 3 < size` with `u32 size` is safe for
  realistic DMA sizes.
- **Red flags:** none.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

Step 3.1: BLAME THE CHANGED LINES
Record:
- Loop introduced in **`1c1e45d17b663d`** (Hans Verkuil, 2008-04-28) —
  original cx18 driver, `for (i = 0; i < size; i++, buf++)`.
- Current form (`i = hdr_size, buf += hdr_size; i < size`) from
  **`4ab9b256b5908a`** (Andy Walls, 2009-03-14) — “Optimize processing
  of VBI buffers”.
- Bug present ~17 years. Bound fixed in **`bf533acaaa7de`** (Pengpeng
  Hou, 2026-06-30; Hans Verkuil commit).

Step 3.2: FOLLOW THE FIXES: TAG
Record: **No Fixes: tag.** N/A. Introducer is `4ab9b256b5908a` /
original `1c1e45d17b663d`, both ancestors of this tree.

Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Recent cx18-vbi.c: this fix, email/SPDX/typo/whitespace. No refactor
  of the scan.
- **Sibling (same author, same day, same maintainer):** `f373cf17fb8e7`
  `media: ivtv: stop VBI start-code scan before short tail` — same one-
  line change in `drivers/media/pci/ivtv/ivtv-vbi.c`.
- **Standalone.** Not “patch X/Y”. ivtv is a parallel clone, not a
  prerequisite.

Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record:
- Pengpeng Hou: several small media correctness patches (ivtv twin, cec,
  v4l2-ctrls, stm32 resume errors). Not the cx18 maintainer.
- **Andy Walls** is listed maintainer for CX18; **Hans Verkuil** applied
  this (media co-maintainer). That is a strong apply-path signal.

Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: **None.** Touches only the for-condition. Parent still has
`compress_sliced_buf()`, `sliced_vbi_eav_rp[]`, and `i < size`. Applies
standalone.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- **b4 dig -c bf533acaaa7de:** match
  https://patch.msgid.link/2026063007035519.3-ccfa108-0014-media-
  cx18-stop-VBI-start-c-pengpeng@iscas.ac.cn
- **b4 dig -a:** **v1 only** (2026-06-30). Applied version is that v1.
- **b4 dig -m:** mbox is the original submission only — commit body +
  1-line diff. **No replies, NAK, or on-list review.**
- lore.kernel.org HTTP: Anubis 403. Discussion beyond the mbox is
  **UNVERIFIED** via WebFetch.
- Hans Verkuil’s SOB is the review/apply signal.

Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (**b4 dig -w**):
- To: Andy Walls (CX18 maintainer), Mauro Carvalho Chehab
- Cc: linux-media, linux-kernel
- Applied by Hans Verkuil. Right lists/maintainers were CCd.

Step 4.3: SEARCH FOR THE BUG REPORT
Record: **No Reported-by, no syzbot, no bugzilla Link.** Looks like
static/code inspection, not a user crash. Twin ivtv patch supports that.

Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Independent `[PATCH]` plus independent ivtv twin (`…-0015-media-
ivtv-…`). No hidden series dependency. This commit is self-contained.

Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: **UNVERIFIED** (lore/stable search blocked). Local history has
no stable-discussion commit for this subject. No evidence it was
rejected for stable.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: **`compress_sliced_buf()`** only.

Step 5.2: TRACE CALLERS
Record (grep, not semcode — semcode MCP not available):
- `compress_sliced_buf()` ← `_cx18_process_vbi_data()` when **not** raw
  VBI
- `_cx18_process_vbi_data()` ← `cx18_process_vbi_data()` per buffer on a
  VBI MDL
- `cx18_process_vbi_data()` ← `cx18_fileops.c` on userspace read of VBI,
  or internal VBI while reading MPEG (`CX18_F_S_INTERNAL_USE`)
- **Context:** process context, V4L2 read/DQBUF — not IRQ. User-
  reachable with sliced VBI capture on cx18.

Step 5.3: TRACE CALLEES
Record: start-code compare; later `v4l2_subdev_call(...,
decode_vbi_line)` and `memcpy` of 42 bytes. The changed loop only
searches; it does not decode until a full line is found.

Step 5.4: FOLLOW THE CALL CHAIN
Record:
`VIDIOC_QBUF/read` → `cx18_dequeue` → `cx18_process_vbi_data` →
`_cx18_process_vbi_data` → `compress_sliced_buf`
- **Userspace-reachable:** yes, with this card and sliced VBI.
- Unprivileged: only with access to the V4L device node (typical video
  group / capture app).

Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same bug in **ivtv** `compress_sliced_buf()`; already fixed with
`i + 3 < size`. No other `i + 3 < size` hits under `drivers/media`.
Systematic cloned-driver bug, both fixed.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- **Tree:** `git describe HEAD` = **v7.3-rc4-27-gf0100363d8c37**; `make
  kernelversion` = **7.3.0-rc4**
- Driver and function exist: `drivers/media/pci/cx18/cx18-vbi.c`
- **This commit is already an ancestor of HEAD** (`git merge-base --is-
  ancestor bf533acaaa7de HEAD` succeeded)
- First mainline tag containing it: **`v7.3-rc1`** (`git describe
  --contains --match 'v*'`)
- **Buggy bound `i < size` is in the parent** `bf533acaaa7de^`; it is
  not a post-7.3 invention
- Introduced **2008/2009**, so every current stable series that still
  has cx18 has the bug unless this commit was backported
- Already-in-HEAD on **mainline 7.3-rc4** is expected; it is not
  “already selected for stable”

Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **Clean apply.** Surrounding function is stable since 2009 aside
from macros/email/SPDX. Stable trees with `i < size` get a 1-line
conflict-free change.

Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: This is the fix. No earlier alternate bound check. ivtv twin is
a different driver.

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record:
- **Subsystem:** media / PCI V4L2 — Conexant CX23418 (Hauppauge HVR-1600
  and similar)
- **Criticality: PERIPHERAL** — old PCI capture card, not mm/net/VFS
- `CONFIG_VIDEO_CX18`; maintainer Andy Walls; list linux-media

Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: **Mature/quiet.** Recent cx18 commits are treewide/API; this is
one of the few real local bugfixes. Long-lived bug, not churn from a
rewrite.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific / config-specific:** `CONFIG_VIDEO_CX18`,
sliced VBI (not raw). Population is small (HVR-1600-class cards) but
real.

Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record:
- Trigger: sliced VBI processing when the 4-byte EAV (`0xff 00 00
  {0xb0,0xf0}`) is not found before the tail — then the loop runs to EOF
  and over-reads
- How common: every sliced-VBI buffer that lacks a match in-range; with
  valid hardware the match is usually early
- Unprivileged: only via the V4L node, not a generic syscall primitive
- Not a race

Default buffer sizing (verified):
- `stream_buf_size[VBI] = VBI_ACTIVE_SAMPLES * 36` = **1444 × 36 =
  51984**
- Sliced MDL: NTSC **9792**, PAL **12496**; `bufs_per_mdl = 1`
- `buf->buf = kmalloc(s->buf_size)` (51984); DMA/`bytesused` ≈ mdl_size
  (~10–12K)
- Default: 1–3 bytes past `bytesused` are **still inside the kmalloc
  object** (not a KASAN slab redzone hit)
- If `bytesused == buf_size` (full buffer), it **would** be a true
  allocation over-read

Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- **Failure mode:** 1–3 byte read past valid DMA `bytesused` while
  matching start codes (result not copied to userspace)
- Default config: no crash, no leak to userspace, no functional change
  (tail false-match still leaves size ≪ line_size)
- Edge: true slab/page OOB / oops if used size equals allocation
- **Severity: MEDIUM** as memory-safety/correctness; **not CRITICAL**
  (no demonstrated panic/corruption). Still a real OOB class bug.

Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** closes a long-standing OOB read on a live capture path;
  low user count
- **Risk: very low** (1 line, loop bound only)
- **Ratio:** favorable — tiny risk, real bounds bug, same pattern
  already used on ivtv

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

Step 9.1: COMPILE THE EVIDENCE
**FOR backporting:**
- Real 4-byte peek past `size`; classic OOB-read class used in stable
- One line, obviously correct, no API/feature
- Code has been in-tree since 2008/2009; no missing prereqs
- Userspace-reachable sliced VBI on cx18
- Applied by Hans Verkuil; CX18 maintainer CCd
- Twin ivtv fix confirms the pattern
- Regression risk essentially zero

**AGAINST:**
- No syzbot/user/crash report
- Peripheral 2008 PCI encoder, small population
- Default kmalloc (52K) ≫ typical `bytesused` (~10K), so default may not
  oops
- No Fixes/Cc:stable (not a veto here)
- Not core mm/fs/net

**UNRESOLVED:**
- lore/stable threads beyond b4 mbox (Anubis)
- No sanitizer report found

Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — bound is locally checkable;
   accepted by media maintainer (no extra Tested-by)
2. Fixes a real bug that affects users? **PASS** — over-read of the VBI
   payload bound on a real capture path
3. Important issue? **PASS** (medium) — memory-safety OOB; crash only if
   used size equals allocation; still the OOB class stable takes as
   small driver fixes
4. Small and contained? **PASS** — 1 line, 1 function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — already in this 7.3-rc4 tree;
   parent form applies cleanly wherever `i < size` remains

Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **None** (not ID/quirk/DT/build/doc). Qualifies as a normal
small bugfix.

Step 9.4: MAKE YOUR DECISION
This tree is mainline **7.3-rc4**, which already contains the fix
(landed in **v7.3-rc1**). The evaluation is technical merit for stable,
not “re-apply on 7.3”.

The bug is a one-byte-stride scan of a four-byte start code with `i <
size`, present since 2008/2009. The patch is the standard remaining-
bytes fix. It does not add features, does not need other commits, and
will not regress the later line parser.

Default cx18 VBI buffers make a crash unlikely, but it is still a real
bounds bug on a user-triggerable path, with ~zero backport risk. That is
enough for YES on this tree’s stable-candidate criteria.

------------------------------------------------
What the commit solves for stable users
`compress_sliced_buf()` must see `buf[0]..buf[3]`. With `i < size`, the
last three iterations read past `bytesused`. Stopping at `i + 3 < size`
prevents that. Users with Hauppauge HVR-1600-class cx18 cards doing
sliced VBI (or MPEG with inserted VBI) no longer walk off the valid DMA
tail.

Stable rules / risk
Meets the rules: obvious, small, no new API, real OOB. Benefit is modest
(niche driver, default alloc has slack); risk is negligible. Prefer
taking a 1-line memory-safety fix over leaving a 17-year over-read.

Concerns
None for apply/prereqs. Not a sanitizer/CVE-backed crash. ivtv twin is
separate. This 7.3-rc4 checkout already has the commit; older stables
still on `i < size` are the backport targets.

Verification:
- [Phase 1] Subject/tags: media/cx18 “stop”; SOBs Hou + Verkuil; no
  Fixes/Reported-by/Link/Cc:stable
- [Phase 2] Diff: `drivers/media/pci/cx18/cx18-vbi.c`
  `compress_sliced_buf()` `i < size` → `i + 3 < size` (1/1)
- [Phase 2] Confirmed `buf[0]..buf[3]` vs exclusive `size`; post-loop
  `size < line_size` still holds if no match
- [Phase 3] `git blame`: loop from `1c1e45d17b663d` (2008) /
  `4ab9b256b5908a` (2009); fix `bf533acaaa7de`
- [Phase 3] `git show bf533acaaa7de^`: parent still has `i < size`
- [Phase 3] Sibling `f373cf17fb8e7` ivtv same change; author log shows
  both
- [Phase 4] `b4 dig -c`: lore msgid `2026063007035519.3-ccfa108-0014-…`;
  v1 only; mbox = patch, no replies
- [Phase 4] `b4 dig -w`: Walls, Chehab, linux-media, linux-kernel
- [Phase 4] WebFetch/WebSearch lore: **UNVERIFIED** (Anubis 403)
- [Phase 5] Callers: `_cx18_process_vbi_data` ← `cx18_process_vbi_data`
  ← `cx18-fileops.c` VBI/MPEG read
- [Phase 5] `i + 3 < size` only in cx18-vbi.c and ivtv-vbi.c
- [Phase 6] `git describe HEAD` v7.3-rc4-27; kernel 7.3.0-rc4; `merge-
  base --is-ancestor bf533acaaa7de HEAD` true; `--contains` v7.3-rc1
- [Phase 6] File present; apply would be clean on `i < size`
- [Phase 7] CONFIG_VIDEO_CX18; MAINTAINERS Andy Walls; mature driver
- [Phase 8] buf_size 1444*36=51984; sliced mdl_size 9792/12496;
  kmalloc(buf_size) so default over-read stays in-object
- [Phase 8] Failure: OOB read, severity MEDIUM; risk very low
- UNVERIFIED: on-list review beyond Hans’s SOB; stable@ discussion;
  KASAN/syzbot report

**YES**

 drivers/media/pci/cx18/cx18-vbi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c
index 8dc4ce3259353..3a8430f3259eb 100644
--- a/drivers/media/pci/cx18/cx18-vbi.c
+++ b/drivers/media/pci/cx18/cx18-vbi.c
@@ -135,7 +135,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
 				    : VBI_HBLANK_SAMPLES_50HZ;
 
 	/* find the first valid line */
-	for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) {
+	for (i = hdr_size, buf += hdr_size; i + 3 < size; i++, buf++) {
 		if (buf[0] == 0xff && !buf[1] && !buf[2] &&
 		    (buf[3] == sliced_vbi_eav_rp[0] ||
 		     buf[3] == sliced_vbi_eav_rp[1]))
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Program the sensor on stream start
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (11 preceding siblings ...)
  2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] media: cx18: stop VBI start-code scan before short tail Sasha Levin
@ 2026-10-19 13:51 ` Sasha Levin
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] media: cec/core: drop cec_post_state_event call Sasha Levin
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:51 UTC (permalink / raw)
  To: patches, stable
  Cc: Jurison Murati, Sakari Ailus, Sasha Levin, mchehab, linux-media,
	linux-kernel

From: Jurison Murati <eng.juri@gmail.com>

[ Upstream commit 4e1446ac169a1a621ba90502ab8db3be821fe726 ]

The sensor registers are only written in the runtime PM resume
handler; ov8865_set_fmt() merely stores the requested mode, relying on
the sensor being runtime suspended between uses so that the next
resume applies it.

That assumption breaks when something keeps the sensor powered. On
IPU3 platforms, ipu_bridge instantiates the VCM device with a
DL_FLAG_PM_RUNTIME device link to the sensor, so a userspace process
holding the VCM subdev open (e.g. wireplumber's camera monitor) pins
the sensor runtime-active. A subsequent set_fmt() then never reaches
the hardware: the sensor keeps streaming the mode programmed on the
last resume while the CSI-2 receiver expects the newly negotiated
format.

On a Surface Book 2 (IPU3, ov8865 + dw9719 VCM), requesting the
3264x2448 mode while the hardware was left programmed for the
1632x1224 binned mode makes ipu3-cio2 report "frame sync error" and
"payload length is 10340352, received 2585088" (exactly one binned
frame) for every frame, and the inverse case stalls the stream after
a single frame. Camera applications end up displaying one bogus frame
forever.

Program the sensor configuration and apply the control values on
stream start instead, where the negotiated mode is always current,
and only write the configuration in the runtime PM resume handler
when resuming with the stream already started.

Signed-off-by: Jurison Murati <eng.juri@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local checkout is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
verdict is whether this ov8865 programming fix belongs **here**, not in
other series.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[media: i2c: ov8865] [Program] Program the sensor on stream
start` — “Program” here is a correctness change: write the negotiated
mode at `s_stream`, not only on runtime resume.

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Jurison Murati <eng.juri@gmail.com>` (author)
- `Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>`
  (media/I2C sensor maintainer; merger)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Cc:
  stable`, `Link:`, or syzbot tags (absence expected)
- Mailing-list thread (Phase 4) has `Reviewed-by: Daniel Scally` on
  series patch 1/2 only, not on this 2/2 as merged

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: `set_fmt()` only stores the mode; registers are written in the
  runtime-PM resume handler. That assumes the sensor suspends between
  uses.
- Trigger: IPU3 `ipu_bridge` VCM device link (`DL_FLAG_PM_RUNTIME`) plus
  userspace holding the VCM subdev open (wireplumber camera monitor)
  keeps the sensor runtime-active, so resume never runs after
  `set_fmt()`.
- Symptom: CSI-2 receiver (`ipu3-cio2`) sees a format mismatch. Full
  3264×2448 vs leftover 1632×1224 binned mode → `"frame sync error"` and
  `"payload length is 10340352, received 2585088"`; the inverse stalls
  after one frame. Camera apps show one bogus frame forever.
- Hardware: Surface Book 2 (IPU3, ov8865 + dw9719 VCM).
- Fix: program + apply controls on stream start; resume only reprograms
  if already streaming (mid-stream suspend).

**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. Explicit functional bug: hardware left in the
previous mode.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/media/i2c/ov8865.c` (+25 / −9)
- Functions: `ov8865_s_stream()`, `ov8865_resume()`
- Scope: single-file, surgical

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- `ov8865_s_stream(enable=1)` before: `pm_runtime_resume_and_get()` then
  only `ov8865_sw_standby(false)`. After: still resume_and_get, then
  always `ov8865_sensor_init()` + `__v4l2_ctrl_handler_setup()` then
  standby off. Stream-start path.
- `ov8865_resume()` before: always `sensor_init` + ctrl setup, then
  standby off if streaming. After: those writes only if
  `state->streaming`. Runtime-resume path; skipped when VCM merely pins
  power.

**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: `[Logic / correctness]` Mode was applied only on RPM resume.
With an external RPM pin, `set_fmt()` never reached the sensor. Fix
writes the current software mode at stream start. Category is not
UAF/leak/race; it is a hardware/software format desync.

**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct. Matches the usual sensor pattern (configure
at stream on). Extra I2C on every start is harmless (same work resume
used to do). Resume still covers mid-stream suspend. `int ret = 0` is
required because disable no longer assigned `ret` before the new `if
(!ret)` guard. Regression risk low; no API/lock change. Depends on
sibling 1/2 (`3fe797a12bfa9`) for unified `pm_runtime_put` on
`sensor_init` failure — that commit **is** in this tree.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Driver added in `11c0d8fdccc56` (“Add support for the OV8865 image
  sensor”, 2020-12-31, first in **v5.12-rc1**). Original `s_stream` only
  toggled standby after RPM get; resume always called `sensor_init`.
- Original `ov8865_state_configure()` **did** call
  `ov8865_mode_configure()` when the device was already runtime-active
  (`!pm_runtime_suspended`). That covered the VCM-pin case at
  `set_fmt()`.
- `da8f23e359166` (“move mode_configure out of state_configure”,
  2025-09-09, contained in **v6.18-rc1**) removed that powered-path
  `mode_configure`. That is the regression this commit repairs. Present
  in this 7.3 tree.

**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. The introducing commit is `da8f23e359166`. `git
merge-base --is-ancestor da8f23e359166 HEAD` succeeded.

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `3fe797a12bfa9` — same author, same second, series 1/2: drop RPM count
  on stream failure. v2 changelog says 2/2 was rebased on that unified
  error path.
- `8e3e916e23f5a` (2023-08-10) — `ipu-bridge` VCM `DL_FLAG_PM_RUNTIME`
  link (the pin).
- No follow-up/revert of `4e1446ac169a1` on this file after it landed.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Jurison Murati has these two ov8865 commits in-tree. Not the
subsystem maintainer. Sakari Ailus merged both. Dan Scally (Intel
IPU3/libcamera) reviewed the series.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Soft prerequisite: `3fe797a12bfa9` (already in HEAD). Without
it, `sensor_init` failure after `resume_and_get` would leak the RPM ref.
No new helpers. Standalone on this tree.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 4e1446ac169a1`: https://patch.msgid.link/fa341298dfd2ba9ce4
  31e21c2cf45002efacf2cf.1781085860.git.eng.juri@gmail.com
- Series: v1 then v2 (2 patches).
  - v1 1/2: “Program the mode on stream start if needed” — extra
    `hw_mode`/`hw_mbus_code` state
  - v1 2/2: RPM put on stream-start failure
  - v2 1/2: RPM leak fix (reordered)
  - v2 2/2: this commit (unconditional program at start; resume gated on
    streaming)
- Applied version is v2, latest. No NAK. Sakari: do not add more driver
  state; Dan: program unconditionally at `s_stream` and gate resume —
  that is what landed. Author retested on Surface Book 2 with the sensor
  held runtime-active; both modes worked; mid-stream resume still
  reprogrammed.
- No `Cc: stable` in the thread.

**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: `b4 dig -w` recipients: Sakari Ailus, Daniel Scally, Hans de
Goede, Mauro Carvalho Chehab, linux-media. Right audience (sensor
maintainer, IPU3/VCM authors).

**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot. Concrete user-visible failure on Surface
Book 2 with exact cio2 log lines. Author is the reporter; not a
theoretical race.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 2/2 of a two-patch series. 1/2 is `3fe797a12bfa9`, already in
this tree. This hunk does not need other media patches.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: WebFetch of lore.kernel.org/stable returned 403. `b4` mbox has
no “stable” mention. UNVERIFIED whether stable@ discussed this later.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `ov8865_s_stream` (modified), `ov8865_resume` (modified).
Callees used: `ov8865_sensor_init`, `__v4l2_ctrl_handler_setup`,
`ov8865_sw_standby`. `ov8865_set_fmt` → `ov8865_state_configure` is the
path that only stores `state->mode`.

**Step 5.2: TRACE CALLERS**
Record: `ov8865_s_stream` is `.s_stream` on the V4L2 subdev. Called from
the media pipeline when userspace starts/stops capture (libcamera /
camera apps), not IRQ. `ov8865_resume` is `SET_RUNTIME_PM_OPS` runtime
resume.

**Step 5.3: TRACE CALLEES**
Record: `ov8865_sensor_init` does sw reset, standby, chip-id, init
sequence, then `ov8865_mode_configure(sensor->state.mode, …)` — so it
programs the **currently negotiated** mode. That is why calling it from
`s_stream` after `set_fmt()` is the right place.

**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace opens VCM (wireplumber) → `ipu_bridge`
`device_link_add(..., DL_FLAG_PM_RUNTIME)` keeps sensor RPM-active →
`VIDIOC_S_FMT`/`set_fmt` updates software mode only → `s_stream(1)` used
to only leave standby, leaving old registers → `ipu3-cio2` receives the
wrong frame size. Unprivileged user with camera access can trigger it;
wireplumber makes it the common case.

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: `ov5648_s_stream` still only does standby after RPM get and
always inits in resume — sibling still has the old pattern. Not a reason
to reject this ov8865 fix. `ipu-bridge.c:714` still has the VCM PM link.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Tree: VERSION=7 PATCHLEVEL=3 SUBLEVEL=0 EXTRAVERSION=-rc4
- `drivers/media/i2c/ov8865.c`, `VIDEO_OV8865`, ipu3-cio2,
  `ipu_bridge_instantiate_vcm_work` + `DL_FLAG_PM_RUNTIME` all exist
- Regression `da8f23e359166` is an ancestor of HEAD
- Pre-fix `s_stream` (parent of `4e1446ac169a1`) only called
  `ov8865_sw_standby`; pre-fix `resume` always inited
- cio2 strings `"frame sync error"` and `"payload length is %lu,
  received %u"` match the report (`ipu3-cio2.c`)

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply on this tree. Prerequisite `3fe797a12bfa9` already
present. Difficulty: clean.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No other fix for “wrong mode while RPM-pinned.” `git merge-base
--is-ancestor 4e1446ac169a1 HEAD` is true — used only to confirm file
state, not as “already selected for stable.”

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/media/i2c` OmniVision OV8865. **IMPORTANT** for IPU3
laptops that use this sensor (Surface Book 2 and similar); not core
mm/fs/net. Camera capture is a primary function of that hardware.

**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Driver is mature (v5.12). Recent changes are targeted fixes, not
a rewrite. Bug is a 2025 regression in a long-lived driver.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Users of ov8865 with a VCM RPM device link (IPU3 +
`ipu_bridge`), especially when wireplumber/PipeWire keeps the VCM open.
Driver-specific / platform-specific, but real shipping laptops.

**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Common on affected machines: camera monitor holds VCM, then a
capture app sets format and streams. Not a rare race. Unprivileged users
with camera access can hit it.

**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Not oops/UAF/deadlock. Camera stream is wrong or stuck: cio2
frame-sync/payload errors, one frozen bogus frame, or stall after one
frame. **HIGH** for those users (device unusable), **MEDIUM–HIGH**
overall.

**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: Benefit: restores working capture after a v6.18 regression.
Risk: low (~34-line, one driver, reviewed, retested). Ratio favors
including the fix.

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

**Step 9.1: COMPILE THE EVIDENCE**

FOR backporting:
- Real, reproduced bug on Surface Book 2 with exact cio2 logs present in
  this tree
- Regression from `da8f23e359166` (v6.18), which is in this tree; that
  commit removed the only powered-path `mode_configure` on `set_fmt`
- Trigger is ordinary (wireplumber + IPU3 VCM PM link, also in this
  tree)
- Small, obviously correct, no new API
- v2 matches maintainer (Sakari) and IPU3 reviewer (Dan Scally)
  feedback; retested
- Prerequisite RPM error-path fix is already here

AGAINST backporting:
- Not a kernel crash, UAF, or security hole
- Affects one sensor + IPU3/VCM, not all users
- No explicit `Cc: stable` (not a negative by itself)
- Merged 2/2 has no in-commit `Reviewed-by` (review happened on the
  list)

UNRESOLVED:
- lore.kernel.org WebFetch 403; thread recovered via `b4 dig -m`
- Whether stable@ later discussed this (no hit in the patch mbox)

**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — v2 as Dan/Sakari asked;
   author retested both modes and mid-stream resume on SB2
2. Fixes a real bug that affects users? **PASS** — camera unusable when
   VCM pins the sensor
3. Important issue? **PASS** — serious functional failure of the laptop
   camera (wrong CSI-2 format / stuck frame), not cosmetic
4. Small and contained? **PASS** — +25/−9, one file, two functions
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — same functions;
   `3fe797a12bfa9` present

**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None of ID/quirk/DT/build/docs. It is a normal driver
correctness fix (plus the spirit of a hardware-path workaround for the
VCM PM link).

**Step 9.4: MAKE YOUR DECISION**
This tree has the ov8865 driver, the v6.18 `mode_configure` removal that
dropped the powered `set_fmt` path, and the IPU3 VCM RPM pin that makes
that path the default with wireplumber. The result is a format mismatch
that breaks capture. The fix is small, reviewed, and tested. It meets
stable rules for this checkout.

Verification:
- [Phase 1] Parsed tags: author + Sakari SOB only; no Fixes/Reported-
  by/syzbot/Cc:stable
- [Phase 2] Diff: `ov8865_s_stream` always inits+ctrl setup on enable;
  `ov8865_resume` inits only if `state->streaming`
- [Phase 3] Blame: `s_stream`/resume from `11c0d8fdccc56` (v5.12);
  powered `set_fmt` `mode_configure` removed by `da8f23e359166`
  (v6.18-rc1)
- [Phase 3] `git merge-base --is-ancestor da8f23e359166 HEAD` succeeded;
  `3fe797a12bfa9` also ancestor
- [Phase 3] `git show da8f23e359166`: removed `if
  (!pm_runtime_suspended) ov8865_mode_configure()` from
  `ov8865_state_configure`
- [Phase 4] `b4 dig -c 4e1446ac169a1`: v2 2/2 at
  patch.msgid.link/fa341298…; v1 added hw_mode state; Sakari objected;
  Dan proposed this design
- [Phase 4] Author reply: retested SB2 with sensor held runtime-active
- [Phase 4] `b4 dig -w`: Sakari, Dan Scally, Hans de Goede, Mauro,
  linux-media
- [Phase 4] lore/stable WebFetch: 403; mbox has no “stable”
- [Phase 5] `ov8865_set_fmt` → `ov8865_state_configure` only stores
  `state->mode`; `sensor_init` calls
  `ov8865_mode_configure(state->mode)`
- [Phase 5] `ipu-bridge.c:714` `device_link_add(...,
  DL_FLAG_PM_RUNTIME)`
- [Phase 6] Makefile/describe: 7.3.0-rc4; `VIDEO_OV8865` present
- [Phase 6] cio2: `"frame sync error"` and `"payload length is %lu,
  received %u"` in `ipu3-cio2.c`
- [Phase 8] Failure: wrong/stalled camera frames, not oops; HIGH for
  affected IPU3+ov8865 users
- UNVERIFIED: later stable@ discussion (lore 403)

The patch is a real, tested regression fix for this tree’s ov8865 + IPU3
VCM PM link path.

**YES**

 drivers/media/i2c/ov8865.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c
index 5b909a8561287..c6d53c3d55caa 100644
--- a/drivers/media/i2c/ov8865.c
+++ b/drivers/media/i2c/ov8865.c
@@ -2609,7 +2609,7 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable)
 {
 	struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);
 	struct ov8865_state *state = &sensor->state;
-	int ret;
+	int ret = 0;
 
 	if (enable) {
 		ret = pm_runtime_resume_and_get(sensor->dev);
@@ -2618,7 +2618,23 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable)
 	}
 
 	mutex_lock(&sensor->mutex);
-	ret = ov8865_sw_standby(sensor, !enable);
+
+	/*
+	 * The sensor may have been kept powered by something else (e.g. the
+	 * VCM's runtime PM device link on IPU3 platforms), in which case
+	 * runtime resume did not run and the hardware may still be
+	 * configured for a previous mode. Always program the negotiated
+	 * configuration on stream start.
+	 */
+	if (enable) {
+		ret = ov8865_sensor_init(sensor);
+		if (!ret)
+			ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
+	}
+
+	if (!ret)
+		ret = ov8865_sw_standby(sensor, !enable);
+
 	mutex_unlock(&sensor->mutex);
 
 	if (ret || !enable)
@@ -2914,15 +2930,15 @@ static int ov8865_resume(struct device *dev)
 	if (ret)
 		goto complete;
 
-	ret = ov8865_sensor_init(sensor);
-	if (ret)
-		goto error_power;
+	if (state->streaming) {
+		ret = ov8865_sensor_init(sensor);
+		if (ret)
+			goto error_power;
 
-	ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
-	if (ret)
-		goto error_power;
+		ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
+		if (ret)
+			goto error_power;
 
-	if (state->streaming) {
 		ret = ov8865_sw_standby(sensor, false);
 		if (ret)
 			goto error_power;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: cec/core: drop cec_post_state_event call
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (12 preceding siblings ...)
  2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Program the sensor on stream start Sasha Levin
@ 2026-10-19 13:52 ` Sasha Levin
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: dev_info->pr_info since dev has been freed Sasha Levin
  2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Drop the runtime PM usage count on stream failure Sasha Levin
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:52 UTC (permalink / raw)
  To: patches, stable
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Sasha Levin, hverkuil,
	mchehab, linux-media, linux-kernel

From: Hans Verkuil <hverkuil+cisco@kernel.org>

[ Upstream commit 2ff4b91e82bd76e1a6e1ff22bfc9aeda08e12a61 ]

No need to call cec_post_state_event() if the next call
is to cec_adap_unconfigure() since that will also call
cec_post_state_event().

This fixes the case when, when the physical address is
invalidated, you get two CEC_EVENT_STATE_CHANGE events:
one with a non-zero log_addr_mask and one with a zero
log_addr_mask.

You just want to see the event with phys_addr set to
f.f.f.f and log_addr_mask set to 0.

Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is **v7.3-rc4** (mainline 7.3). The extra
`cec_post_state_event()` lives in `__cec_s_phys_addr()` and is a real
UAPI-visible duplicate-event bug on HDMI unplug, not a cleanup-only
change.

## Phase 1: Commit message forensics

**Step 1.1: Subject line**
Record: **[media/cec/core] [drop] [remove redundant
`cec_post_state_event()` before `cec_adap_unconfigure()`]**

**Step 1.2: Tags**
Record:
- Signed-off-by: Hans Verkuil \<hverkuil+cisco@kernel.org\> (CEC
  maintainer / author)
- Signed-off-by: Mauro Carvalho Chehab \<mchehab+huawei@kernel.org\>
  (media maintainer)
- No Fixes:, Reported-by, Tested-by, Reviewed-by, Acked-by, Link:, or
  Cc: stable (absence of Fixes:/Cc: stable is expected for this review)

**Step 1.3: Body**
Record:
- **Bug:** When the CEC physical address is invalidated, userspace gets
  two `CEC_EVENT_STATE_CHANGE` events: one with a non-zero
  `log_addr_mask`, then one with zero.
- **Symptom:** Extra/inconsistent state-change event. Desired event is
  `phys_addr = f.f.f.f` and `log_addr_mask = 0`.
- **Root cause:** `__cec_s_phys_addr()` posts a state event, then
  immediately calls `cec_adap_unconfigure()`, which posts another after
  clearing `log_addr_mask`.
- **Version info:** none in the message. The double-post has been in
  `__cec_s_phys_addr()` since the original CEC adapter (2016).

**Step 1.4: Hidden bug fix?**
Record: **Not hidden.** The first sentence sounds like cleanup, but the
body describes a real userspace-visible duplicate event. Confirmed by
the UAPI docs: `log_addr_mask` must be 0 if `phys_addr` is
`CEC_PHYS_ADDR_INVALID`. The first event violates that.

## Phase 2: Diff analysis

**Step 2.1: Inventory**
Record:
- File: `drivers/media/cec/core/cec-adap.c` (−1 line)
- Function: `__cec_s_phys_addr()`
- Scope: single-file, one-line surgical deletion

**Step 2.2: Code flow**
Record:
- **Before:** On PA change/invalidation (`becomes_invalid ||
  !is_invalid`): set `adap->phys_addr = CEC_PHYS_ADDR_INVALID`, **post
  STATE_CHANGE** (mask still old/non-zero), then
  `cec_adap_unconfigure()` which zeros `log_addr_mask` and posts again.
- **After:** Same path, but only `cec_adap_unconfigure()` posts.
  Userspace sees one event with invalid PA and mask 0.
- Path: HDMI unplug / HPD low / `CEC_ADAP_S_PHYS_ADDR` with
  `CEC_PHYS_ADDR_INVALID` / notifier invalidation. Not an error path.

**Step 2.3: Bug mechanism**
Record: **Logic / userspace-event correctness.** Redundant notification
posted before logical addresses were cleared. First event contradicts
the documented invariant. `cec_adap_unconfigure()` already posts the
correct event (verified at line 1426).

**Step 2.4: Fix quality**
Record: Obviously correct. `cec_adap_unconfigure()` still posts after
clearing the mask. No API/data-structure change. Regression risk is very
low: anyone depending on the intermediate non-zero mask with invalid PA
would be depending on a documented-impossible state.

## Phase 3: Git history

**Step 3.1: Blame**
Record: The extra `cec_post_state_event()` before
`cec_adap_unconfigure()` is from **9881fe0ca187c2** (“[media] cec: add
HDMI CEC framework (adapter)”, 2016-06-28). Present since CEC was
introduced.

**Step 3.2: Fixes: tag**
Record: None. The double-post is original 2016 code. It became much more
visible after **67d9598720159** (“handle core events like normal
events”, 2026-07-17), which raised the STATE_CHANGE queue from 1 to 3 so
the first event is no longer overwritten.

**Step 3.3: Related file history**
Record: Same-day series (Hans Verkuil, 2026-07-10, merged 2026-07-17):
1. `e6dcc43e5174d` max_retries → max_attempts (rename)
2. `0c138a5d5045f` drop ABORTED/TIMEOUT check
3. `67d9598720159` handle core events like normal events (**makes
   duplicate visible**)
4. `2ff4b91e82bd7` **this commit**
5. `350308a05f7dd` flush stale STATE_CHANGE events (related,
   independent)
6–8. new UAPI flag, pin toggle, debugfs (features)

This patch is 4/8. It is self-contained: it only deletes a call that has
existed since 2016.

**Step 3.4: Author**
Record: Hans Verkuil is the CEC subsystem maintainer and original author
of this function. High confidence in the diagnosis.

**Step 3.5: Prerequisites**
Record: Applies standalone (one-line delete). **67d9598720159 is in this
tree** (`git merge-base --is-ancestor` succeeded), so the duplicate is
actually delivered here. Follow-up `350308a05f7dd` is not required for
this fix.

## Phase 4: Mailing list / external research

**Step 4.1: Original discussion**
Record:
- `b4 dig -c 2ff4b91e82bd7` → https://patch.msgid.link/cc357768324be21b0
  133799326e8230face817ad.1783681656.git.hverkuil+cisco@kernel.org
- Cover: `[PATCH 0/8] media: cec/core: fixes and improvements`
- `b4 dig -a`: **v1 only**, no later revisions
- Thread (mbox) contains only Hans’s 8 patches. **No replies, no NAKs,
  no reviewer Cc: stable.**
- Cover letter: mixed “fixes and improvements”; this patch’s body is a
  concrete event bug, not a feature.

**Step 4.2: Recipients**
Record: `b4 dig -w`: Hans Verkuil + linux-media@vger.kernel.org. Merged
by Mauro Chehab. No external reviewer tags.

**Step 4.3: Bug report**
Record: No Reported-by / Link / bugzilla / syzbot. Author-found while
changing event queuing.

**Step 4.4: Series**
Record: 8-patch series. Patches 6–8 add a UAPI flag and debugfs (not
needed here). Patch 3 is in this tree and is why two STATE_CHANGE events
are queued. Patch 5 flushes older queued events on invalid PA;
complementary, not a prerequisite.

**Step 4.5: Stable list**
Record: lore.kernel.org returned HTTP 403 via WebFetch/curl.
**UNVERIFIED** whether this was discussed on stable@. No Cc: stable in
the commit or mbox.

## Phase 5: Code semantic analysis

**Step 5.1: Functions**
Record: `__cec_s_phys_addr()` (modified). Helpers involved:
`cec_post_state_event()`, `cec_adap_unconfigure()`, `cec_s_phys_addr()`.

**Step 5.2: Callers**
Record:
- `cec_s_phys_addr()` — exported; HDMI drivers/notifiers (DRM HDMI
  helper, DP CEC, Pulse8, Extron, adv76xx, tc358743, sun4i, omap,
  ch7322, vivid, …)
- `__cec_s_phys_addr()` also from `cec-api.c` (`CEC_ADAP_S_PHYS_ADDR`)
  and `cec-core.c` (unregister)
- `cec-notifier.c` on HDMI HPD/EDID PA updates

Reachable from ioctl and from HDMI hotplug.

**Step 5.3: Callees**
Record: Sets `adap->phys_addr`, `cec_adap_unconfigure()` (clears mask,
flush, **posts event**), `cec_adap_enable()`, `cec_claim_log_addrs()`.
Called with `adap->lock` held.

**Step 5.4: Call chain / reachability**
Record: Userspace-reachable. Common trigger: HDMI unplug →
notifier/driver sets PA invalid → `__cec_s_phys_addr()`. Also
`CEC_ADAP_S_PHYS_ADDR`. `cec_dqevent()` takes only `fh->lock`, not
`adap->lock`, so a waiter can dequeue the first (bad) event before
unconfigure posts the second.

**Step 5.5: Similar patterns**
Record: Other `cec_post_state_event()` sites (unconfigure, config-
complete, `cec_s_conn_info`) post once after state is consistent. Only
this site posted before clearing the mask. Follow-up `350308a05f7dd`
flushes stale STATE_CHANGE events when PA becomes invalid.

## Phase 6: This tree

**Step 6.1: Does the buggy code exist?**
Record: **Yes.** Tree is **v7.3-rc4** (`7.3.0-rc4`).
`__cec_s_phys_addr()` and the extra post exist in this lineage since
2016. Parent **67d9598720159 is an ancestor of HEAD**, so the
STATE_CHANGE queue depth is 3 and both events are delivered. Bug
introduced in 2016; user-visible duplicate made systematic in 7.3.

**Step 6.2: Backport difficulty**
Record: Clean apply. Surrounding function matches the pre-image. One-
line deletion, no conflicts expected.

**Step 6.3: Related fixes already here**
Record: `350308a05f7dd` (flush stale events) is already in this tree as
the next series patch. It does not replace this deletion; it handles
previously queued events. No alternate fix for the double-post.

## Phase 7: Subsystem context

**Step 7.1:**
Record: **media/CEC core**. Criticality: **IMPORTANT** for HDMI-CEC
users (TVs, Android TV, STBs, desktops with HDMI CEC). Not mm/fs/net
core, but the CEC device node is the userspace ABI for that class of
hardware.

**Step 7.2:**
Record: Active. Multiple CEC core commits in 7.3 from the maintainer.
This file is mature (2016) with ongoing event/config fixes.

## Phase 8: Impact and risk

**Step 8.1: Who is affected**
Record: Driver/config-specific: `CONFIG_CEC_CORE` and a CEC adapter (DRM
HDMI, USB CEC dongles, SoC CEC). Userspace that dequeues
`CEC_EVENT_STATE_CHANGE` (libcec, v4l-utils, Android CEC HAL).

**Step 8.2: Trigger**
Record: HDMI unplug / HPD low / invalidating the physical address.
Common for CEC users. Unprivileged userspace with a CEC fd can also set
PA via ioctl if `CEC_CAP_PHYS_ADDR` is set. Timing: the two posts are
consecutive in one lock section, but `cec_dqevent()` does not take
`adap->lock`, so a blocked waiter can observe the first event.

**Step 8.3: Failure mode**
Record: Userspace sees a STATE_CHANGE with `phys_addr = f.f.f.f` and
**non-zero** `log_addr_mask`, which the UAPI docs forbid, then a second
correct event. Can confuse adapters as still configured after
disconnect. **Severity: MEDIUM** (incorrect userspace event / UAPI
invariant break; not a kernel oops, leak, or corruption).

**Step 8.4: Risk-benefit**
Record:
- **Benefit:** Medium. Stops a documented-impossible event on a common
  HDMI path in this 7.3 tree, where queue depth is 3.
- **Risk:** Very low. One-line delete; unconfigure still posts the
  correct event.
- **Ratio:** Favorable.

## Phase 9: Synthesis

**Step 9.1: Evidence**

FOR:
- Real userspace bug: two STATE_CHANGE events, first with invalid PA and
  non-zero mask
- Violates documented UAPI (`log_addr_mask` must be 0 if PA is invalid)
- HDMI unplug / PA invalidation is a common path
- This tree has 67d9598720159, so both events are queued (not coalesced)
- 1-line deletion, obviously correct
- `cec_adap_unconfigure()` already posts the right event
- Author is the CEC maintainer; media maintainer merged it
- Applies cleanly here; no new API

AGAINST:
- Not a kernel crash, UAF, deadlock, or security issue
- No Reported-by / syzbot / user bug report
- Patch 4/8 in a mixed “fixes and improvements” series
- No mailing-list review comments beyond submission
- Severity is MEDIUM (wrong event), not CRITICAL

UNRESOLVED:
- lore.kernel.org HTTP 403; stable@ discussion not independently
  confirmed (no Cc: stable in the mbox)

**Step 9.2: Stable rules checklist**
1. Obviously correct and tested? **PASS** — one redundant call removed;
   unconfigure still notifies. Maintainer-authored, merged to media
   tree.
2. Real bug affecting users? **PASS** — duplicate/inconsistent CEC event
   on PA invalidation; userspace that trusts the UAPI invariant can mis-
   handle HDMI disconnect.
3. Important issue? **PASS** (medium) — not oops/corruption, but a
   userspace ABI invariant break on a common hotplug path. In this tree
   it is systematic because STATE_CHANGE is no longer a single-slot core
   event.
4. Small and contained? **PASS** — −1 line, one function.
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — code and prerequisite
   67d9598720159 are present; hunk matches.

**Step 9.3: Exception category**
Record: None (not a device ID, quirk, DT, build, or docs fix). Qualifies
as a normal small bugfix.

**Step 9.4: Decision**
This tree is 7.3-rc4. The buggy double-post is in this lineage, and
67d9598720159 is here, so userspace actually receives the illegal first
event. The fix is a one-line deletion with essentially no regression
risk. That is appropriate to carry on this tree.

## What the commit solves for this tree

`__cec_s_phys_addr()` used to notify userspace **before** logical
addresses were cleared, then `cec_adap_unconfigure()` notified again.
After 67d9598720159 (in this tree), both events are queued. On HDMI
unplug, apps can see `phys_addr = f.f.f.f` with a non-zero
`log_addr_mask`, which the CEC UAPI says cannot happen. Dropping the
first post leaves a single correct event.

## Risk vs benefit

Benefit is correct CEC state on disconnect for every CEC userspace
client in 7.3. Risk is a one-line delete of a notification that is
immediately superseded. No locking, allocation, or ABI change.

## Concerns

- Importance is medium, not a kernel crash. Still a real ABI bug on a
  common path, with a trivial fix.
- Series patches 6–8 are unrelated features and must not be pulled with
  this.
- Patch 5 (flush stale events) is complementary, not required for this
  deletion to be correct.

## Verification
- [Phase 1] Parsed tags: author Hans Verkuil, SOB Mauro Chehab; no
  Fixes:/Reported-by/Cc: stable
- [Phase 1] UAPI docs in `cec-ioc-dqevent.rst`: `log_addr_mask` is 0 if
  `phys_addr` is `CEC_PHYS_ADDR_INVALID`
- [Phase 2] Diff: −1 line in `__cec_s_phys_addr()`;
  `cec_adap_unconfigure()` still calls `cec_post_state_event()` at line
  1426
- [Phase 3] `git describe HEAD` / Makefile: v7.3-rc4, VERSION=7
  PATCHLEVEL=3 SUBLEVEL=0 EXTRAVERSION=-rc4
- [Phase 3] `git blame` on pre-fix file: extra call from 9881fe0ca187c2
  (2016 CEC adapter)
- [Phase 3] `git show 9881fe0ca187c2`: original `__cec_s_phys_addr`
  already had post-then-unconfigure
- [Phase 3] `git merge-base --is-ancestor 2ff4b91e82bd7 HEAD` and
  `67d9598720159 HEAD`: both ancestors
- [Phase 3] `git show 67d9598720159`: STATE_CHANGE `max_events` 1→3;
  core-event overwrite removed
- [Phase 3] Series around the commit: 8 patches; this is 4/8; 5/8 is
  flush-stale, independent
- [Phase 4] `b4 dig -c 2ff4b91e82bd7`: lore URL found; v1 only; linux-
  media only; no replies in mbox
- [Phase 4] Cover letter: “fixes and improvements”; this patch body is
  the duplicate-event fix
- [Phase 4] lore.kernel.org WebFetch/curl: 403 — stable@ discussion
  UNVERIFIED
- [Phase 5] Callers: `cec_s_phys_addr`, ioctl, notifier, HDMI
  DRM/USB/platform drivers
- [Phase 5] `cec_dqevent()` uses only `fh->lock`; can dequeue between
  the two posts
- [Phase 6] Current `__cec_s_phys_addr` in this checkout already lacks
  the extra call (fix present in 7.3-rc4 lineage); pre-image still
  matches for a clean apply
- [Phase 8] Failure mode: inconsistent CEC_EVENT_STATE_CHANGE, severity
  MEDIUM, trigger HDMI PA invalidation

**YES**

 drivers/media/cec/core/cec-adap.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
index 84eaf9780db25..4d2262530c94a 100644
--- a/drivers/media/cec/core/cec-adap.c
+++ b/drivers/media/cec/core/cec-adap.c
@@ -1708,7 +1708,6 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
 		cec_phys_addr_exp(phys_addr));
 	if (becomes_invalid || !is_invalid) {
 		adap->phys_addr = CEC_PHYS_ADDR_INVALID;
-		cec_post_state_event(adap);
 		cec_adap_unconfigure(adap);
 		if (becomes_invalid) {
 			cec_adap_enable(adap);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] media: em28xx: dev_info->pr_info since dev has been freed
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (13 preceding siblings ...)
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] media: cec/core: drop cec_post_state_event call Sasha Levin
@ 2026-10-19 13:52 ` Sasha Levin
  2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Drop the runtime PM usage count on stream failure Sasha Levin
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:52 UTC (permalink / raw)
  To: patches, stable
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Sasha Levin, mchehab,
	linux-media, linux-kernel

From: Hans Verkuil <hverkuil+cisco@kernel.org>

[ Upstream commit c132b07f7e5853c0df35a9b94b8e204cdc6afdef ]

In em28xx_free_device() dev_info passed &dev->intf->dev,
but that device can be freed already.

Just use pr_info instead.

Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This is a one-line use-after-free fix in a USB disconnect/teardown path.
The local tree is mainline **v7.3-rc4** (`7.3.0-rc4`); the driver and
the delayed-free path are present, and the change is independently
correct.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

**Step 1.1: PARSE THE SUBJECT LINE**
- Subsystem: `media: em28xx`
- Action verb: implicit fix (`dev_info->pr_info since dev has been
  freed`)
- Claimed intent: stop logging through a USB `struct device` that may
  already have been freed.

Record: **[media/em28xx] [replace logging helper] [do not use freed USB
device in em28xx_free_device()]**

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- No `Fixes:` tag (expected for this review)
- No `Reported-by:` / syzbot
- `Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>` — author tested
  on real hardware
- No `Reviewed-by:` / `Acked-by:` on the committed message
- No `Link:`
- No `Cc: stable@vger.kernel.org` (expected)
- `Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>` (author;
  V4L2 maintainer)
- `Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>`
  (media maintainer)

Record: **Author+media maintainer SOBs; Tested-by from author; no
Fixes/Cc stable (not a negative).**

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Body: `em28xx_free_device()` passed `&dev->intf->dev` to `dev_info`, but
that USB interface device can already be gone. Replace with `pr_info`
using `dev->name`.

Record:
- Bug: use of `dev->intf->dev` after the USB interface may have been
  freed
- Symptom: kernel UAF / oops while printing “Freeing device”
- Version info: none in the message; history shows the log line since
  v4.10
- Root cause: delayed `kref_put` after USB disconnect tears down `intf`

**Step 1.4: DETECT HIDDEN BUG FIXES**
Not hidden. Cover letter for the series says explicitly: “The fifth
patch fixes a use-after-freed”.

Record: **[Explicit UAF fix, not cleanup]**

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

**Step 2.1: INVENTORY THE CHANGES**
- File: `drivers/media/usb/em28xx/em28xx-cards.c` (1 insertion, 1
  deletion)
- Function: `em28xx_free_device()`
- Scope: single-file surgical fix

Record: **[em28xx-cards.c ±1] [em28xx_free_device] [surgical]**

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Before:
```
dev_info(&dev->intf->dev, "Freeing device\n");
```
After:
```
pr_info("%s: Freeing device\n", dev->name);
```

This runs at the start of the kref release callback, **before**
`kfree(dev)`. `dev->name` is an embedded `unsigned char name[32]` in
`struct em28xx`, still valid. `&dev->intf->dev` is not, if USB core
already dropped the interface.

Record: **[dev_info on possibly-freed usb_interface -> pr_info on still-
live em28xx::name]**

**Step 2.3: IDENTIFY THE BUG MECHANISM**
Category: **memory safety / use-after-free**.

Call path (verified in this tree):
1. `em28xx_usb_disconnect()` sets `dev->disconnected = 1`, calls
   `em28xx_close_extension()`, then `em28xx_release_resources()`
   (`usb_put_dev`), then `kref_put(&dev->ref, em28xx_free_device)`.
2. Extensions hold extra refs. Audio PCM close still does `kref_put`
   (`em28xx-audio.c`); v4l2 defers the last `kref_put` until
   `em28xx_free_v4l2()` after the last userspace close.
3. If a capture/audio handle is still open at unplug, the last
   `kref_put` happens **after** USB `disconnect()` returns. USB core
   then unregisters/frees `usb_interface`. `dev->intf` is dangling.
4. `dev_info(&dev->intf->dev, ...)` dereferences that freed `struct
   device`.

This delayed-free path is not new: even before the 2026 v4l2-release-
callback series, open/close took `kref_get`/`kref_put` on `dev->ref`, so
the last put could already run after unplug.

Record: **[UAF] [printk through freed usb_interface after delayed kref
release]**

**Step 2.4: ASSESS THE FIX QUALITY**
Obviously correct: stop touching `intf` once it may be gone; log via a
field inside `dev` that has not been freed yet. No API change.
Regression risk is negligible (log prefix loses the kernel device name;
`dev->name` is set in probe via `snprintf`).

Record: **[minimal, correct] [regression risk very low]**

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

**Step 3.1: BLAME THE CHANGED LINES**
Buggy `dev_info` line: `29b05e22f5c68c` (“[media] em28xx: use
usb_interface for dev_foo() calls”, Mauro, 2016-12-07). `git describe`
on that commit: `v4.9-rc6-495-g29b05e22f5c68`; `git describe
--contains`: `v4.10-rc1~71^2^2~4`. `em28xx_free_device()` itself is from
`47677e51e2a404` (2014).

Record: **[29b05e22f5c68c, first in v4.10] [long-standing]**

**Step 3.2: FOLLOW THE FIXES: TAG**
No `Fixes:` tag.

Record: **[N/A — no Fixes tag; introducing commit identified via
blame]**

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
This commit is **patch 5/6** of Hans Verkuil’s “media: em28xx: fix
lifecycle issues” series (v2, 2026-06-16), applied next to:
- `288254383674b` use v4l2_device release callback
- `de626073dfcbb` drop `users` field
- `7c8bf63b79371` use `vb2_video_unregister_device` (immediate parent)
- `67f87b104f4ef` requeue buffers if start_streaming fails

Those other patches are lifetime/refactor/WARN_ON work. **This hunk does
not use any of that new machinery**; it only edits a log line that has
existed since 2016.

Record: **[part of a series, but this patch is standalone]**

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Hans Verkuil is the V4L2 maintainer; Mauro is listed as em28xx
maintainer in `MAINTAINERS`. Cover letter: tested on Hans’s em28xx
device.

Record: **[subsystem maintainer-level author; related lifecycle series
exists but is not a hard dep]**

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
The replacement uses existing `pr_info` and `dev->name`. No new helpers.
Applies on the pre-series `em28xx_free_device()` as well.

Record: **[no prerequisites] [can apply standalone]**

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
`b4 dig -c c132b07f7e585` → https://patch.msgid.link/4f25383b64139feb0a6
4a07c20b1776d13301f9c.1781615432.git.hverkuil+cisco@kernel.org

`b4 dig -a`:
- v1: 3-patch series (2026-05-19), this change was not in v1
- v2: `[PATCHv2 0/6] media: em28xx: fix lifecycle issues` (2026-06-16) —
  this is 5/6

Cover letter (from saved mbox): “The fifth patch fixes a use-after-
freed”. No NAK on 5/6. Review discussion in the matched thread was about
1/6 (`v4l2-async`), not this patch.

Record: **[lore/msgid above] [v1 then v2/6] [no NAK on this patch]
[author described it as UAF]**

**Step 4.2: CHECK WHO REVIEWED THE PATCH**
`b4 dig -w`: Hans Verkuil; `linux-media@vger.kernel.org`; Mauricio Faria
de Oliveira; Sakari Ailus. Sakari reviewed 1/6 only. Mauro applied it.

Record: **[media list + Sakari on a different patch; Mauro merged]**

**Step 4.3: SEARCH FOR THE BUG REPORT**
No syzbot/bugzilla for this specific log-line UAF. Author found it while
fixing em28xx lifecycle and tested on hardware.

Record: **[no public crash report; maintainer-found UAF]**

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Series mates are separate bugs (v4l2-async crash, lifetime refactor, vb2
unregister, start_streaming WARN_ON). Not required for this one-liner.

Record: **[standalone among the 6]**

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
lore.kernel.org/stable search was blocked (Anubis bot challenge). No
stable discussion in the saved media thread.

Record: **[UNVERIFIED: no stable@ thread retrieved]**

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

**Step 5.1: IDENTIFY KEY FUNCTIONS**
`em28xx_free_device()` (exported `EXPORT_SYMBOL_GPL`).

**Step 5.2: TRACE CALLERS**
`kref_put(&dev->ref, em28xx_free_device)` from:
- `em28xx_usb_disconnect()` (`em28xx-cards.c`)
- `em28xx_free_v4l2()` (`em28xx-video.c`) — after last v4l2 user
- `em28xx_audio_fini()` and PCM close (`em28xx-audio.c`)
- `em28xx_dvb` fini (`em28xx-dvb.c`)
- `em28xx-input.c` fini

The dangerous caller is a **late** `kref_put` after USB disconnect has
returned.

**Step 5.3: TRACE CALLEES**
`kref_to_dev`, `pr_info`, optional `em28xx_release_resources()` only if
`!dev->disconnected` (that path still has a live interface), `kfree`.

**Step 5.4: FOLLOW THE CALL CHAIN**
Userspace-reachable: unplug an em28xx USB capture stick while v4l2/ALSA
still has it open, then close the app. Common physical-unplug path, not
an obscure config.

Record: **[reachable from USB unplug + close] [yes, from
userspace/device removal]**

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Many other `dev_info(&dev->intf->dev, ...)` calls exist, but they run
while the interface is still bound (probe, streaming, disconnect
itself). The unique one in the post-disconnect free callback was this
“Freeing device” line.

Record: **[only this log site in the free callback]**

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Local tree: `v7.3-rc4-27-gf0100363d8c37`, `VERSION=7 PATCHLEVEL=3
SUBLEVEL=0 EXTRAVERSION=-rc4`.

`git merge-base --is-ancestor c132b07f7e585 HEAD` → yes. Current source
already has `pr_info("%s: Freeing device\n", dev->name);`.

The **bug** existed here before that commit; the **buggy pattern**
(`em28xx_free_device` + `dev->intf` + delayed kref) is still the
lifetime model. For any stable tree that branched with the 2016
`dev_info` line and without this commit, the bug is present.

Record: **[driver present; fix already in this mainline checkout; bug
introduced v4.10]**

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Hunk is one line in a function whose shape has been stable since 2014.
Would apply cleanly to trees still using `dev_info`.

Record: **[clean apply on pre-fix trees / already applied here]**

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
This is the fix. No earlier alternate fix of this log site.

Record: **[no other fix of this UAF]**

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

**Step 7.1: SUBSYSTEM AND CRITICALITY**
`drivers/media/usb/em28xx/` — USB analog/DVB capture (Hauppauge,
Terratec, etc.).

Record: **[media USB driver] [IMPORTANT / driver-specific, not
staging]**

**Step 7.2: SUBSYSTEM ACTIVITY**
Actively maintained (IDs, lifecycle, syzbot list-corruption fixes in the
same files). Mature driver, bug is old.

Record: **[mature, still active]**

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

**Step 8.1: WHO IS AFFECTED**
Users of em28xx USB sticks (`CONFIG_VIDEO_EM28XX`). Not universal, but
real consumer hardware.

**Step 8.2: TRIGGER CONDITIONS**
Unplug (or USB reset) while a v4l2/ALSA/DVB client still holds the
device, then close. Timing-dependent on refcount, but the window is the
entire time the app stays open after unplug — not a one-instruction
race.

Unprivileged users can trigger it by unplugging hardware.

**Step 8.3: FAILURE MODE SEVERITY**
`dev_info()` → `dev_printk()` walks a freed `struct device`. UAF: oops /
KASAN report, possible panic. Not data corruption, but a real crash on a
common unplug path.

Record: **[UAF oops] [HIGH]**

**Step 8.4: RISK-BENEFIT RATIO**
- Benefit: prevent oops on device removal for em28xx users
- Risk: 1-line log change, no locking/API/lifetime change

Record: **[high benefit for those devices] [very low risk] [favorable]**

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

**Step 9.1: COMPILE THE EVIDENCE**

FOR:
- Confirmed UAF: delayed `em28xx_free_device()` after USB interface
  teardown
- Cover letter calls it a use-after-free
- One-line, obviously correct
- Tested by V4L2 maintainer on real em28xx hardware; merged by Mauro
- Bug in code since v4.10; delayed kref existed long before the 2026
  series
- No new API/feature
- Standalone; other series patches not required

AGAINST:
- No `Fixes:` / `Cc: stable` / syzbot (not a reason to reject)
- Driver-specific, not core mm/net
- This mainline checkout already contains the commit (expected for a
  mainline candidate)
- UNVERIFIED: stable@ mailing list history (lore bot-blocked)

**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — one-line; Tested-by Hans;
   cover letter explains UAF
2. Fixes a real bug that affects users? **PASS** — UAF on unplug-while-
   open
3. Important issue? **PASS** — UAF oops, HIGH (not theoretical)
4. Small and contained? **PASS** — 1 line, one function
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — surrounding
   `em28xx_free_device()` matches; trees that still have `dev_info` get
   a clean apply. This checkout already has the after-state because it
   *is* mainline including the fix.

**Step 9.3: EXCEPTION CATEGORIES**
Not a device-ID/quirk/DT/build/doc exception. It is a normal memory-
safety fix.

**Step 9.4: DECISION**
This should be backported. It is a small, tested UAF fix in a teardown
path users hit when they unplug a capture device. It does not depend on
the rest of the lifecycle series.

What it solves for stable users: kernel oops from
`dev_info(&dev->intf->dev)` after USB core has freed the interface, when
the last em28xx kref is dropped from v4l2/audio close. Risk is
essentially zero.

Verification:
- [Phase 1] Parsed tags: Tested-by Hans Verkuil; SOBs Hans + Mauro; no
  Fixes/Cc stable/Reported-by
- [Phase 1] Cover letter (mbox): “The fifth patch fixes a use-after-
  freed”
- [Phase 2] Diff: 1 line in `em28xx_free_device()`;
  `dev_info(&dev->intf->dev)` → `pr_info("%s: ...", dev->name)`
- [Phase 2] Call path: `em28xx_usb_disconnect` → `kref_put`; extra puts
  from `em28xx_free_v4l2`, audio PCM close (`kref_put` at em28xx-
  audio.c:312)
- [Phase 3] git blame parent: `29b05e22f5c68c` (v4.10) introduced
  `dev_info`; `git merge-base --is-ancestor 29b05e22f5c68c HEAD` true
- [Phase 3] No Fixes tag; standalone vs series confirmed by reading
  `288254383674b` (does not change this log line)
- [Phase 3] `git merge-base --is-ancestor c132b07f7e585 HEAD` true
  (original commit is in this mainline tree)
- [Phase 4] `b4 dig -c c132b07f7e585`: msgid 4f25383b64139feb… ; v2 5/6
  of lifecycle series
- [Phase 4] `b4 dig -a`: v1 (3 patches) then v2 (6 patches); this UAF
  patch added in v2
- [Phase 4] `b4 dig -w`: linux-media, Sakari Ailus, Mauricio Faria de
  Oliveira
- [Phase 4] mbox: no NAK on 5/6; Sakari comments only on 1/6
- [Phase 4] lore WebFetch 403; stable search Anubis-blocked — UNVERIFIED
  stable@ discussion
- [Phase 5] Callers of `em28xx_free_device` enumerated via grep of
  `kref_put`
- [Phase 5] `dev->name` is `unsigned char name[32]` in `struct em28xx`;
  set in probe (`snprintf(dev->name, 28, "em28xx")`)
- [Phase 6] `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
  kernelversion` = `7.3.0-rc4`
- [Phase 6] Current file already has `pr_info` (fix present in this
  checkout)
- [Phase 7] MAINTAINERS: EM28XX VIDEO4LINUX DRIVER, Mauro Chehab
- [Phase 8] Failure mode: UAF in `dev_printk` on freed `usb_interface` →
  oops; trigger = unplug while open
- UNVERIFIED: whether a dedicated stable@ thread exists (lore bot)

**YES**

 drivers/media/usb/em28xx/em28xx-cards.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index b8e207443770e..af2c06a05084d 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -3556,7 +3556,7 @@ void em28xx_free_device(struct kref *ref)
 {
 	struct em28xx *dev = kref_to_dev(ref);
 
-	dev_info(&dev->intf->dev, "Freeing device\n");
+	pr_info("%s: Freeing device\n", dev->name);
 
 	if (!dev->disconnected)
 		em28xx_release_resources(dev);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Drop the runtime PM usage count on stream failure
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (14 preceding siblings ...)
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: dev_info->pr_info since dev has been freed Sasha Levin
@ 2026-10-19 13:53 ` Sasha Levin
  15 siblings, 0 replies; 16+ messages in thread
From: Sasha Levin @ 2026-10-19 13:53 UTC (permalink / raw)
  To: patches, stable
  Cc: Jurison Murati, Daniel Scally, Sakari Ailus, Sasha Levin, mchehab,
	linux-media, linux-kernel

From: Jurison Murati <eng.juri@gmail.com>

[ Upstream commit 3fe797a12bfa9a49aa998ee722e5f25c957b9b15 ]

ov8865_s_stream() takes a runtime PM reference when enabling the
stream, but returns without releasing it if ov8865_sw_standby()
fails, leaving the reference unbalanced and the sensor powered
indefinitely. The same applies to a failure while disabling the
stream, in which case the reference acquired at stream start is
never dropped.

Drop the reference in a single place, both when disabling the
stream and on failure, and only update the streaming state on
success.

Signed-off-by: Jurison Murati <eng.juri@gmail.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
driver and the unbalanced RPM `s_stream` path exist here; this is a
real, small resource-leak fix that belongs in this tree.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[media/i2c/ov8865] [Drop] Drop the runtime PM usage count on
stream failure.** “Drop” here is a leak fix: release a held RPM
reference, not a feature removal.

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Signed-off-by:** Jurison Murati `<eng.juri@gmail.com>` (author)
- **Reviewed-by:** Daniel Scally `<dan.scally@ideasonboard.com>`
- **Signed-off-by:** Sakari Ailus `<sakari.ailus@linux.intel.com>`
  (media I2C maintainer; applied the patch)
- **No Fixes:** (expected for this review)
- **No Cc: stable** (expected)
- **No Reported-by / Tested-by / Link / Acked-by**
- Ignore any pipeline-added Sasha Levin SOB / `[Upstream commit]`
  markers (none in the real commit)

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `ov8865_s_stream()` calls `pm_runtime_resume_and_get()` on
  stream-on, then returns early if `ov8865_sw_standby()` fails, without
  `pm_runtime_put()`.
- **Symptom:** RPM usage count stays elevated; the sensor stays powered
  indefinitely. Same leak on failed stream-off (the get from stream-on
  is never dropped).
- **Root cause:** error returns skip the put that is only done on
  successful stream-off.
- **Fix:** put on `ret || !enable`; only set `state->streaming` on
  success; return the real `ret`.
- **Version info in the message:** none.

**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not hidden.** It is an explicit RPM reference-count leak fix
(error-path resource leak).

---

## PHASE 2: DIFF ANALYSIS

**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/media/i2c/ov8865.c` — **+5 / −7** (12 lines
  touched)
- **Function:** `ov8865_s_stream()` only
- **Scope:** single-file, surgical

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Before (parent of `3fe797a12bfa9`):

```c
if (enable) {
    ret = pm_runtime_resume_and_get(sensor->dev);
    if (ret < 0)
        return ret;
}
mutex_lock(&sensor->mutex);
ret = ov8865_sw_standby(sensor, !enable);
mutex_unlock(&sensor->mutex);
if (ret)
    return ret;                 /* leak: no put */
state->streaming = !!enable;
if (!enable)
    pm_runtime_put(sensor->dev);
return 0;
```

After:

```c
if (ret || !enable)
    pm_runtime_put(sensor->dev);
if (!ret)
    state->streaming = enable;
return ret;
```

Record:
- Stream-on success: no put, `streaming = 1` (unchanged).
- Stream-on failure: **put** (was leaked).
- Stream-off success: put, `streaming = 0` (unchanged).
- Stream-off failure: **put** (was leaked); `streaming` left unchanged.

**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Error path / resource leak — runtime PM usage count]**
`pm_runtime_resume_and_get()` increments the usage count.
`ov8865_sw_standby()` is a single I2C write and can fail. Early `return
ret` skipped the matching `pm_runtime_put()`.

**Step 2.4: ASSESS THE FIX QUALITY**
Record: **Obviously correct and minimal.** Same pattern suggested by
Sakari Ailus on v1 and used by sibling OmniVision drivers (e.g.
`ov8856_set_stream()`).
**Regression risk: very low.**

Verified against `call_s_stream()` in this tree:

```475:503:drivers/media/v4l2-core/v4l2-subdev.c
static int call_s_stream(struct v4l2_subdev *sd, int enable)
{
        ...
        if (WARN_ON(sd->s_stream_enabled == !!enable))
                return 0;
        ret = sd->ops->video->s_stream(sd, enable);
        if (!enable && ret < 0) {
                dev_warn(sd->dev, "disabling streaming failed (%d)\n",
ret);
                ret = 0;
        }
        if (!ret)
                sd->s_stream_enabled = enable;
        ...
}
```

Disable is never retried by the core (failure is treated as success,
`s_stream_enabled` becomes 0). Enable failure keeps `s_stream_enabled ==
0`, so a retry does a fresh get. No double-put on the core path.

---

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Buggy `if (ret) return ret;` / put-only-on-success:
  **`11c0d8fdccc56`** — “media: i2c: Add support for the OV8865 image
  sensor” (2020-12-31), first in **v5.12-rc1**.
- `pm_runtime_resume_and_get()` rename: **`586ee057ba6b01`**
  (2021-04-23). The leak was already present with the original get.

**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Bug dates to driver introduction, not a later
regression.

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- This is **patch 1/2**. Follow-up **`4e1446ac169a1`** (“Program the
  sensor on stream start”) depends on this unified error handling (v2
  changelog).
- This commit is **standalone**; it does not need patch 2.
- Both are already in this 7.3-rc4 checkout via `media/v7.3-1`.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Author Jurison Murati has exactly these two ov8865 commits in
`drivers/media/i2c/`. Not the subsystem maintainer. Weight comes from
**Daniel Scally’s Reviewed-by** and **Sakari Ailus applying it**.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: **None.** Touches only `ov8865_s_stream()`, `pm_runtime_put()`,
and `state->streaming`, all present since the driver was added.

---

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore (via `b4 dig -c 3fe797a12bfa9`):
  https://patch.msgid.link/6b764b77a7d78b8ae2cfb8a213a1e844a329db26.1781
  085860.git.eng.juri@gmail.com
- **v1:** `[PATCH 2/2] Drop PM runtime reference if stream start fails`
  — put only on enable failure.
- **v2:** unified `if (ret || !enable)` as Sakari asked; also covers
  disable failure; reordered to 1/2.
- **No NAKs.** Dan Scally: “I think this is ok” + Reviewed-by on v2.
- **No Cc: stable** in the thread (`grep stable` on the saved mbox: no
  matches).

**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): Jurison Murati; **Sakari Ailus**; **Daniel
Scally**; Hans de Goede; Mauro Carvalho Chehab; **linux-
media@vger.kernel.org**. Right maintainers/lists.

**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: **No user/syzbot report** of this leak. Found by inspection
while fixing IPU3/Surface Book 2 stream-on programming (sibling patch).
Still a real, reachable leak.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 2-patch series. This patch is self-contained. Patch 2 is a
separate functional fix (program mode on stream start).

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — `lore.kernel.org/stable/` fetch returned 403.
The linux-media mbox has no stable discussion.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: **`ov8865_s_stream()`** only.

**Step 5.2: TRACE CALLERS**
Record: Registered as `.s_stream` in `ov8865_subdev_video_ops`. Invoked
from **`call_s_stream()`** / `v4l2_subdev_call(..., s_stream, ...)` when
userspace starts/stops the camera pipeline (VIDIOC_STREAMON/OFF).
**Userspace-reachable.** Not IRQ context.

**Step 5.3: TRACE CALLEES**
Record: `pm_runtime_resume_and_get()`, `ov8865_sw_standby()` →
`ov8865_write()` (I2C), `pm_runtime_put()`.

**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Camera app → V4L2 STREAMON → subdev `.s_stream(1)` → get + I2C
standby-off. Fail that I2C write → leak on old code. **Yes, reachable
from userspace** on hardware that uses this sensor
(`CONFIG_VIDEO_OV8865`).

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same class of fix exists elsewhere (`media: smiapp: Fix runtime
PM imbalance on error`, `media: s5k6a3: Fix runtime PM imbalance on
error`). `ov8856_set_stream()` already puts on start failure.

---

## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** Driver is `drivers/media/i2c/ov8865.c`. Buggy
`s_stream` was in this lineage from **v5.12** until **`3fe797a12bfa9`**.
This 7.3-rc4 tree already contains that commit (plus follow-up
`4e1446ac169a1`, which kept `if (ret || !enable) pm_runtime_put()`).

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Against the pre-fix blob, the provided diff matches **exactly**.
**Clean apply** to the buggy function. No structural prerequisites.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This *is* the RPM-leak fix in this tree. No earlier alternate
fix. Follow-up `4e1446ac169a1` is a different bug (stale mode when RPM
is pinned).

---

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **[media / i2c camera sensor] [PERIPHERAL]** — OmniVision OV8865
(`CONFIG_VIDEO_OV8865`, depends on `PM`). Real products: sibling commit
documents Surface Book 2 (IPU3 + ov8865).

**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature driver (since v5.12), occasional fixes. Not a new/staging
driver.

---

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific / config-specific** (`CONFIG_VIDEO_OV8865`).
Laptop/embedded camera users (e.g. IPU3/Surface).

**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Stream on/off when `ov8865_sw_standby()` I2C write fails. Not
every boot; **error path**. Unprivileged camera users can hit STREAMON.
Repeated failed starts **stack** usage counts on the old code.

**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **[RPM usage leak → sensor never runtime-suspends, extra power]
[HIGH for that device, not a kernel oops].** Not panic/UAF/corruption.
Persistent until reboot.

**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** medium-high for ov8865 users (device otherwise stays
  powered after a failed stream).
- **Risk:** very low (5/7 lines, error/stream-off path only, reviewed).
- **Ratio:** strongly favors applying it.

---

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: COMPILE THE EVIDENCE**

**FOR:**
- Real unbalanced `pm_runtime_resume_and_get()` / missing
  `pm_runtime_put()` on I2C failure.
- Sensor can remain runtime-active indefinitely; retries worsen the
  count.
- Tiny, obviously correct; maintainer-suggested form; Reviewed-by Daniel
  Scally; applied by Sakari Ailus.
- Bug present since v5.12; code exists in this tree.
- Standalone; no new API/feature.
- Same class as other media “runtime PM imbalance” fixes.

**AGAINST:**
- Peripheral sensor, not core mm/net/fs.
- Error path (I2C failure), no syzbot/user report of *this* leak.
- No crash/UAF/CVE.

**UNRESOLVED:**
- Could not query lore.kernel.org/stable (HTTP 403).
- WebFetch of lore HTML also 403; discussion recovered via `b4 dig -m`.

**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — reviewed, maintainer-
   applied, logic matches V4L2 `s_stream` pairing.
2. Fixes a real bug that affects users? **PASS** — RPM leak on stream
   start/stop failure.
3. Important issue? **PASS** — persistent device power / RPM imbalance
   (HIGH for this driver, not a panic).
4. Small and contained? **PASS** — one function, +5/−7.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — buggy `ov8865_s_stream()` is
   this driver’s historical code; diff matches that blob.

**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **None** (not a device ID/quirk/DT/build/doc exception). It is a
normal bugfix.

**Step 9.4: MAKE YOUR DECISION**
This is a surgical RPM reference leak fix in a driver this tree actually
ships. Benefit outweighs risk.

---

What it solves for this tree: if `ov8865_sw_standby()` fails after
`pm_runtime_resume_and_get()`, the usage count was never dropped, so the
OV8865 stayed powered. The patch puts in one place on failure and on
stream-off, and only updates `state->streaming` on success.

It meets stable rules: real leak, small, no new API, applies to this
`ov8865.c`. Risk is negligible versus leaving the sensor runtime-pinned
after a failed stream.

### Verification
- [Phase 1] Tags: author SOB Jurison Murati; Reviewed-by Daniel Scally;
  SOB Sakari Ailus; no Fixes/Cc:stable/Reported-by
- [Phase 2] Diff: `ov8865_s_stream()` only, +5/−7; put on `ret ||
  !enable`
- [Phase 2] `call_s_stream()` swallows disable errors and will not
  double-call disable (verified in `v4l2-subdev.c`)
- [Phase 3] `git blame` on parent: leak from `11c0d8fdccc56` (v5.12-rc1)
- [Phase 3] `git merge-base --is-ancestor 3fe797a12bfa9 HEAD` → in this
  tree
- [Phase 3] Follow-up `4e1446ac169a1` is a separate series patch; this
  commit is standalone
- [Phase 4] `b4 dig -c 3fe797a12bfa9` → v2 1/2 lore URL; `b4 dig -a` →
  v1 then v2; `b4 dig -w` → Sakari, Scally, Chehab, linux-media
- [Phase 4] mbox: Sakari proposed the unified put; Scally re-reviewed;
  no NAK; no “stable” string
- [Phase 4] lore.kernel.org HTML/stable search: 403 — UNVERIFIED on
  stable@ thread
- [Phase 5] Callers: V4L2 subdev `.s_stream` from STREAMON/OFF;
  `ov8865_sw_standby()` is an I2C write that can fail
- [Phase 6] `git describe HEAD` → `v7.3-rc4-27-gf0100363d8c37`; `make
  kernelversion` → 7.3.0-rc4; pre-fix function matches the candidate
  diff
- [Phase 8] Failure mode: RPM usage leak, sensor stays powered; severity
  HIGH for this device, not oops
- UNVERIFIED: whether this was already discussed on stable@ (fetch
  blocked)

**YES**

 drivers/media/i2c/ov8865.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c
index a8586df14f777..5b909a8561287 100644
--- a/drivers/media/i2c/ov8865.c
+++ b/drivers/media/i2c/ov8865.c
@@ -2621,15 +2621,13 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable)
 	ret = ov8865_sw_standby(sensor, !enable);
 	mutex_unlock(&sensor->mutex);
 
-	if (ret)
-		return ret;
-
-	state->streaming = !!enable;
-
-	if (!enable)
+	if (ret || !enable)
 		pm_runtime_put(sensor->dev);
 
-	return 0;
+	if (!ret)
+		state->streaming = enable;
+
+	return ret;
 }
 
 static const struct v4l2_subdev_video_ops ov8865_subdev_video_ops = {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-10-19 14:06 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20261019135441.1420968-1-sashal@kernel.org>
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: use vb2_video_unregister_device Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: requeue buffers if start_streaming fails Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: cec: tegra_cec: don't break off msg on NACK Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: dvb-core: fix feed leak on failed DMX_ADD_PID Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: go7007: s2250: propagate control I/O failures Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] media: ivtv: stop VBI start-code scan before short tail Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: go7007: avoid undefined shifts in MPEG-4 headers Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: cx88: fix memory leak in cx8802_register_driver() error path Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] media: cec: tegra: add missing MODULE_DEVICE_TABLE() Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] media: cec: stm32: return an error when log-address wait times out Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] media: v4l2-tpg: reduce stack usage for kasan builds Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] media: cx18: stop VBI start-code scan before short tail Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Program the sensor on stream start Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] media: cec/core: drop cec_post_state_event call Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] media: em28xx: dev_info->pr_info since dev has been freed Sasha Levin
2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-5.15] media: i2c: ov8865: Drop the runtime PM usage count on stream failure Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox